2020-08-29 01:42:28 +00:00
|
|
|
package roundimage
|
|
|
|
|
|
|
|
import (
|
2020-12-20 09:48:52 +00:00
|
|
|
"context"
|
|
|
|
|
2020-08-29 01:42:28 +00:00
|
|
|
"github.com/diamondburned/cchat-gtk/internal/gts/httputil"
|
|
|
|
"github.com/diamondburned/handy"
|
|
|
|
"github.com/gotk3/gotk3/gdk"
|
|
|
|
"github.com/gotk3/gotk3/gtk"
|
|
|
|
)
|
|
|
|
|
|
|
|
// TODO: GIF support
|
|
|
|
|
|
|
|
// TextSetter is an interface for setting texts.
|
|
|
|
type TextSetter interface {
|
|
|
|
SetText(text string)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TrySetText(imager Imager, text string) {
|
|
|
|
if setter, ok := imager.(TextSetter); ok {
|
|
|
|
setter.SetText(text)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Avatar is a static HdyAvatar container.
|
|
|
|
type Avatar struct {
|
|
|
|
handy.Avatar
|
|
|
|
pixbuf *gdk.Pixbuf
|
2020-12-20 09:48:52 +00:00
|
|
|
url string
|
2020-12-20 08:18:23 +00:00
|
|
|
size int
|
2021-03-29 21:46:52 +00:00
|
|
|
cancel context.CancelFunc
|
2020-08-29 01:42:28 +00:00
|
|
|
}
|
|
|
|
|
2020-12-20 08:18:23 +00:00
|
|
|
// Make a better API that allows scaling.
|
|
|
|
|
2020-08-29 01:42:28 +00:00
|
|
|
var (
|
|
|
|
_ Imager = (*Avatar)(nil)
|
|
|
|
_ TextSetter = (*Avatar)(nil)
|
|
|
|
_ httputil.ImageContainer = (*Avatar)(nil)
|
|
|
|
)
|
|
|
|
|
|
|
|
func NewAvatar(size int) *Avatar {
|
2020-12-20 08:18:23 +00:00
|
|
|
avatar := Avatar{
|
|
|
|
Avatar: *handy.AvatarNew(size, "", true),
|
|
|
|
size: size,
|
2020-08-29 01:42:28 +00:00
|
|
|
}
|
2020-12-20 08:18:23 +00:00
|
|
|
// Set the load function. This should hopefully trigger a reload.
|
|
|
|
avatar.SetImageLoadFunc(avatar.loadFunc)
|
|
|
|
|
|
|
|
return &avatar
|
|
|
|
}
|
2020-08-29 01:42:28 +00:00
|
|
|
|
2021-03-29 21:46:52 +00:00
|
|
|
// GetSizeRequest returns the virtual size.
|
2020-12-20 08:18:23 +00:00
|
|
|
func (a *Avatar) GetSizeRequest() (int, int) {
|
|
|
|
return a.size, a.size
|
2020-08-29 01:42:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetSizeRequest sets the avatar size. The actual size is min(w, h).
|
|
|
|
func (a *Avatar) SetSizeRequest(w, h int) {
|
|
|
|
var min = w
|
|
|
|
if w > h {
|
|
|
|
min = h
|
|
|
|
}
|
|
|
|
|
2020-12-20 09:48:52 +00:00
|
|
|
a.size = min
|
2020-08-29 01:42:28 +00:00
|
|
|
a.Avatar.SetSize(min)
|
|
|
|
a.Avatar.SetSizeRequest(w, h)
|
|
|
|
}
|
|
|
|
|
2020-12-20 08:18:23 +00:00
|
|
|
func (a *Avatar) loadFunc(size int) *gdk.Pixbuf {
|
2020-12-20 09:48:52 +00:00
|
|
|
if a.url == "" {
|
2020-12-20 08:18:23 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-12-20 09:48:52 +00:00
|
|
|
if a.pixbuf != nil && a.size == size {
|
|
|
|
return a.pixbuf
|
|
|
|
}
|
2020-12-20 08:18:23 +00:00
|
|
|
|
2020-12-20 09:48:52 +00:00
|
|
|
a.size = size
|
2021-03-29 21:46:52 +00:00
|
|
|
a.refetch()
|
2020-12-20 08:18:23 +00:00
|
|
|
|
2021-03-29 21:46:52 +00:00
|
|
|
return nil
|
|
|
|
}
|
2020-12-20 08:18:23 +00:00
|
|
|
|
2021-03-29 21:46:52 +00:00
|
|
|
func (a *Avatar) refetch() {
|
|
|
|
a.cancelCtx()
|
2020-12-20 09:48:52 +00:00
|
|
|
|
2021-03-29 21:46:52 +00:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
a.cancel = cancel
|
|
|
|
|
|
|
|
httputil.AsyncImage(ctx, a, a.url)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *Avatar) cancelCtx() {
|
|
|
|
if a.cancel != nil {
|
|
|
|
a.cancel()
|
|
|
|
a.cancel = nil
|
|
|
|
}
|
2020-08-29 01:42:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetRadius is a no-op.
|
|
|
|
func (a *Avatar) SetRadius(float64) {}
|
|
|
|
|
2021-03-29 21:46:52 +00:00
|
|
|
// SetImageURL sets the avatar's source URL and reloads it asynchronously.
|
2020-12-20 09:48:52 +00:00
|
|
|
func (a *Avatar) SetImageURL(url string) {
|
|
|
|
a.url = url
|
2021-03-29 21:46:52 +00:00
|
|
|
a.refetch()
|
2020-12-20 09:48:52 +00:00
|
|
|
}
|
|
|
|
|
2020-08-29 01:42:28 +00:00
|
|
|
// SetFromPixbuf sets the pixbuf.
|
|
|
|
func (a *Avatar) SetFromPixbuf(pb *gdk.Pixbuf) {
|
2021-03-29 21:46:52 +00:00
|
|
|
a.cancelCtx()
|
2020-08-29 01:42:28 +00:00
|
|
|
a.pixbuf = pb
|
2021-03-29 21:46:52 +00:00
|
|
|
// a.Avatar.SetImageLoadFunc(a.loadFunc)
|
|
|
|
a.Avatar.QueueDraw()
|
2020-08-29 01:42:28 +00:00
|
|
|
}
|
|
|
|
|
2021-03-29 21:46:52 +00:00
|
|
|
// SetFromAnimation sets the first frame of the animation.
|
2020-08-29 01:42:28 +00:00
|
|
|
func (a *Avatar) SetFromAnimation(pa *gdk.PixbufAnimation) {
|
2021-03-29 21:46:52 +00:00
|
|
|
a.cancelCtx()
|
2020-08-29 01:42:28 +00:00
|
|
|
a.pixbuf = pa.GetStaticImage()
|
2021-03-29 21:46:52 +00:00
|
|
|
// a.Avatar.SetImageLoadFunc(a.loadFunc)
|
|
|
|
a.Avatar.QueueDraw()
|
2020-08-29 01:42:28 +00:00
|
|
|
}
|
|
|
|
|
2021-03-29 21:46:52 +00:00
|
|
|
// GetPixbuf returns the underlying pixbuf.
|
2020-08-29 01:42:28 +00:00
|
|
|
func (a *Avatar) GetPixbuf() *gdk.Pixbuf {
|
|
|
|
return a.pixbuf
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetAnimation returns nil.
|
|
|
|
func (a *Avatar) GetAnimation() *gdk.PixbufAnimation {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetImage returns nil.
|
|
|
|
func (a *Avatar) GetImage() *gtk.Image {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-03-29 21:46:52 +00:00
|
|
|
// GetStorageType always returns IMAGE_PIXBUF.
|
2020-08-29 01:42:28 +00:00
|
|
|
func (a *Avatar) GetStorageType() gtk.ImageType {
|
|
|
|
return gtk.IMAGE_PIXBUF
|
|
|
|
}
|