zntg/ui/checkbox.go

135 lines
3.5 KiB
Go

package ui
import (
"opslag.de/schobers/geom"
)
type Checkbox struct {
ControlBase
selectedChanged Events
Selected bool
Text string
}
func BuildCheckbox(text string, fn func(c *Checkbox)) *Checkbox {
var c = &Checkbox{Text: text}
if fn != nil {
fn(c)
}
return c
}
func (c *Checkbox) desiredSize(ctx Context) geom.PointF32 {
pad := c.ActualTextPadding(ctx)
font := c.ActualFont(ctx)
var w, h float32 = 0, font.Height()
if len(c.Text) != 0 {
w += pad.Left + font.WidthOf(c.Text)
}
icon := c.getOrCreateNormalIcon(ctx)
_, iconWidth := ScaleToHeight(SizeOfTexture(icon).ToF32(), h)
w += pad.Left + iconWidth
return geom.PtF32(w+pad.Right, pad.Top+h+pad.Bottom)
}
func (c *Checkbox) icon(ctx Context) Texture {
if c.Selected {
return GetOrCreateIcon(ctx, "ui-default-checkbox-selected", c.selectedIcon)
} else if c.over && !c.Disabled {
return GetOrCreateIcon(ctx, "ui-default-checkbox-hover", c.hoverIcon)
}
return c.getOrCreateNormalIcon(ctx)
}
func (c *Checkbox) getOrCreateNormalIcon(ctx Context) Texture {
return GetOrCreateIcon(ctx, "ui-default-checkbox", c.normalIcon)
}
var checkBoxIconBorder = geom.PolF32(
geom.PtF32(48, 80),
geom.PtF32(400, 80),
geom.PtF32(400, 432),
geom.PtF32(48, 432),
)
var checkBoxCheckMark = geom.PointsF32{
geom.PtF32(96, 256),
geom.PtF32(180, 340),
geom.PtF32(340, 150),
}
func (c *Checkbox) hoverIcon(pt geom.PointF32) bool {
return (pt.DistanceToPolygon(checkBoxIconBorder) < 48 && !pt.InPolygon(checkBoxIconBorder)) || pt.DistanceToLines(checkBoxCheckMark) < 24
}
func (c *Checkbox) normalIcon(pt geom.PointF32) bool {
return pt.DistanceToPolygon(checkBoxIconBorder) < 48 && !pt.InPolygon(checkBoxIconBorder)
}
func (c *Checkbox) selectedIcon(pt geom.PointF32) bool {
if pt.DistanceToPolygon(checkBoxIconBorder) < 48 || pt.InPolygon(checkBoxIconBorder) {
return pt.DistanceToLines(checkBoxCheckMark) > 24
}
return false
}
func (c *Checkbox) DesiredSize(ctx Context, _ geom.PointF32) geom.PointF32 { return c.desiredSize(ctx) }
func (c *Checkbox) Handle(ctx Context, e Event) bool {
result := c.ControlBase.Handle(ctx, e)
if c.over {
if c.Disabled {
return true
}
ctx.Renderer().SetMouseCursor(MouseCursorPointer)
}
if result {
return true
}
switch e := e.(type) {
case *MouseButtonDownEvent:
if e.Button == MouseButtonLeft && c.over {
c.Selected = !c.Selected
return c.selectedChanged.Notify(ctx, c.Selected)
}
}
return false
}
func (c *Checkbox) SelectedChanged() EventHandler { return &c.selectedChanged }
func (c *Checkbox) Render(ctx Context) {
c.RenderBackground(ctx)
var style = ctx.Style()
var palette = style.Palette
fore := c.TextColor(ctx)
bounds := c.bounds
pad := c.ActualTextPadding(ctx)
bounds = pad.InsetRect(bounds)
boundsH := bounds.Dy()
pos := bounds.Min
icon := c.icon(ctx)
if icon != nil {
iconColor := fore
if c.Selected {
iconColor = c.FontColor(ctx, palette.Primary)
}
scaledIcon, _ := ctx.Textures().ScaledHeight(icon, boundsH) // try to pre-scale icon
if scaledIcon == nil { // let the renderer scale
scaledIcon = icon
}
_, iconWidth := ScaleToHeight(SizeOfTexture(scaledIcon).ToF32(), boundsH)
rect := geom.RectRelF32(pos.X, pos.Y, iconWidth, boundsH)
ctx.Renderer().DrawTextureOptions(scaledIcon, rect, DrawOptions{Tint: iconColor})
pos.X += iconWidth + pad.Right
}
if len(c.Text) != 0 {
font := c.ActualFont(ctx)
ctx.Renderer().Text(font, geom.PtF32(pos.X, pos.Y+.5*(boundsH-font.Height())), fore, c.Text)
}
}