diff --git a/go.mod b/go.mod index fd01342..0b9c612 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.14 require ( github.com/Xuanwo/go-locale v0.2.0 + github.com/davecgh/go-spew v1.1.1 // indirect github.com/diamondburned/cchat v0.0.9 github.com/diamondburned/cchat-mock v0.0.0-20200525222906-807afeffb7d4 github.com/goodsign/monday v1.0.0 diff --git a/go.sum b/go.sum index 99bb189..e764834 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/Pallinder/go-randomdata v1.2.0/go.mod h1:yHmJgulpD2Nfrm0cR9tI/+oAgRqC github.com/Xuanwo/go-locale v0.2.0 h1:1N8SGG2VNpLl6VVa8ueZm3Nm+dxvk8ffY9aviKHl4IE= github.com/Xuanwo/go-locale v0.2.0/go.mod h1:6qbT9M726OJgyiGZro2YwPmx63wQzlH+VvtjJWQoftw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/diamondburned/cchat v0.0.8 h1:/PmI23SFHJcjYBWNBwQbp36n7fDvDu+NMnQuhM5FM2E= -github.com/diamondburned/cchat v0.0.8/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/diamondburned/cchat v0.0.9 h1:+F96eDDuaOg4v4dz3GBDWbEW4dZ/k5uGrDp33/yeXR8= github.com/diamondburned/cchat v0.0.9/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= github.com/diamondburned/cchat-mock v0.0.0-20200525222906-807afeffb7d4 h1:k6vfDs6NR8yIi2V7YEpNp9Vujtl6mpDL5cWh7Pg09kk= @@ -13,18 +13,22 @@ github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/goodsign/monday v1.0.0 h1:Yyk/s/WgudMbAJN6UWSU5xAs8jtNewfqtVblAlw0yoc= github.com/goodsign/monday v1.0.0/go.mod h1:r4T4breXpoFwspQNM+u2sLxJb2zyTaxVGqUfTBjWOu8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gotk3/gotk3 v0.4.0 h1:TIuhyQitGeRTxOQIV3AJlYtEWWJpC74JHwAIsxlH8MU= -github.com/gotk3/gotk3 v0.4.0/go.mod h1:Eew3QBwAOBTrfFFDmsDE5wZWbcagBL1NUslj1GhRveo= github.com/gotk3/gotk3 v0.4.1-0.20200524052254-cb2aa31c6194 h1:bB6XWpxMt2isCWqzjXN8tfVazjxvD8nRJrNoKcL0xAc= github.com/gotk3/gotk3 v0.4.1-0.20200524052254-cb2aa31c6194/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -34,5 +38,7 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/gts/gts.go b/internal/gts/gts.go index 14ac2a3..dbe5c46 100644 --- a/internal/gts/gts.go +++ b/internal/gts/gts.go @@ -48,12 +48,13 @@ type WindowHeaderer interface { func Main(wfn func() WindowHeaderer) { App.Application.Connect("activate", func() { App.Header, _ = gtk.HeaderBarNew() - App.Header.Show() App.Header.SetShowCloseButton(true) + App.Header.Show() App.Window, _ = gtk.ApplicationWindowNew(App.Application) - App.Window.Show() + App.Window.SetDefaultSize(750, 400) App.Window.SetTitlebar(App.Header) + App.Window.Show() // Execute the function later, because we need it to run after // initialization. diff --git a/internal/ui/message/container.go b/internal/ui/message/container.go index e0f6306..f637220 100644 --- a/internal/ui/message/container.go +++ b/internal/ui/message/container.go @@ -8,23 +8,31 @@ import ( type Container struct { *gtk.ScrolledWindow - main *gtk.Box + main *gtk.Grid messages map[string]Message } func NewContainer() *Container { - box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 3) - box.Show() + grid, _ := gtk.GridNew() + grid.SetColumnSpacing(8) + grid.SetRowSpacing(5) + grid.SetMarginStart(5) + grid.SetMarginEnd(5) + grid.Show() sw, _ := gtk.ScrolledWindowNew(nil, nil) + sw.Add(grid) + sw.SetPolicy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) sw.Show() - return &Container{sw, box, map[string]Message{}} + return &Container{sw, grid, map[string]Message{}} } func (c *Container) Reset() { - for _, msg := range c.messages { - c.main.Remove(msg) + // does this actually work? + var rows = len(c.messages) + for i := 0; i < rows; i++ { + c.main.RemoveRow(i) } c.messages = nil @@ -32,9 +40,11 @@ func (c *Container) Reset() { func (c *Container) CreateMessage(msg cchat.MessageCreate) { gts.ExecAsync(func() { - var msgc = NewMessage(msg) + msgc := NewMessage(msg) + msgc.index = len(c.messages) // unsure + c.messages[msgc.ID] = msgc - c.main.Add(msgc) + msgc.Attach(c.main, msgc.index) }) } @@ -58,7 +68,7 @@ func (c *Container) DeleteMessage(msg cchat.MessageDelete) { gts.ExecAsync(func() { if m, ok := c.messages[msg.ID()]; ok { delete(c.messages, msg.ID()) - c.main.Remove(m) + c.main.RemoveRow(m.index) } }) } diff --git a/internal/ui/message/message.go b/internal/ui/message/message.go index 8ac2651..0919477 100644 --- a/internal/ui/message/message.go +++ b/internal/ui/message/message.go @@ -11,38 +11,40 @@ import ( ) type Message struct { + index int ID string Nonce string - *gtk.Box Timestamp *gtk.Label Username *gtk.Label Content *gtk.Label } func NewMessage(msg cchat.MessageCreate) Message { - box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 3) - box.Show() - ts, _ := gtk.LabelNew("") - ts.Show() - ts.SetWidthChars(12) + ts.SetLineWrap(true) ts.SetLineWrapMode(pango.WRAP_WORD) + ts.SetHAlign(gtk.ALIGN_END) + ts.SetVAlign(gtk.ALIGN_START) + ts.Show() user, _ := gtk.LabelNew("") - user.Show() + user.SetLineWrap(true) user.SetLineWrapMode(pango.WRAP_WORD_CHAR) + user.SetHAlign(gtk.ALIGN_END) + user.SetVAlign(gtk.ALIGN_START) + user.Show() content, _ := gtk.LabelNew("") + content.SetHExpand(true) + content.SetXAlign(0) // left-align with size filled + content.SetVAlign(gtk.ALIGN_START) + content.SetLineWrap(true) + content.SetLineWrapMode(pango.WRAP_WORD_CHAR) content.Show() - box.PackStart(ts, false, false, 0) - box.PackStart(user, false, false, 0) - box.PackStart(content, true, true, 0) - m := Message{ ID: msg.ID(), - Box: box, Timestamp: ts, Username: user, Content: content, @@ -58,6 +60,12 @@ func NewMessage(msg cchat.MessageCreate) Message { return m } +func (m *Message) Attach(grid *gtk.Grid, row int) { + grid.Attach(m.Timestamp, 0, row, 1, 1) + grid.Attach(m.Username, 1, row, 1, 1) + grid.Attach(m.Content, 2, row, 1, 1) +} + func (m *Message) UpdateTimestamp(t time.Time) { m.Timestamp.SetLabel(humanize.TimeAgo(t)) } diff --git a/internal/ui/message/view.go b/internal/ui/message/view.go index d68ecfc..df3bb1f 100644 --- a/internal/ui/message/view.go +++ b/internal/ui/message/view.go @@ -21,9 +21,9 @@ func NewView() *View { sendinput := input.NewField() box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0) - box.Show() box.PackStart(container, true, true, 0) box.PackStart(sendinput, false, false, 0) + box.Show() return &View{ Box: box, @@ -37,6 +37,9 @@ func (v *View) JoinServer(server cchat.ServerMessage) { if err := v.current.LeaveServer(); err != nil { log.Error(errors.Wrap(err, "Error leaving server")) } + + // Clean all messages. + v.Container.Reset() } v.current = server diff --git a/internal/ui/primitives/primitives.go b/internal/ui/primitives/primitives.go new file mode 100644 index 0000000..4b3c819 --- /dev/null +++ b/internal/ui/primitives/primitives.go @@ -0,0 +1,25 @@ +package primitives + +import "github.com/gotk3/gotk3/gtk" + +type StyleContexter interface { + GetStyleContext() (*gtk.StyleContext, error) +} + +func AddClass(styleCtx StyleContexter, classes ...string) { + var style, _ = styleCtx.GetStyleContext() + for _, class := range classes { + style.AddClass(class) + } +} + +type Bin interface { + GetChild() (gtk.IWidget, error) +} + +var _ Bin = (*gtk.Bin)(nil) + +func BinLeftAlignLabel(bin Bin) { + widget, _ := bin.GetChild() + widget.(interface{ SetXAlign(float64) }).SetXAlign(0) +} diff --git a/internal/ui/service/service.go b/internal/ui/service/service.go index 412e4a9..31364cd 100644 --- a/internal/ui/service/service.go +++ b/internal/ui/service/service.go @@ -2,8 +2,10 @@ package service import ( "github.com/diamondburned/cchat" + "github.com/diamondburned/cchat-gtk/internal/ui/primitives" "github.com/diamondburned/cchat-gtk/internal/ui/service/auth" "github.com/diamondburned/cchat-gtk/internal/ui/service/session" + "github.com/diamondburned/cchat-gtk/internal/ui/service/session/server" "github.com/gotk3/gotk3/gtk" ) @@ -17,9 +19,12 @@ func NewView() *View { box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0) box.Show() + primitives.AddClass(box, "services") + sw, _ := gtk.ScrolledWindowNew(nil, nil) - sw.Show() + sw.SetPolicy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) sw.Add(box) + sw.Show() return &View{ sw, @@ -28,8 +33,8 @@ func NewView() *View { } } -func (v *View) AddService(svc cchat.Service) { - s := NewContainer(svc) +func (v *View) AddService(svc cchat.Service, rowctrl server.RowController) { + s := NewContainer(svc, rowctrl) v.Services = append(v.Services, s) v.Box.Add(s) } @@ -39,24 +44,36 @@ type Container struct { header *header revealer *gtk.Revealer children *children + rowctrl server.RowController } -func NewContainer(svc cchat.Service) *Container { +func NewContainer(svc cchat.Service, rowctrl server.RowController) *Container { header := newHeader(svc) children := newChildren() + chrev, _ := gtk.RevealerNew() - chrev.Show() chrev.SetRevealChild(false) chrev.Add(children) + chrev.Show() box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0) box.Show() box.PackStart(header, false, false, 0) box.PackStart(chrev, false, false, 0) - var container = &Container{box, header, chrev, children} + primitives.AddClass(box, "service") + var container = &Container{box, header, chrev, children, rowctrl} + + // 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. header.add.Connect("clicked", func() { auth.NewDialog(svc.Name(), svc.Authenticate(), container.addSession) }) @@ -65,31 +82,34 @@ func NewContainer(svc cchat.Service) *Container { } func (c *Container) addSession(ses cchat.Session) { - srow := session.New(ses) + srow := session.New(ses, c.rowctrl) c.children.addSessionRow(srow) } type header struct { *gtk.Box - label *gtk.Label - add *gtk.Button + reveal *gtk.ToggleButton + add *gtk.Button } func newHeader(svc cchat.Service) *header { - label, _ := gtk.LabelNew(svc.Name()) - label.Show() - label.SetXAlign(0) + reveal, _ := gtk.ToggleButtonNewWithLabel(svc.Name()) + primitives.BinLeftAlignLabel(reveal) // do this first + + reveal.SetRelief(gtk.RELIEF_NONE) + reveal.SetMode(true) + reveal.Show() add, _ := gtk.ButtonNewFromIconName("list-add-symbolic", gtk.ICON_SIZE_BUTTON) add.SetRelief(gtk.RELIEF_NONE) add.Show() box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0) - box.Show() - box.PackStart(label, true, true, 5) + box.PackStart(reveal, true, true, 0) box.PackStart(add, false, false, 0) + box.Show() - return &header{box, label, add} + return &header{box, reveal, add} } type children struct { diff --git a/internal/ui/service/session/server/server.go b/internal/ui/service/session/server/server.go index 0e0db73..9ff8339 100644 --- a/internal/ui/service/session/server/server.go +++ b/internal/ui/service/session/server/server.go @@ -4,37 +4,49 @@ import ( "github.com/diamondburned/cchat" "github.com/diamondburned/cchat-gtk/internal/gts" "github.com/diamondburned/cchat-gtk/internal/log" + "github.com/diamondburned/cchat-gtk/internal/ui/primitives" "github.com/gotk3/gotk3/gtk" "github.com/pkg/errors" ) +const ChildrenMargin = 24 + +type RowController interface { + MessageRowSelected(*Row, cchat.ServerMessage) +} + type Row struct { *gtk.Box Button *gtk.Button Server cchat.Server + ctrl RowController + // enum 1 - clicked func(*Row) message cchat.ServerMessage // enum 2 children *Children } -func New(server cchat.Server) *Row { +func New(server cchat.Server, ctrl RowController) *Row { name, err := server.Name() if err != nil { log.Error(errors.Wrap(err, "Failed to get the server name")) name = "no name" } - box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0) + button, _ := gtk.ButtonNewWithLabel(name) + primitives.BinLeftAlignLabel(button) + + button.SetRelief(gtk.RELIEF_NONE) + button.Show() + + box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0) + box.PackStart(button, false, false, 0) box.Show() - button, _ := gtk.ButtonNew() - button.Show() - button.SetRelief(gtk.RELIEF_NONE) - button.SetLabel(name) + primitives.AddClass(box, "server") // TODO: images @@ -42,31 +54,30 @@ func New(server cchat.Server) *Row { Box: box, Button: button, Server: server, + ctrl: ctrl, } button.Connect("clicked", row.onClick) switch server := server.(type) { case cchat.ServerList: - row.children = NewChildren(server) + row.children = NewChildren(server, ctrl) + box.PackStart(row.children, false, false, 0) + + primitives.AddClass(box, "server-list") + case cchat.ServerMessage: row.message = server + + primitives.AddClass(box, "server-message") } return row } -// SetOnClick sets the callback when the server is clicked. This only works if -// the passed in server implements ServerMessage. -func (row *Row) SetOnClick(clicked func(*Row)) { - if row.message != nil { - row.clicked = clicked - } -} - func (row *Row) onClick() { switch { case row.message != nil: - row.clicked(row) + row.ctrl.MessageRowSelected(row, row.message) case row.children != nil: row.children.SetRevealChild(!row.children.GetRevealChild()) } @@ -75,22 +86,27 @@ func (row *Row) onClick() { type Children struct { *gtk.Revealer Main *gtk.Box - Rows []*Row List cchat.ServerList + + Rows []*Row + rowctrl RowController } -func NewChildren(list cchat.ServerList) *Children { - rev, _ := gtk.RevealerNew() - rev.Show() - rev.SetRevealChild(false) - - main, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0) +func NewChildren(list cchat.ServerList, ctrl RowController) *Children { + main, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0) + main.SetMarginStart(ChildrenMargin) main.Show() + rev, _ := gtk.RevealerNew() + rev.SetRevealChild(false) + rev.Add(main) + rev.Show() + children := &Children{ Revealer: rev, Main: main, List: list, + rowctrl: ctrl, } if err := list.Servers(children); err != nil { @@ -109,7 +125,7 @@ func (c *Children) SetServers(servers []cchat.Server) { c.Rows = make([]*Row, len(servers)) for i, server := range servers { - row := New(server) + row := New(server, c.rowctrl) c.Rows[i] = row c.Main.Add(row) } diff --git a/internal/ui/service/session/session.go b/internal/ui/service/session/session.go index 6740110..5288133 100644 --- a/internal/ui/service/session/session.go +++ b/internal/ui/service/session/session.go @@ -3,6 +3,7 @@ package session import ( "github.com/diamondburned/cchat" "github.com/diamondburned/cchat-gtk/internal/log" + "github.com/diamondburned/cchat-gtk/internal/ui/primitives" "github.com/diamondburned/cchat-gtk/internal/ui/service/session/server" "github.com/gotk3/gotk3/gtk" "github.com/pkg/errors" @@ -10,35 +11,46 @@ import ( type Row struct { *gtk.Box - Button *gtk.Button + Button *gtk.ToggleButton Session cchat.Session Servers *server.Children } -func New(ses cchat.Session) *Row { +func New(ses cchat.Session, rowctrl server.RowController) *Row { n, err := ses.Name() if err != nil { log.Error(errors.Wrap(err, "Failed to get the username")) n = "no name" } - box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0) - box.Show() + button, _ := gtk.ToggleButtonNewWithLabel(n) + primitives.BinLeftAlignLabel(button) - button, _ := gtk.ButtonNew() - button.Show() button.SetRelief(gtk.RELIEF_NONE) - button.SetLabel(n) + button.Show() - rev, _ := gtk.RevealerNew() - rev.Show() - rev.SetRevealChild(false) + servers := server.NewChildren(ses, rowctrl) + + box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0) + box.Show() + box.SetMarginStart(server.ChildrenMargin) + box.PackStart(button, false, false, 0) + box.PackStart(servers, false, false, 0) + + primitives.AddClass(box, "session") + + // On click, toggle reveal. + button.Connect("clicked", func() { + revealed := !servers.GetRevealChild() + servers.SetRevealChild(revealed) + button.SetActive(revealed) + }) return &Row{ Box: box, Button: button, Session: ses, - Servers: server.NewChildren(ses), + Servers: servers, } } diff --git a/internal/ui/ui.go b/internal/ui/ui.go index c94d8da..70cad76 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -3,6 +3,7 @@ package ui import ( "github.com/diamondburned/cchat" "github.com/diamondburned/cchat-gtk/internal/gts" + "github.com/diamondburned/cchat-gtk/internal/ui/service/session/server" "github.com/gotk3/gotk3/gtk" ) @@ -14,8 +15,9 @@ type Application struct { } var ( - _ gts.Windower = (*Application)(nil) - _ gts.Headerer = (*Application)(nil) + _ gts.Windower = (*Application)(nil) + _ gts.Headerer = (*Application)(nil) + _ server.RowController = (*Application)(nil) ) func NewApplication() *Application { @@ -28,7 +30,11 @@ func NewApplication() *Application { } func (app *Application) AddService(svc cchat.Service) { - app.window.Services.AddService(svc) + app.window.Services.AddService(svc, app) +} + +func (app *Application) MessageRowSelected(_ *server.Row, smsg cchat.ServerMessage) { + app.window.MessageView.JoinServer(smsg) } func (app *Application) Header() gtk.IWidget { diff --git a/internal/ui/window.go b/internal/ui/window.go index 30a1397..e4b4ef4 100644 --- a/internal/ui/window.go +++ b/internal/ui/window.go @@ -17,10 +17,14 @@ func newWindow() *window { services.SetSizeRequest(LeftWidth, -1) mesgview := message.NewView() + separator, _ := gtk.SeparatorNew(gtk.ORIENTATION_VERTICAL) + separator.Show() + box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0) - box.Show() box.PackStart(services, false, false, 0) + box.PackStart(separator, false, false, 0) box.PackStart(mesgview, true, true, 0) + box.Show() return &window{box, services, mesgview} }