mirror of
https://github.com/diamondburned/cchat-gtk.git
synced 2024-12-05 04:14:56 +00:00
Working prototype
This commit is contained in:
parent
275ae709ae
commit
ee657a8177
1
go.mod
1
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
|
||||
|
|
14
go.sum
14
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=
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
25
internal/ui/primitives/primitives.go
Normal file
25
internal/ui/primitives/primitives.go
Normal file
|
@ -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)
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue