2020-05-26 06:51:06 +00:00
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/diamondburned/cchat"
|
2020-05-28 19:26:55 +00:00
|
|
|
"github.com/diamondburned/cchat-gtk/internal/ui/primitives"
|
2020-06-04 23:00:41 +00:00
|
|
|
"github.com/diamondburned/cchat-gtk/internal/ui/rich"
|
2020-05-26 06:51:06 +00:00
|
|
|
"github.com/diamondburned/cchat-gtk/internal/ui/service/session"
|
2020-06-04 23:00:41 +00:00
|
|
|
"github.com/diamondburned/cchat/text"
|
2020-05-26 06:51:06 +00:00
|
|
|
"github.com/gotk3/gotk3/gtk"
|
|
|
|
)
|
|
|
|
|
2020-06-04 23:00:41 +00:00
|
|
|
const IconSize = 32
|
|
|
|
|
|
|
|
type Controller interface {
|
|
|
|
session.Controller
|
|
|
|
AuthenticateSession(*Container, cchat.Service)
|
|
|
|
}
|
|
|
|
|
2020-05-26 06:51:06 +00:00
|
|
|
type View struct {
|
|
|
|
*gtk.ScrolledWindow
|
|
|
|
Box *gtk.Box
|
|
|
|
Services []*Container
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewView() *View {
|
|
|
|
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
|
|
|
|
box.Show()
|
|
|
|
|
2020-05-28 19:26:55 +00:00
|
|
|
primitives.AddClass(box, "services")
|
|
|
|
|
2020-05-26 06:51:06 +00:00
|
|
|
sw, _ := gtk.ScrolledWindowNew(nil, nil)
|
2020-05-28 19:26:55 +00:00
|
|
|
sw.SetPolicy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
|
2020-05-26 06:51:06 +00:00
|
|
|
sw.Add(box)
|
2020-05-28 19:26:55 +00:00
|
|
|
sw.Show()
|
2020-05-26 06:51:06 +00:00
|
|
|
|
|
|
|
return &View{
|
|
|
|
sw,
|
|
|
|
box,
|
|
|
|
nil,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-04 23:00:41 +00:00
|
|
|
func (v *View) AddService(svc cchat.Service, ctrl Controller) *Container {
|
|
|
|
s := NewContainer(svc, ctrl)
|
2020-05-26 06:51:06 +00:00
|
|
|
v.Services = append(v.Services, s)
|
|
|
|
v.Box.Add(s)
|
2020-06-04 23:00:41 +00:00
|
|
|
return s
|
2020-05-26 06:51:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Container struct {
|
|
|
|
*gtk.Box
|
|
|
|
header *header
|
|
|
|
revealer *gtk.Revealer
|
|
|
|
children *children
|
2020-06-04 23:00:41 +00:00
|
|
|
rowctrl Controller
|
2020-05-26 06:51:06 +00:00
|
|
|
}
|
|
|
|
|
2020-06-04 23:00:41 +00:00
|
|
|
func NewContainer(svc cchat.Service, ctrl Controller) *Container {
|
2020-05-26 06:51:06 +00:00
|
|
|
children := newChildren()
|
2020-05-28 19:26:55 +00:00
|
|
|
|
2020-05-26 06:51:06 +00:00
|
|
|
chrev, _ := gtk.RevealerNew()
|
2020-06-04 23:00:41 +00:00
|
|
|
chrev.SetRevealChild(true)
|
2020-05-26 06:51:06 +00:00
|
|
|
chrev.Add(children)
|
2020-05-28 19:26:55 +00:00
|
|
|
chrev.Show()
|
2020-05-26 06:51:06 +00:00
|
|
|
|
2020-06-04 23:00:41 +00:00
|
|
|
header := newHeader(svc)
|
|
|
|
header.reveal.SetActive(chrev.GetRevealChild())
|
|
|
|
|
2020-05-26 06:51:06 +00:00
|
|
|
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
|
|
|
|
box.Show()
|
|
|
|
box.PackStart(header, false, false, 0)
|
|
|
|
box.PackStart(chrev, false, false, 0)
|
|
|
|
|
2020-05-28 19:26:55 +00:00
|
|
|
primitives.AddClass(box, "service")
|
2020-05-26 06:51:06 +00:00
|
|
|
|
2020-06-04 23:00:41 +00:00
|
|
|
var container = &Container{box, header, chrev, children, ctrl}
|
2020-05-28 19:26:55 +00:00
|
|
|
|
|
|
|
// On click, toggle reveal.
|
|
|
|
header.reveal.Connect("clicked", func() {
|
|
|
|
revealed := !chrev.GetRevealChild()
|
|
|
|
chrev.SetRevealChild(revealed)
|
|
|
|
header.reveal.SetActive(revealed)
|
|
|
|
})
|
|
|
|
|
|
|
|
// On click, show the auth dialog.
|
2020-05-26 06:51:06 +00:00
|
|
|
header.add.Connect("clicked", func() {
|
2020-06-04 23:00:41 +00:00
|
|
|
ctrl.AuthenticateSession(container, svc)
|
2020-05-26 06:51:06 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
return container
|
|
|
|
}
|
|
|
|
|
2020-06-04 23:00:41 +00:00
|
|
|
func (c *Container) AddSession(ses cchat.Session) {
|
2020-05-28 19:26:55 +00:00
|
|
|
srow := session.New(ses, c.rowctrl)
|
2020-05-26 06:51:06 +00:00
|
|
|
c.children.addSessionRow(srow)
|
|
|
|
}
|
|
|
|
|
2020-06-04 23:00:41 +00:00
|
|
|
func (c *Container) Sessions() []cchat.Session {
|
|
|
|
var sessions = make([]cchat.Session, len(c.children.Sessions))
|
|
|
|
for i, s := range c.children.Sessions {
|
|
|
|
sessions[i] = s.Session
|
|
|
|
}
|
|
|
|
return sessions
|
|
|
|
}
|
|
|
|
|
2020-05-26 06:51:06 +00:00
|
|
|
type header struct {
|
|
|
|
*gtk.Box
|
2020-06-04 23:00:41 +00:00
|
|
|
reveal *rich.ToggleButtonImage // no rich text here but it's left aligned
|
2020-05-28 19:26:55 +00:00
|
|
|
add *gtk.Button
|
2020-05-26 06:51:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func newHeader(svc cchat.Service) *header {
|
2020-06-04 23:00:41 +00:00
|
|
|
reveal := rich.NewToggleButtonImage(text.Rich{Content: svc.Name()}, "")
|
|
|
|
reveal.Box.SetHAlign(gtk.ALIGN_START)
|
2020-05-28 19:26:55 +00:00
|
|
|
reveal.SetRelief(gtk.RELIEF_NONE)
|
|
|
|
reveal.SetMode(true)
|
|
|
|
reveal.Show()
|
2020-05-26 06:51:06 +00:00
|
|
|
|
2020-06-04 23:00:41 +00:00
|
|
|
// Set a custom icon.
|
|
|
|
primitives.SetImageIcon(&reveal.Image, "folder-remote-symbolic", IconSize)
|
|
|
|
|
2020-05-26 06:51:06 +00:00
|
|
|
add, _ := gtk.ButtonNewFromIconName("list-add-symbolic", gtk.ICON_SIZE_BUTTON)
|
|
|
|
add.SetRelief(gtk.RELIEF_NONE)
|
|
|
|
add.Show()
|
|
|
|
|
|
|
|
box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
|
2020-05-28 19:26:55 +00:00
|
|
|
box.PackStart(reveal, true, true, 0)
|
2020-05-26 06:51:06 +00:00
|
|
|
box.PackStart(add, false, false, 0)
|
2020-05-28 19:26:55 +00:00
|
|
|
box.Show()
|
2020-05-26 06:51:06 +00:00
|
|
|
|
2020-05-28 19:26:55 +00:00
|
|
|
return &header{box, reveal, add}
|
2020-05-26 06:51:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type children struct {
|
|
|
|
*gtk.Box
|
|
|
|
Sessions []*session.Row
|
|
|
|
}
|
|
|
|
|
|
|
|
func newChildren() *children {
|
|
|
|
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
|
|
|
|
box.Show()
|
|
|
|
|
|
|
|
return &children{box, nil}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *children) addSessionRow(row *session.Row) {
|
|
|
|
c.Sessions = append(c.Sessions, row)
|
|
|
|
c.Box.Add(row)
|
|
|
|
}
|