Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
diamondburned
GitHub Repository: diamondburned/gtkcord4
Path: blob/main/internal/sidebar/sidebutton/pill.go
366 views
1
package sidebutton
2
3
import (
4
"github.com/diamondburned/gotk4/pkg/gtk/v4"
5
"github.com/diamondburned/gotkit/gtkutil/cssutil"
6
"github.com/diamondburned/ningen/v3"
7
)
8
9
type PillState uint8
10
11
// Pill state enums.
12
const (
13
PillInactive PillState = iota
14
PillDisabled
15
PillActive
16
PillOpened
17
)
18
19
// CSSClass returns the CSS class for the current state.
20
func (s PillState) CSSClass() string {
21
switch s {
22
case PillInactive, PillDisabled:
23
return ""
24
case PillActive:
25
return "guilds-pill-active"
26
case PillOpened:
27
return "guilds-pill-opened"
28
default:
29
return ""
30
}
31
}
32
33
type PillAttributes uint8
34
35
// Additional pill attributes.
36
const (
37
PillUnread PillAttributes = 1 << iota
38
PillMentioned
39
)
40
41
// PillAttrsFromUnread creates a new PillAttributes reflecting the correct
42
// unread indication state.
43
func PillAttrsFromUnread(state ningen.UnreadIndication) PillAttributes {
44
var attrs PillAttributes
45
46
switch state {
47
case ningen.ChannelUnread:
48
attrs |= PillUnread
49
case ningen.ChannelMentioned:
50
attrs |= PillUnread | PillMentioned
51
}
52
53
return attrs
54
}
55
56
// CSSClasses returns the CSS classes that corresponds to the current state of
57
// the pill.
58
func (a PillAttributes) CSSClasses() []string {
59
var classes []string
60
if a.Has(PillUnread) {
61
classes = append(classes, "guilds-pill-unread")
62
}
63
if a.Has(PillMentioned) {
64
classes = append(classes, "guilds-pill-mentioned")
65
}
66
return classes
67
}
68
69
// Has returns true if a has these in its bits.
70
func (a PillAttributes) Has(these PillAttributes) bool {
71
return a&these == these
72
}
73
74
type Pill struct {
75
*gtk.Box // width IconPadding
76
77
State PillState
78
Attrs PillAttributes
79
80
oldState PillState
81
oldAttrs PillAttributes
82
}
83
84
var stripCSS = cssutil.Applier("guilds-pill", `
85
@define-color mentioned rgb(240, 71, 71);
86
87
.guilds-pill {
88
padding: 0;
89
transition: 100ms linear;
90
border-radius: 0 99px 99px 0;
91
background-color: @theme_fg_color;
92
}
93
.guilds-pill.guilds-pill-active {
94
padding: 20px 3px;
95
}
96
.guilds-pill.guilds-pill-unread:not(.guilds-pill-opened):not(.guilds-pill-active) {
97
padding: 6px 3px;
98
}
99
.guilds-pill.guilds-pill-mentioned {
100
background-color: @mentioned;
101
}
102
`)
103
104
func NewPill() *Pill {
105
p := Pill{}
106
p.Box = gtk.NewBox(gtk.OrientationHorizontal, 0)
107
p.Box.SetVExpand(true)
108
p.Box.SetVAlign(gtk.AlignCenter)
109
p.Box.SetHAlign(gtk.AlignStart)
110
111
stripCSS(p)
112
return &p
113
}
114
115
// Invalidate reads the 2 fields inside Pill and updates the widget accordingly.
116
func (r *Pill) Invalidate() {
117
if r.State != r.oldState {
118
if class := r.oldState.CSSClass(); class != "" {
119
r.RemoveCSSClass(r.oldState.CSSClass())
120
}
121
122
r.oldState = r.State
123
124
if class := r.oldState.CSSClass(); class != "" {
125
r.AddCSSClass(class)
126
}
127
}
128
129
if r.Attrs != r.oldAttrs {
130
for _, class := range r.oldAttrs.CSSClasses() {
131
r.RemoveCSSClass(class)
132
}
133
134
r.oldAttrs = r.Attrs
135
136
for _, class := range r.oldAttrs.CSSClasses() {
137
r.AddCSSClass(class)
138
}
139
}
140
}
141
142