zntg/ui/checkbox.go
Sander Schobers d072e202ab Added checkbox.
Added utility methods for generating icons.
2019-04-11 21:23:51 +02:00

115 lines
2.8 KiB
Go

package ui
import (
"opslag.de/schobers/geom"
)
type Checkbox struct {
ControlBase
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 {
var pad = ctx.Style().Dimensions.TextPadding
var font = ctx.Renderer().Font(c.FontName(ctx))
var w, h float32 = 0, font.Height()
if len(c.Text) != 0 {
w += pad + font.WidthOf(c.Text)
}
icon, _ := ctx.Images().ScaledHeight(c.icon(ctx, false), h)
w += pad + icon.Width()
return geom.PtF32(w+pad, pad+h+pad)
}
func (c *Checkbox) icon(ctx Context, selected bool) Image {
if selected {
return GetOrCreateIcon(ctx, "ui-default-checkbox-selected", c.selectedIcon)
}
return GetOrCreateIcon(ctx, "ui-default-checkbox", c.normalIcon)
}
func (c *Checkbox) iconBorder() geom.PolygonF32 {
return geom.PolF32(
geom.PtF32(48, 80),
geom.PtF32(400, 80),
geom.PtF32(400, 432),
geom.PtF32(48, 432),
)
}
func (c *Checkbox) normalIcon() IconPixelTestFn {
border := c.iconBorder()
return func(pt geom.PointF32) bool {
return pt.DistanceToPolygon(border) < 48 && !pt.InPolygon(border)
}
}
func (c *Checkbox) selectedIcon() IconPixelTestFn {
border := c.iconBorder()
check := geom.PointsF32{
geom.PtF32(84, 256),
geom.PtF32(180, 352),
geom.PtF32(352, 150),
}
return func(pt geom.PointF32) bool {
if pt.DistanceToPolygon(border) < 48 || pt.InPolygon(border) {
return pt.DistanceToLines(check) > 24
}
return false
}
}
func (c *Checkbox) DesiredSize(ctx Context) geom.PointF32 { return c.desiredSize(ctx) }
func (c *Checkbox) Handle(ctx Context, e Event) {
switch e := e.(type) {
case *MouseButtonDownEvent:
if e.Button == MouseButtonLeft && c.over {
c.Selected = !c.Selected
}
}
c.ControlBase.Handle(ctx, e)
if c.over {
ctx.Renderer().SetMouseCursor(MouseCursorPointer)
}
}
func (c *Checkbox) Render(ctx Context) {
var style = ctx.Style()
var palette = style.Palette
fore := c.FontColor(ctx)
size := c.desiredSize(ctx)
bounds := c.bounds
deltaX, deltaY := bounds.Dx()-size.X, bounds.Dy()-size.Y
bounds.Min.X += .5 * deltaX
bounds.Min.Y += .5 * deltaY
var pad = style.Dimensions.TextPadding
bounds = bounds.Inset(pad)
pos := bounds.Min
icon, _ := ctx.Images().ScaledHeight(c.icon(ctx, c.Selected), bounds.Dy())
if icon != nil {
iconColor := fore
if c.Selected {
iconColor = palette.Primary
}
ctx.Renderer().DrawImageOptions(icon, geom.PtF32(pos.X, pos.Y+.5*(bounds.Dy()-icon.Height())), DrawOptions{Tint: iconColor})
pos.X += icon.Width() + pad
}
if len(c.Text) != 0 {
var fontName = c.FontName(ctx)
var font = ctx.Renderer().Font(fontName)
ctx.Renderer().Text(geom.PtF32(pos.X, pos.Y+.5*(bounds.Dy()-font.Height())), fontName, fore, c.Text)
}
}