Path: blob/main/internal/sidebar/sidebutton/pill.go
366 views
package sidebutton12import (3"github.com/diamondburned/gotk4/pkg/gtk/v4"4"github.com/diamondburned/gotkit/gtkutil/cssutil"5"github.com/diamondburned/ningen/v3"6)78type PillState uint8910// Pill state enums.11const (12PillInactive PillState = iota13PillDisabled14PillActive15PillOpened16)1718// CSSClass returns the CSS class for the current state.19func (s PillState) CSSClass() string {20switch s {21case PillInactive, PillDisabled:22return ""23case PillActive:24return "guilds-pill-active"25case PillOpened:26return "guilds-pill-opened"27default:28return ""29}30}3132type PillAttributes uint83334// Additional pill attributes.35const (36PillUnread PillAttributes = 1 << iota37PillMentioned38)3940// PillAttrsFromUnread creates a new PillAttributes reflecting the correct41// unread indication state.42func PillAttrsFromUnread(state ningen.UnreadIndication) PillAttributes {43var attrs PillAttributes4445switch state {46case ningen.ChannelUnread:47attrs |= PillUnread48case ningen.ChannelMentioned:49attrs |= PillUnread | PillMentioned50}5152return attrs53}5455// CSSClasses returns the CSS classes that corresponds to the current state of56// the pill.57func (a PillAttributes) CSSClasses() []string {58var classes []string59if a.Has(PillUnread) {60classes = append(classes, "guilds-pill-unread")61}62if a.Has(PillMentioned) {63classes = append(classes, "guilds-pill-mentioned")64}65return classes66}6768// Has returns true if a has these in its bits.69func (a PillAttributes) Has(these PillAttributes) bool {70return a&these == these71}7273type Pill struct {74*gtk.Box // width IconPadding7576State PillState77Attrs PillAttributes7879oldState PillState80oldAttrs PillAttributes81}8283var stripCSS = cssutil.Applier("guilds-pill", `84@define-color mentioned rgb(240, 71, 71);8586.guilds-pill {87padding: 0;88transition: 100ms linear;89border-radius: 0 99px 99px 0;90background-color: @theme_fg_color;91}92.guilds-pill.guilds-pill-active {93padding: 20px 3px;94}95.guilds-pill.guilds-pill-unread:not(.guilds-pill-opened):not(.guilds-pill-active) {96padding: 6px 3px;97}98.guilds-pill.guilds-pill-mentioned {99background-color: @mentioned;100}101`)102103func NewPill() *Pill {104p := Pill{}105p.Box = gtk.NewBox(gtk.OrientationHorizontal, 0)106p.Box.SetVExpand(true)107p.Box.SetVAlign(gtk.AlignCenter)108p.Box.SetHAlign(gtk.AlignStart)109110stripCSS(p)111return &p112}113114// Invalidate reads the 2 fields inside Pill and updates the widget accordingly.115func (r *Pill) Invalidate() {116if r.State != r.oldState {117if class := r.oldState.CSSClass(); class != "" {118r.RemoveCSSClass(r.oldState.CSSClass())119}120121r.oldState = r.State122123if class := r.oldState.CSSClass(); class != "" {124r.AddCSSClass(class)125}126}127128if r.Attrs != r.oldAttrs {129for _, class := range r.oldAttrs.CSSClasses() {130r.RemoveCSSClass(class)131}132133r.oldAttrs = r.Attrs134135for _, class := range r.oldAttrs.CSSClasses() {136r.AddCSSClass(class)137}138}139}140141142