1
0
Fork 0
mirror of https://github.com/diamondburned/cchat-gtk.git synced 2024-11-01 03:54:16 +00:00
cchat-gtk/internal/ui/rich/image.go

163 lines
3.3 KiB
Go
Raw Normal View History

2020-06-06 07:44:36 +00:00
package rich
import (
"github.com/diamondburned/cchat"
"github.com/diamondburned/cchat-gtk/internal/gts"
"github.com/diamondburned/cchat-gtk/internal/gts/httputil"
"github.com/diamondburned/cchat-gtk/internal/log"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives"
"github.com/diamondburned/cchat/text"
"github.com/diamondburned/imgutil"
"github.com/gotk3/gotk3/gtk"
"github.com/pkg/errors"
)
type Icon struct {
*gtk.Revealer
2020-06-07 07:06:13 +00:00
Image *gtk.Image
2020-06-06 07:44:36 +00:00
resizer imgutil.Processor
procs []imgutil.Processor
2020-06-07 07:06:13 +00:00
// state
url string
2020-06-06 07:44:36 +00:00
}
const DefaultIconSize = 16
var _ cchat.IconContainer = (*Icon)(nil)
func NewIcon(sizepx int, procs ...imgutil.Processor) *Icon {
if sizepx == 0 {
sizepx = DefaultIconSize
}
img, _ := gtk.ImageNew()
img.Show()
img.SetSizeRequest(sizepx, sizepx)
rev, _ := gtk.RevealerNew()
rev.Add(img)
rev.SetRevealChild(false)
rev.SetTransitionType(gtk.REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
rev.SetTransitionDuration(50)
return &Icon{
Revealer: rev,
Image: img,
resizer: imgutil.Resize(sizepx, sizepx),
procs: procs,
}
}
2020-06-07 07:06:13 +00:00
// Reset wipes the state to be just after construction.
func (i *Icon) Reset() {
i.url = ""
i.Revealer.SetRevealChild(false)
i.Image.SetFromPixbuf(nil) // destroy old pb
2020-06-07 07:06:13 +00:00
}
2020-06-07 04:27:28 +00:00
// URL is not thread-safe.
func (i *Icon) URL() string {
return i.url
}
func (i *Icon) CopyPixbuf(dst httputil.ImageContainer) {
switch i.Image.GetStorageType() {
case gtk.IMAGE_PIXBUF:
dst.SetFromPixbuf(i.Image.GetPixbuf())
case gtk.IMAGE_ANIMATION:
dst.SetFromAnimation(i.Image.GetAnimation())
}
}
// Thread-unsafe setter methods should only be called right after construction.
2020-06-06 07:44:36 +00:00
// SetPlaceholderIcon is not thread-safe.
func (i *Icon) SetPlaceholderIcon(iconName string, iconSzPx int) {
i.SetRevealChild(true)
i.SetSize(iconSzPx)
if iconName != "" {
primitives.SetImageIcon(i.Image, iconName, iconSzPx)
}
}
// SetSize is not thread-safe.
func (i *Icon) SetSize(szpx int) {
i.Image.SetSizeRequest(szpx, szpx)
i.resizer = imgutil.Resize(szpx, szpx)
}
// AddProcessors is not thread-safe.
func (i *Icon) AddProcessors(procs ...imgutil.Processor) {
i.procs = append(i.procs, procs...)
}
// SetIcon is thread-safe.
func (i *Icon) SetIcon(url string) {
2020-06-07 04:27:28 +00:00
gts.ExecAsync(func() {
i.SetIconUnsafe(url)
})
}
func (i *Icon) AsyncSetIcon(fn func(cchat.IconContainer) error, wrap string) {
go func() {
if err := fn(i); err != nil {
log.Error(errors.Wrap(err, wrap))
}
}()
}
2020-06-07 04:27:28 +00:00
// SetIconUnsafe is not thread-safe.
func (i *Icon) SetIconUnsafe(url string) {
i.SetRevealChild(true)
2020-06-06 07:44:36 +00:00
i.url = url
i.updateAsync()
}
func (i *Icon) updateAsync() {
httputil.AsyncImage(i.Image, i.url, imgutil.Prepend(i.resizer, i.procs)...)
}
type ToggleButtonImage struct {
gtk.ToggleButton
Labeler
cchat.IconContainer
Label *gtk.Label
Image *Icon
Box *gtk.Box
}
var (
_ gtk.IWidget = (*ToggleButton)(nil)
_ cchat.LabelContainer = (*ToggleButton)(nil)
)
func NewToggleButtonImage(content text.Rich) *ToggleButtonImage {
l := NewLabel(content)
l.Show()
i := NewIcon(0)
i.Show()
box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
box.PackStart(i, false, false, 0)
box.PackStart(l, true, true, 5)
box.Show()
b, _ := gtk.ToggleButtonNew()
b.Add(box)
return &ToggleButtonImage{
ToggleButton: *b,
Labeler: l, // easy inheritance of methods
IconContainer: i,
Label: &l.Label,
Image: i,
Box: box,
}
}