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/messages/sadface/sadface.go

144 lines
3.1 KiB
Go

// Package sadface provides different views for the message container.
package sadface
import (
"strings"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives"
"github.com/gotk3/gotk3/gtk"
)
const FaceSize = 56
type WidgetUnreferencer interface {
gtk.IWidget
Unref()
}
type FaceView struct {
gtk.Stack
placeholder WidgetUnreferencer
Face *Container
Loading *Spinner
}
func New(parent gtk.IWidget, placeholder WidgetUnreferencer) *FaceView {
c := NewContainer()
c.Show()
s := NewSpinner()
s.Show()
// make an empty box for an empty page.
b, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
stack, _ := gtk.StackNew()
stack.SetTransitionType(gtk.STACK_TRANSITION_TYPE_CROSSFADE)
stack.SetTransitionDuration(75)
stack.AddNamed(parent, "main")
stack.AddNamed(placeholder, "placeholder")
stack.AddNamed(c, "face")
stack.AddNamed(s, "loading")
stack.AddNamed(b, "empty")
// Show placeholder by default.
stack.SetVisibleChildName("placeholder")
return &FaceView{*stack, placeholder, c, s}
}
// Reset brings the view to an empty box.
func (v *FaceView) Reset() {
v.Stack.SetVisibleChildName("empty")
v.ensurePlaceholderDestroyed()
v.Loading.Spinner.Stop()
}
func (v *FaceView) SetMain() {
v.Stack.SetVisibleChildName("main")
v.ensurePlaceholderDestroyed()
v.Loading.Spinner.Stop()
}
func (v *FaceView) SetLoading() {
v.ensurePlaceholderDestroyed()
v.Loading.Spinner.Start()
v.Stack.SetVisibleChildName("loading")
}
func (v *FaceView) SetError(err error) {
v.Face.SetError(err)
v.Stack.SetVisibleChildName("face")
v.ensurePlaceholderDestroyed()
v.Loading.Spinner.Stop()
}
func (v *FaceView) ensurePlaceholderDestroyed() {
// If the placeholder is still there:
if v.placeholder != nil {
// Safely remove the placeholder from the stack.
if v.Stack.GetVisibleChildName() == "placeholder" {
v.Stack.SetVisibleChildName("main")
}
// Remove the placeholder widget.
v.Stack.Remove(v.placeholder)
v.placeholder = nil
}
}
type Spinner struct {
gtk.Box
Spinner *gtk.Spinner
}
func NewSpinner() *Spinner {
s, _ := gtk.SpinnerNew()
s.SetSizeRequest(FaceSize, FaceSize)
s.Start()
s.Show()
b, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
b.Add(s)
b.SetHAlign(gtk.ALIGN_CENTER)
b.SetVAlign(gtk.ALIGN_CENTER)
return &Spinner{*b, s}
}
type Container struct {
gtk.Box
Face *gtk.Image
Error *gtk.Label
}
func NewContainer() *Container {
face, _ := gtk.ImageNew()
face.SetSizeRequest(FaceSize, FaceSize)
face.Show()
primitives.SetImageIcon(face, "face-sad-symbolic", FaceSize)
errlabel, _ := gtk.LabelNew("")
errlabel.SetOpacity(0.75) // low contrast good because unreadable
errlabel.Show()
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 15)
box.SetVAlign(gtk.ALIGN_CENTER)
box.SetHAlign(gtk.ALIGN_CENTER)
box.PackStart(face, false, false, 0)
box.PackStart(errlabel, false, false, 0)
return &Container{*box, face, errlabel}
}
// SetError sets the view to display the error. Error must not be nil.
func (v *Container) SetError(err error) {
// Split the error.
parts := strings.Split(err.Error(), ": ")
v.Error.SetLabel("Error: " + parts[len(parts)-1])
// Use the full error for the tooltip.
v.Box.SetTooltipText(err.Error())
}