Files
aego/ui/widgets/toolbar.go
T

175 lines
4.0 KiB
Go

package widgets
import (
"math"
"strings"
"aego/core/mathx"
"aego/ui/core"
)
type DotState uint8
const (
DotIdle DotState = iota
DotBusy
DotOK
DotError
)
func IconAt(c *core.Context, r mathx.Rect, id string, tint mathx.Color) {
r = snap(r, c.Scale())
if c.Icons != nil {
if reg, ok := c.Icons.Region(id, r.H, c.Scale()); ok {
c.List().Texture(reg, r, tint)
return
}
}
th := &c.Theme
c.Rect(r, th.Badge)
name := id
if i := strings.LastIndexByte(id, '.'); i >= 0 {
name = id[i+1:]
}
if name != "" {
c.TextIn(r, strings.ToUpper(name[:1]), th.TextDim, core.AlignCenter)
}
}
type Toolbar struct {
c *core.Context
r mathx.Rect
x float32
Active mathx.Color
Label mathx.Color
}
func BeginToolbar(c *core.Context, r mathx.Rect) Toolbar {
th := &c.Theme
c.Rect(r, th.BarBg)
c.Rect(mathx.Rect{X: r.X, Y: r.Y + r.H - 1, W: r.W, H: 1}, th.BarBorder)
return Toolbar{c: c, r: r, x: r.X + 6}
}
func BeginToolbarIn(c *core.Context, r mathx.Rect) Toolbar {
return Toolbar{c: c, r: r, x: r.X + 6}
}
func (t *Toolbar) X() float32 {
return t.x
}
func (t *Toolbar) SetX(x float32) {
t.x = x
}
func (t *Toolbar) ButtonW() float32 {
return t.r.H - 6 + 2
}
func (t *Toolbar) Button(id core.ID, icon, tooltip string, active, enabled bool) bool {
return t.TintButton(id, icon, tooltip, active, enabled, t.c.Theme.Text)
}
func (t *Toolbar) TintButton(id core.ID, icon, tooltip string, active, enabled bool, tint mathx.Color) bool {
c := t.c
th := &c.Theme
s := t.r.H - 6
br := mathx.Rect{X: t.x, Y: t.r.Y + 3, W: s, H: s}
t.x += s + 2
clicked := false
if enabled {
clicked = c.Clicked(id, br)
} else {
c.MouseOver(id, br)
}
switch {
case active:
bg := th.ButtonActive
if t.Active.A > 0 {
bg = t.Active
}
c.RoundRect(br, th.Radius.Button, bg)
case enabled && (c.Hot() == id || c.Active() == id):
c.RoundRect(br, th.Radius.Button, th.ButtonHover)
}
if !enabled {
tint = th.TextDisabled
}
is := min(float32(16), s-4)
ix, iy := float32(int(br.X+(s-is)/2)), float32(int(br.Y+(s-is)/2))
IconAt(c, mathx.Rect{X: ix, Y: iy, W: is, H: is}, icon, tint)
Tooltip(c, id, tooltip)
return clicked
}
func (t *Toolbar) TextButton(id core.ID, label, tooltip string) (bool, mathx.Rect) {
c := t.c
th := &c.Theme
w := c.TextSize(label).X + 14
br := mathx.Rect{X: t.x, Y: t.r.Y + 3, W: w, H: t.r.H - 6}
t.x += w + 2
clicked := c.Clicked(id, br)
if c.Hot() == id || c.Active() == id {
c.RoundRect(br, th.Radius.Button, th.ButtonHover)
}
col := th.TextDim
if t.Label.A > 0 {
col = t.Label
}
c.TextIn(br, label, col, core.AlignCenter)
Tooltip(c, id, tooltip)
return clicked, br
}
func (t *Toolbar) Separator() {
t.x += 4
t.c.Rect(mathx.Rect{X: t.x, Y: t.r.Y + 6, W: 1, H: t.r.H - 12}, t.c.Theme.BarBorder)
t.x += 5
}
func StatusDot(c *core.Context, id core.ID, r mathx.Rect, state DotState, label string) bool {
th := &c.Theme
clicked := c.Clicked(id, r)
if c.Hot() == id {
c.Rect(r, th.ButtonHover)
}
col := th.TextDisabled
switch state {
case DotBusy:
col = th.Warn
case DotOK:
col = th.Ok
case DotError:
col = th.Error
}
d := mathx.Rect{X: r.X + 6, Y: r.Y + (r.H-8)/2, W: 8, H: 8}
c.Rect(d, col)
c.Text(label, mathx.Vec2{X: d.X + d.W + 6, Y: c.TextY(r)}, th.TextDim)
return clicked
}
func IconButton(c *core.Context, id core.ID, r mathx.Rect, icon, tooltip string) bool {
th := &c.Theme
clicked := c.Clicked(id, r)
tint := th.TextDim
if c.Hot() == id || c.Active() == id {
c.RoundRect(r, th.Radius.Button, th.ButtonHover)
tint = th.Text
}
is := min(float32(16), min(r.W, r.H)-4)
ix, iy := float32(int(r.X+(r.W-is)/2)), float32(int(r.Y+(r.H-is)/2))
IconAt(c, mathx.Rect{X: ix, Y: iy, W: is, H: is}, icon, tint)
Tooltip(c, id, tooltip)
return clicked
}
func snap(r mathx.Rect, scale float32) mathx.Rect {
if scale <= 0 {
scale = 1
}
round := func(v float32) float32 { return float32(math.Round(float64(v*scale))) / scale }
x, y := round(r.X), round(r.Y)
return mathx.Rect{X: x, Y: y, W: round(r.X+r.W) - x, H: round(r.Y+r.H) - y}
}