WIP libhandy support

This commit is contained in:
diamondburned 2020-08-28 00:16:03 -07:00
parent c2fc4d7512
commit ba105295eb
13 changed files with 383 additions and 186 deletions

2
go.mod
View File

@ -10,7 +10,7 @@ require (
github.com/diamondburned/cchat v0.0.49
github.com/diamondburned/cchat-discord v0.0.0-20200821041521-647c854d7b5e
github.com/diamondburned/cchat-mock v0.0.0-20200709231652-ad222ce5a74b
github.com/diamondburned/handy v0.0.0-20200827040421-5b4a15843526 // indirect
github.com/diamondburned/handy v0.0.0-20200827040421-5b4a15843526
github.com/diamondburned/imgutil v0.0.0-20200710174014-8a3be144a972
github.com/disintegration/imaging v1.6.2
github.com/goodsign/monday v1.0.0

View File

@ -8,6 +8,7 @@ import (
"github.com/diamondburned/cchat-gtk/internal/gts/throttler"
"github.com/diamondburned/cchat-gtk/internal/log"
"github.com/diamondburned/handy"
"github.com/disintegration/imaging"
"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/glib"
@ -21,12 +22,22 @@ var Args = append([]string{}, os.Args...)
var App struct {
*gtk.Application
Window *gtk.ApplicationWindow
Header *gtk.HeaderBar
Window *handy.ApplicationWindow
Throttler *throttler.State
}
// Windower is the interface for a window.
type Windower interface {
gtk.IWidget
gtk.IWindow
throttler.Connector
}
func AddWindow(w Windower) {
App.AddWindow(w)
App.Throttler.Connect(w)
}
// Clipboard is initialized on init().
var Clipboard *gtk.Clipboard
@ -39,7 +50,8 @@ func NewModalDialog() (*gtk.Dialog, error) {
}
d.SetModal(true)
d.SetTransientFor(App.Window)
App.Throttler.Connect(d)
AddWindow(d)
return d, nil
}
@ -75,72 +87,42 @@ func init() {
App.Throttler = throttler.Bind(App.Application)
}
// // AppMenuWidget returns the box that holds the app menu.
// func AppMenuWidget() (widget *gtk.Widget) {
// App.Header.For().Foreach(func(v interface{}) {
// // If we've already found the widget, then stop finding.
// if widget != nil {
// return
// }
// // Cast the interface to a widget.
// curr := v.(gtk.IWidget).ToWidget()
// log.Println("testing")
// // Check if the widget has a class named "left".
// if sctx, _ := curr.GetStyleContext(); sctx.HasClass("left") {
// log.Println("has class .left")
// widget = curr
// }
// })
// return
// }
type Window interface {
Window() gtk.IWidget
Header() gtk.IWidget
type MainApplication interface {
gtk.IWidget
Menu() *glib.MenuModel
Icon() *gdk.Pixbuf
Close()
}
func Main(wfn func() Window) {
func Main(wfn func() MainApplication) {
App.Application.Connect("activate", func() {
handy.Init()
// Load all CSS onto the default screen.
loadProviders(getDefaultScreen())
App.Header, _ = gtk.HeaderBarNew()
// Right buttons only.
App.Header.SetDecorationLayout(":minimize,close")
App.Header.SetShowCloseButton(true)
App.Header.SetProperty("spacing", 0)
// App.Header, _ = gtk.HeaderBarNew()
// // Right buttons only.
// App.Header.SetDecorationLayout(":minimize,close")
// App.Header.SetShowCloseButton(true)
// App.Header.SetProperty("spacing", 0)
b, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
App.Header.SetCustomTitle(b)
App.Window, _ = gtk.ApplicationWindowNew(App.Application)
App.Window = handy.ApplicationWindowNew()
App.Window.SetDefaultSize(1000, 500)
App.Window.SetTitlebar(App.Header)
App.Window.Show()
AddWindow(&App.Window.Window)
App.Throttler.Connect(&App.Window.Window)
// Execute the function later, because we need it to run after
// initialization.
w := wfn()
App.Application.SetAppMenu(w.Menu())
App.Window.Add(w)
App.Window.SetIcon(w.Icon())
App.Window.Add(w.Window())
App.Window.Show()
App.Header.Add(w.Header())
App.Header.Show()
// Connect extra actions.
AddAppAction("quit", App.Window.Destroy)
// App.Application.SetAppMenu(w.Menu())
// Connect the destructor.
App.Window.Connect("destroy", func() {
App.Window.Window.Connect("destroy", func() {
// Hide the application window.
App.Window.Hide()
@ -154,6 +136,9 @@ func Main(wfn func() Window) {
w.Close()
})
})
// Connect extra actions.
AddAppAction("quit", App.Window.Destroy)
})
// Use a special function to run the application. Exit with the appropriate

View File

@ -9,43 +9,33 @@ import (
"github.com/diamondburned/cchat-gtk/internal/ui/primitives/actions"
"github.com/diamondburned/cchat-gtk/internal/ui/service/session"
"github.com/diamondburned/cchat-gtk/internal/ui/service/session/server/traverse"
"github.com/diamondburned/handy"
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
"github.com/gotk3/gotk3/pango"
)
type header struct {
*gtk.Box
left *headerLeft // middle-ish
right *headerRight
menu *glib.Menu
}
func newHeader() *header {
left := newHeaderLeft()
left.Show()
right := newHeaderRight()
right.Show()
separator, _ := gtk.SeparatorNew(gtk.ORIENTATION_VERTICAL)
separator.Show()
box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
box.PackStart(left, false, false, 0)
box.PackStart(separator, false, false, 0)
box.PackStart(right, true, true, 0)
box.Show()
menu := glib.MenuNew()
menu.Append("Preferences", "app.preferences")
menu.Append("Quit", "app.quit")
left := newHeaderLeft()
left.appmenu.SetMenuModel(&menu.MenuModel)
// TODO
right := newHeaderRight()
group := handy.HeaderGroupNew()
group.AddHeaderBar(&left.HeaderBar)
group.AddHeaderBar(&right.HeaderBar)
return &header{
box,
left,
right,
menu,
@ -111,60 +101,84 @@ func (a *appMenu) SetSizeRequest(w, h int) {
}
type headerLeft struct {
*gtk.Box
handy.HeaderBar
appmenu *appMenu
svcname *gtk.Label
sesmenu *actions.MenuButton
}
var serviceNameCSS = primitives.PrepareClassCSS("service-name", `
.service-name {
margin-left: 14px;
}
`)
var sessionMenuCSS = primitives.PrepareClassCSS("session-menu", `
.session-menu {
margin: 0 5px;
}
`)
func newHeaderLeft() *headerLeft {
appmenu := newAppMenu()
appmenu.Show()
sep, _ := gtk.SeparatorNew(gtk.ORIENTATION_VERTICAL)
sep.Show()
primitives.AddClass(sep, "titlebutton")
// sep, _ := gtk.SeparatorNew(gtk.ORIENTATION_VERTICAL)
// sep.Show()
// primitives.AddClass(sep, "titlebutton")
svcname, _ := gtk.LabelNew("")
svcname, _ := gtk.LabelNew("cchat-gtk")
svcname.SetXAlign(0)
svcname.SetEllipsize(pango.ELLIPSIZE_END)
svcname.Show()
svcname.SetMarginStart(14)
serviceNameCSS(svcname)
sesmenu := actions.NewMenuButton()
sesmenu.Show()
sessionMenuCSS(sesmenu)
box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
box.PackStart(appmenu, false, false, 0)
box.PackStart(sep, false, false, 0)
box.PackStart(svcname, true, true, 0)
box.PackStart(sesmenu, false, false, 5)
header := handy.HeaderBarNew()
header.SetShowCloseButton(true)
header.PackStart(appmenu)
// box.PackStart(sep, false, false, 0)
header.PackStart(svcname)
header.PackStart(sesmenu)
return &headerLeft{
Box: box,
appmenu: appmenu,
svcname: svcname,
sesmenu: sesmenu,
HeaderBar: *header,
appmenu: appmenu,
svcname: svcname,
sesmenu: sesmenu,
}
}
type headerRight struct {
*gtk.Box
handy.HeaderBar
breadcrumb *gtk.Label
}
var rightBreadcrumbCSS = primitives.PrepareClassCSS("right-breadcrumb", `
.right-breadcrumb {
margin: 0 14px;
}
`)
func newHeaderRight() *headerRight {
bc, _ := gtk.LabelNew(BreadcrumbSlash)
bc.SetUseMarkup(true)
bc.SetXAlign(0.0)
bc.Show()
rightBreadcrumbCSS(bc)
box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
box.PackStart(bc, true, true, 14)
box.Show()
header := handy.HeaderBarNew()
header.SetShowCloseButton(true)
header.PackStart(bc)
header.Show()
return &headerRight{
Box: box,
HeaderBar: *header,
breadcrumb: bc,
}
}

View File

@ -0,0 +1,64 @@
package messages
import (
"html"
"strings"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives"
"github.com/diamondburned/cchat-gtk/internal/ui/service/session/server/traverse"
"github.com/diamondburned/handy"
"github.com/gotk3/gotk3/gtk"
)
// const BreadcrumbSlash = `<span rise="-1024" size="x-large">❭</span>`
const BreadcrumbSlash = " 〉"
type Header struct {
handy.HeaderBar
Breadcrumb *gtk.Label
}
var rightBreadcrumbCSS = primitives.PrepareClassCSS("right-breadcrumb", `
.right-breadcrumb {
margin: 0 14px;
}
`)
func NewHeader() *Header {
bc, _ := gtk.LabelNew(BreadcrumbSlash)
bc.SetUseMarkup(true)
bc.SetXAlign(0.0)
bc.Show()
rightBreadcrumbCSS(bc)
header := handy.HeaderBarNew()
header.SetShowCloseButton(true)
header.PackStart(bc)
header.Show()
return &Header{
HeaderBar: *header,
Breadcrumb: bc,
}
}
func (h *Header) Reset() {
h.SetBreadcrumber(nil)
}
func (h *Header) SetBreadcrumber(b traverse.Breadcrumber) {
if b == nil {
h.Breadcrumb.SetText("")
return
}
var crumb = b.Breadcrumb()
for i := range crumb {
crumb[i] = html.EscapeString(crumb[i])
}
h.Breadcrumb.SetMarkup(
BreadcrumbSlash + " " + strings.Join(crumb, " "+BreadcrumbSlash+" "),
)
}

View File

@ -49,8 +49,12 @@ type Controller interface {
}
type View struct {
*sadface.FaceView
Grid *gtk.Grid
*gtk.Box
Header *Header
FaceView *sadface.FaceView
Grid *gtk.Grid
Scroller *autoscroll.ScrolledWindow
InputView *input.InputView
@ -126,6 +130,15 @@ func NewView(c Controller) *View {
logo.Show()
view.FaceView = sadface.New(view.Grid, logo)
view.FaceView.Show()
view.Header = NewHeader()
view.Header.Show()
view.Box, _ = gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
view.Box.PackStart(view.Header, false, false, 0)
view.Box.PackStart(view.FaceView, true, true, 0)
return view
}
@ -153,6 +166,7 @@ func (v *View) createMessageContainer() {
func (v *View) Bottomed() bool { return v.Scroller.Bottomed }
func (v *View) Reset() {
v.Header.Reset() // Reset the header.
v.state.Reset() // Reset the state variables.
v.Typing.Reset() // Reset the typing state.
v.InputView.Reset() // Reset the input.
@ -194,7 +208,7 @@ func (v *View) JoinServer(session cchat.Session, server ServerMessage) {
err = errors.Wrap(err, "Failed to join server")
// Even if we're erroring out, we're running the done() callback
// anyway.
return func() { v.ctrl.OnMessageDone(); v.SetError(err) }, err
return func() { v.ctrl.OnMessageDone(); v.FaceView.SetError(err) }, err
}
return func() {

View File

@ -14,6 +14,7 @@ type MenuButton struct {
func NewMenuButton() *MenuButton {
b, _ := gtk.MenuButtonNew()
b.SetVAlign(gtk.ALIGN_CENTER)
b.SetSensitive(false)
return &MenuButton{

View File

@ -0,0 +1,137 @@
package service
import (
"github.com/diamondburned/cchat-gtk/icons"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives/actions"
"github.com/diamondburned/cchat-gtk/internal/ui/service/session"
"github.com/diamondburned/cchat-gtk/internal/ui/service/session/server/traverse"
"github.com/diamondburned/handy"
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
"github.com/gotk3/gotk3/pango"
)
type AppMenu struct {
gtk.MenuButton
}
func NewAppMenu() *AppMenu {
img, _ := gtk.ImageNew()
img.SetFromPixbuf(icons.Logo256(24))
img.Show()
appmenu, _ := gtk.MenuButtonNew()
appmenu.SetImage(img)
appmenu.SetUsePopover(true)
appmenu.SetHAlign(gtk.ALIGN_CENTER)
appmenu.SetMarginStart(8)
appmenu.SetMarginEnd(8)
return &AppMenu{*appmenu}
}
func (a *AppMenu) SetSizeRequest(w, h int) {
// Subtract the margin size.
if w -= 8 * 2; w < 0 {
w = 0
}
a.MenuButton.SetSizeRequest(w, h)
}
type Header struct {
handy.HeaderBar
MenuModel *glib.MenuModel
AppMenu *AppMenu
SvcName *gtk.Label
SesMenu *actions.MenuButton
}
var serviceNameCSS = primitives.PrepareClassCSS("service-name", `
.service-name {
margin-left: 14px;
}
`)
var sessionMenuCSS = primitives.PrepareClassCSS("session-menu", `
.session-menu {
margin: 0 5px;
}
`)
func NewHeader() *Header {
menu := glib.MenuNew()
menu.Append("Preferences", "app.preferences")
menu.Append("Quit", "app.quit")
appmenu := NewAppMenu()
appmenu.Show()
appmenu.SetMenuModel(&menu.MenuModel)
sep, _ := gtk.SeparatorNew(gtk.ORIENTATION_VERTICAL)
sep.Show()
primitives.AddClass(sep, "titlebutton")
svcname, _ := gtk.LabelNew("cchat-gtk")
svcname.SetXAlign(0)
svcname.SetEllipsize(pango.ELLIPSIZE_END)
svcname.Show()
serviceNameCSS(svcname)
sesmenu := actions.NewMenuButton()
sesmenu.Show()
sessionMenuCSS(sesmenu)
header := handy.HeaderBarNew()
header.SetProperty("spacing", 0)
header.SetShowCloseButton(true)
header.PackStart(appmenu)
header.PackStart(sep)
header.PackStart(svcname)
header.PackStart(sesmenu)
// Hack to hide the title.
b, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
header.SetCustomTitle(b)
return &Header{
HeaderBar: *header,
MenuModel: &menu.MenuModel,
AppMenu: appmenu,
SvcName: svcname,
SesMenu: sesmenu,
}
}
func (h *Header) SetBreadcrumber(b traverse.Breadcrumber) {
if b == nil {
h.SvcName.SetText("cchat-gtk")
return
}
if crumb := b.Breadcrumb(); len(crumb) > 0 {
h.SvcName.SetText(crumb[0])
} else {
h.SvcName.SetText("")
}
}
func (h *Header) SetSessionMenu(s *session.Row) {
h.SesMenu.Bind(s.ActionsMenu)
}
type sizeBinder interface {
primitives.Connector
GetAllocatedWidth() int
}
var _ sizeBinder = (*List)(nil)
func (h *Header) AppMenuBindSize(c sizeBinder) {
c.Connect("size-allocate", func() {
h.AppMenu.SetSizeRequest(c.GetAllocatedWidth(), -1)
})
}

View File

@ -45,7 +45,6 @@ func NewList(vctl ViewController) *List {
svlist.ListBox, _ = gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
svlist.ListBox.Show()
svlist.ListBox.SetHAlign(gtk.ALIGN_START)
svlist.ListBox.SetHExpand(false)
listCSS(svlist.ListBox)
svlist.ScrolledWindow, _ = gtk.ScrolledWindowNew(nil, nil)

View File

@ -8,13 +8,14 @@ import (
"github.com/diamondburned/cchat-gtk/internal/humanize"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives/spinner"
"github.com/diamondburned/cchat-gtk/internal/ui/service/session/server/traverse"
"github.com/diamondburned/cchat-gtk/internal/ui/service/session/server"
"github.com/diamondburned/cchat-gtk/internal/ui/service/session/server/traverse"
"github.com/gotk3/gotk3/gtk"
"github.com/gotk3/gotk3/pango"
)
const FaceSize = 48 // gtk.ICON_SIZE_DIALOG
const ListWidth = 200
// Servers wraps around a list of servers inherited from Children. It's the
// container that's displayed on the right of the service sidebar.
@ -34,7 +35,7 @@ var toplevelCSS = primitives.PrepareClassCSS("top-level", `
func NewServers(p traverse.Breadcrumber, ctrl server.Controller) *Servers {
c := server.NewChildren(p, ctrl)
c.SetMarginStart(0) // children is top level; there is no main row
c.SetHExpand(true) // fill
c.SetVExpand(true)
c.Show()
toplevelCSS(c)

View File

@ -23,8 +23,12 @@ type Controller interface {
}
type View struct {
*gtk.Box // 2 panes, but left-most hard-coded
Controller // inherit main controller
*gtk.Box
Header *Header
BottomPane *gtk.Box // 2 panes, but left-most hard-coded
Controller // inherit main controller
Services *List
ServerView *gtk.ScrolledWindow
@ -40,9 +44,9 @@ func NewView(ctrller Controller) *View {
view.Services = NewList(view)
view.Services.Show()
// Make a separator.
// sep, _ := gtk.SeparatorNew(gtk.ORIENTATION_VERTICAL)
// sep.Show()
view.Header = NewHeader()
view.Header.AppMenuBindSize(view.Services)
view.Header.Show()
// Make a stack for the middle panel.
view.ServerStack = singlestack.NewStack()
@ -50,18 +54,21 @@ func NewView(ctrller Controller) *View {
view.ServerStack.SetTransitionDuration(50)
view.ServerStack.SetTransitionType(gtk.STACK_TRANSITION_TYPE_CROSSFADE)
view.ServerStack.SetHomogeneous(true)
view.ServerStack.SetHExpand(true)
view.ServerStack.Show()
view.ServerView, _ = gtk.ScrolledWindowNew(nil, nil)
view.ServerView.SetPolicy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
view.ServerView.SetHExpand(true)
view.ServerView.Add(view.ServerStack)
view.ServerView.Show()
view.Box, _ = gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
view.Box.PackStart(view.Services, false, false, 0)
view.Box.PackStart(view.ServerView, true, true, 0)
view.BottomPane, _ = gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
view.BottomPane.PackStart(view.Services, false, false, 0)
view.BottomPane.PackStart(view.ServerView, true, true, 0)
view.BottomPane.Show()
view.Box, _ = gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
view.Box.PackStart(view.Header, false, false, 0)
view.Box.PackStart(view.BottomPane, true, true, 0)
view.Box.Show()
return view
@ -88,6 +95,24 @@ func (v *View) SessionSelected(svc *Service, srow *session.Row) {
// reference anyway. In fact, cchat REQUIRES us to do so.
v.ServerStack.SetVisibleChild(srow.Servers)
// Call the controller's method.
v.Header.SetSessionMenu(srow)
v.Header.SetBreadcrumber(srow)
v.Controller.SessionSelected(svc, srow)
}
// RowSelected is called when a row is selected. It updates the header then
// calls the application's RowSelected method.
func (v *View) RowSelected(srow *session.Row, srv *server.ServerRow, smsg cchat.ServerMessage) {
v.Header.SetBreadcrumber(srv)
v.Controller.RowSelected(srow, srv, smsg)
}
func (v *View) OnSessionRemove(s *Service, r *session.Row) {
v.Header.SetBreadcrumber(nil)
v.Controller.OnSessionRemove(s, r)
}
func (v *View) OnSessionDisconnect(s *Service, r *session.Row) {
v.Header.SetBreadcrumber(nil)
v.Controller.OnSessionDisconnect(s, r)
}

View File

@ -11,9 +11,9 @@ import (
"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/diamondburned/handy"
"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
"github.com/pkg/errors"
)
@ -51,36 +51,40 @@ func clamp(n, min, max int) int {
}
type App struct {
window *window
header *header
handy.Leaflet
HeaderGroup *handy.HeaderGroup
Services *service.View
MessageView *messages.View
// used to keep track of what row to disconnect before switching
lastSelector func(bool)
}
var (
_ gts.Window = (*App)(nil)
_ service.Controller = (*App)(nil)
_ gts.MainApplication = (*App)(nil)
_ service.Controller = (*App)(nil)
_ messages.Controller = (*App)(nil)
)
func NewApplication() *App {
app := &App{}
app.window = newWindow(app)
app.header = newHeader()
// Resize the app icon with the left-most sidebar.
services := app.window.Services.Services
services.Connect("size-allocate", func() {
app.header.left.appmenu.SetSizeRequest(services.GetAllocatedWidth(), -1)
})
app.Services = service.NewView(app)
app.Services.SetSizeRequest(leftMinWidth, -1)
app.Services.Show()
// Resize the left-side header w/ the left-side pane.
app.window.Services.ServerView.Connect("size-allocate", func() {
// Get the current width of the left sidebar.
width := app.window.GetPosition()
// Set the left-side header's size.
app.header.left.SetSizeRequest(width, -1)
})
app.MessageView = messages.NewView(app)
app.MessageView.Show()
app.HeaderGroup = handy.HeaderGroupNew()
app.HeaderGroup.AddHeaderBar(&app.Services.Header.HeaderBar)
app.HeaderGroup.AddHeaderBar(&app.MessageView.Header.HeaderBar)
app.Leaflet = *handy.LeafletNew()
app.Leaflet.Add(app.Services)
app.Leaflet.Add(app.MessageView)
app.Leaflet.Show()
// Bind the preferences action for our GAction button in the header popover.
// The action name for this is "app.preferences".
@ -89,16 +93,17 @@ func NewApplication() *App {
return app
}
// Services methods.
func (app *App) AddService(svc cchat.Service) {
app.window.Services.AddService(svc)
app.Services.AddService(svc)
}
// OnSessionRemove resets things before the session is removed.
func (app *App) OnSessionRemove(s *service.Service, r *session.Row) {
// Reset the message view if it's what we're showing.
if app.window.MessageView.SessionID() == r.ID() {
app.window.MessageView.Reset()
app.header.SetBreadcrumber(nil)
if app.MessageView.SessionID() == r.ID() {
app.MessageView.Reset()
}
}
@ -119,9 +124,7 @@ func (app *App) SessionSelected(svc *service.Service, ses *session.Row) {
// reset view when setservers top level called
// TODO: restore last message box
app.window.MessageView.Reset()
app.header.SetBreadcrumber(ses)
app.header.SetSessionMenu(ses)
app.MessageView.Reset()
}
func (app *App) RowSelected(ses *session.Row, srv *server.ServerRow, smsg cchat.ServerMessage) {
@ -134,12 +137,12 @@ func (app *App) RowSelected(ses *session.Row, srv *server.ServerRow, smsg cchat.
app.lastSelector = srv.SetSelected
app.lastSelector(true)
app.header.SetBreadcrumber(srv)
// Assert that server is also a list, then join the server.
app.window.MessageView.JoinServer(ses.Session, smsg.(messages.ServerMessage))
app.MessageView.JoinServer(ses.Session, smsg.(messages.ServerMessage))
}
// MessageView methods.
func (app *App) OnMessageBusy() {
// Disable the server list because we don't want the user to switch around
// while we're loading.
@ -163,7 +166,7 @@ func (app *App) Close() {
// Disconnect everything. This blocks the main thread, so by the time we're
// done, the application would exit immediately. There's no need to update
// the GUI.
for _, s := range app.window.AllServices() {
for _, s := range app.Services.Services.Services {
var service = s.Service().Name()
for _, session := range s.BodyList.Sessions() {
@ -180,18 +183,10 @@ func (app *App) Close() {
}
}
func (app *App) Header() gtk.IWidget {
return app.header
}
func (app *App) Window() gtk.IWidget {
return app.window
}
func (app *App) Icon() *gdk.Pixbuf {
return icons.Logo256(0)
}
func (app *App) Menu() *glib.MenuModel {
return &app.header.menu.MenuModel
return app.Services.Header.MenuModel
}

View File

@ -1,39 +1 @@
package ui
import (
"github.com/diamondburned/cchat-gtk/internal/ui/messages"
"github.com/diamondburned/cchat-gtk/internal/ui/service"
"github.com/gotk3/gotk3/gtk"
)
type window struct {
*gtk.Paned
Services *service.View
MessageView *messages.View
}
type Controller interface {
service.Controller
messages.Controller
}
func newWindow(mainctl Controller) *window {
services := service.NewView(mainctl)
services.SetSizeRequest(leftMinWidth, -1)
services.Show()
mesgview := messages.NewView(mainctl)
mesgview.Show()
pane, _ := gtk.PanedNew(gtk.ORIENTATION_HORIZONTAL)
pane.Pack1(services, false, false)
pane.Pack2(mesgview, true, false)
pane.SetPosition(leftCurrentWidth)
pane.Show()
return &window{pane, services, mesgview}
}
func (w *window) AllServices() []*service.Service {
return w.Services.Services.Services
}

View File

@ -16,7 +16,7 @@ import (
var destructor = func() {}
func main() {
gts.Main(func() gts.Window {
gts.Main(func() gts.MainApplication {
var app = ui.NewApplication()
// Load all cchat services.