1
0
Fork 0
mirror of https://github.com/diamondburned/cchat-gtk.git synced 2024-11-16 03:02:45 +00:00
cchat-gtk/internal/ui/messages/message/message.go

191 lines
4.7 KiB
Go
Raw Normal View History

2020-06-06 07:44:36 +00:00
package message
2020-05-26 06:51:06 +00:00
import (
"time"
"github.com/diamondburned/cchat"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives/menu"
"github.com/diamondburned/cchat-gtk/internal/ui/rich"
"github.com/diamondburned/cchat-gtk/internal/ui/rich/labeluri"
2020-05-26 06:51:06 +00:00
"github.com/diamondburned/cchat/text"
"github.com/gotk3/gotk3/gtk"
"github.com/gotk3/gotk3/pango"
)
2020-06-06 07:44:36 +00:00
type Container interface {
2021-01-05 02:05:33 +00:00
ID() cchat.ID
2020-10-24 21:58:48 +00:00
Time() time.Time
2021-01-05 02:05:33 +00:00
Author() cchat.Author
2020-06-06 07:44:36 +00:00
Nonce() string
2020-10-15 06:32:11 +00:00
UpdateAuthor(cchat.Author)
UpdateContent(c text.Rich, edited bool)
2020-06-06 07:44:36 +00:00
UpdateTimestamp(time.Time)
}
// FillContainer sets the container's contents to the one from MessageCreate.
2020-06-07 04:27:28 +00:00
func FillContainer(c Container, msg cchat.MessageCreate) {
c.UpdateAuthor(msg.Author())
c.UpdateContent(msg.Content(), false)
2020-06-07 04:27:28 +00:00
c.UpdateTimestamp(msg.Time())
}
// RefreshContainer sets the container's contents to the one from
// GenericContainer. This is mainly used for transferring between different
// containers.
func RefreshContainer(c Container, gc *GenericContainer) {
c.UpdateTimestamp(gc.time)
}
2020-06-06 07:44:36 +00:00
// GenericContainer provides a single generic message container for subpackages
// to use.
type GenericContainer struct {
*gtk.Box
row *gtk.ListBoxRow // contains Box
class string
2021-01-05 02:05:33 +00:00
id string
time time.Time
author Author
nonce string
2020-05-26 06:51:06 +00:00
2021-01-05 02:05:33 +00:00
Content *gtk.Box
ContentBody *labeluri.Label
ContentBodyStyle *gtk.StyleContext
menuItems []menu.Item
2020-05-26 06:51:06 +00:00
}
2020-06-06 07:44:36 +00:00
var _ Container = (*GenericContainer)(nil)
2020-06-07 04:27:28 +00:00
// NewContainer creates a new message container with the given ID and nonce. It
// does not update the widgets, so FillContainer should be called afterwards.
2020-06-06 07:44:36 +00:00
func NewContainer(msg cchat.MessageCreate) *GenericContainer {
c := NewEmptyContainer()
c.id = msg.ID()
c.time = msg.Time()
2020-10-15 06:32:11 +00:00
c.nonce = msg.Nonce()
2021-01-05 02:05:33 +00:00
c.author.Update(msg.Author())
2020-06-04 23:00:41 +00:00
2020-06-06 07:44:36 +00:00
return c
2020-06-04 23:00:41 +00:00
}
2020-06-06 07:44:36 +00:00
func NewEmptyContainer() *GenericContainer {
ctbody := labeluri.NewLabel(text.Rich{})
ctbody.SetVExpand(true)
ctbody.SetHAlign(gtk.ALIGN_START)
ctbody.SetEllipsize(pango.ELLIPSIZE_NONE)
2020-07-10 23:26:07 +00:00
ctbody.SetLineWrap(true)
ctbody.SetLineWrapMode(pango.WRAP_WORD_CHAR)
ctbody.SetXAlign(0) // left align
ctbody.SetSelectable(true)
ctbody.SetTrackVisitedLinks(false)
2020-07-10 23:26:07 +00:00
ctbody.Show()
2021-01-05 02:05:33 +00:00
ctbodyStyle, _ := ctbody.GetStyleContext()
ctbodyStyle.AddClass("message-content")
2020-07-10 23:26:07 +00:00
// Wrap the content label inside a content box.
ctbox, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
ctbox.SetHExpand(true)
2020-07-10 23:26:07 +00:00
ctbox.PackStart(ctbody, false, false, 0)
ctbox.Show()
2020-05-26 06:51:06 +00:00
box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
box.Show()
row, _ := gtk.ListBoxRowNew()
row.Add(box)
row.Show()
primitives.AddClass(row, "message-row")
2020-07-06 00:19:48 +00:00
gc := &GenericContainer{
Box: box,
row: row,
2021-01-05 02:05:33 +00:00
Content: ctbox,
ContentBody: ctbody,
ContentBodyStyle: ctbodyStyle,
2020-10-24 21:58:48 +00:00
// Time is important, as it is used to sort messages, so we have to be
// careful with this.
time: time.Now(),
2020-05-26 06:51:06 +00:00
}
2020-07-10 23:26:07 +00:00
// Bind the custom popup menu to the content label.
gc.ContentBody.Connect("populate-popup", func(l *gtk.Label, m *gtk.Menu) {
menu.MenuSeparator(m)
menu.MenuItems(m, gc.menuItems)
})
return gc
2020-06-04 23:00:41 +00:00
}
2020-05-26 06:51:06 +00:00
// Row returns the internal list box row. It is used to satisfy MessageRow.
func (m *GenericContainer) Row() *gtk.ListBoxRow { return m.row }
// SetClass sets the internal row's class.
func (m *GenericContainer) SetClass(class string) {
if m.class != "" {
primitives.RemoveClass(m.row, m.class)
}
primitives.AddClass(m.row, class)
m.class = class
}
// SetReferenceHighlighter sets the reference highlighter into the message.
func (m *GenericContainer) SetReferenceHighlighter(r labeluri.ReferenceHighlighter) {
m.ContentBody.SetReferenceHighlighter(r)
}
2020-06-06 07:44:36 +00:00
func (m *GenericContainer) ID() string {
return m.id
}
func (m *GenericContainer) Time() time.Time {
return m.time
}
2021-01-05 02:05:33 +00:00
func (m *GenericContainer) Author() cchat.Author {
return m.author
}
2020-06-06 07:44:36 +00:00
func (m *GenericContainer) Nonce() string {
return m.nonce
2020-05-28 19:26:55 +00:00
}
2020-06-06 07:44:36 +00:00
func (m *GenericContainer) UpdateTimestamp(t time.Time) {
m.time = t
2020-06-04 23:00:41 +00:00
}
2020-10-15 06:32:11 +00:00
func (m *GenericContainer) UpdateAuthor(author cchat.Author) {
2021-01-05 02:05:33 +00:00
m.author.Update(author)
2020-05-26 06:51:06 +00:00
}
func (m *GenericContainer) UpdateContent(content text.Rich, edited bool) {
m.ContentBody.SetLabelUnsafe(content)
if edited {
markup := m.ContentBody.Output().Markup
markup += " " + rich.Small("(edited)")
m.ContentBody.SetMarkup(markup)
}
}
// AttachMenu connects signal handlers to handle a list of menu items from
// the container.
func (m *GenericContainer) AttachMenu(newItems []menu.Item) {
m.menuItems = newItems
}
// MenuItems returns the list of menu items for this message.
func (m *GenericContainer) MenuItems() []menu.Item {
return m.menuItems
2020-05-26 06:51:06 +00:00
}
2020-08-20 23:53:13 +00:00
func (m *GenericContainer) Focusable() gtk.IWidget {
return m.Content
}