2019-04-11 19:23:51 +00:00
|
|
|
package ui
|
|
|
|
|
|
|
|
import (
|
|
|
|
"opslag.de/schobers/geom"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Checkbox struct {
|
|
|
|
ControlBase
|
|
|
|
|
2020-05-15 17:00:43 +00:00
|
|
|
selectedChanged Events
|
2019-04-11 21:30:26 +00:00
|
|
|
|
2019-04-11 19:23:51 +00:00
|
|
|
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
|
2020-05-15 13:42:24 +00:00
|
|
|
var font = ctx.Fonts().Font(c.FontName(ctx))
|
2019-04-11 19:23:51 +00:00
|
|
|
var w, h float32 = 0, font.Height()
|
|
|
|
if len(c.Text) != 0 {
|
|
|
|
w += pad + font.WidthOf(c.Text)
|
|
|
|
}
|
2020-05-15 07:20:44 +00:00
|
|
|
icon := c.getOrCreateNormalIcon(ctx)
|
|
|
|
_, iconWidth := ScaleToHeight(SizeOfTexture(icon), h)
|
|
|
|
w += pad + iconWidth
|
2019-04-11 19:23:51 +00:00
|
|
|
return geom.PtF32(w+pad, pad+h+pad)
|
|
|
|
}
|
|
|
|
|
2020-05-12 21:03:43 +00:00
|
|
|
func (c *Checkbox) icon(ctx Context) Texture {
|
2019-04-11 21:30:26 +00:00
|
|
|
if c.Selected {
|
2019-04-11 19:23:51 +00:00
|
|
|
return GetOrCreateIcon(ctx, "ui-default-checkbox-selected", c.selectedIcon)
|
2020-05-16 11:46:07 +00:00
|
|
|
} else if c.over && !c.Disabled {
|
2019-04-11 21:30:26 +00:00
|
|
|
return GetOrCreateIcon(ctx, "ui-default-checkbox-hover", c.hoverIcon)
|
2019-04-11 19:23:51 +00:00
|
|
|
}
|
2019-04-11 21:30:26 +00:00
|
|
|
return c.getOrCreateNormalIcon(ctx)
|
|
|
|
}
|
|
|
|
|
2020-05-12 21:03:43 +00:00
|
|
|
func (c *Checkbox) getOrCreateNormalIcon(ctx Context) Texture {
|
2019-04-11 19:23:51 +00:00
|
|
|
return GetOrCreateIcon(ctx, "ui-default-checkbox", c.normalIcon)
|
|
|
|
}
|
|
|
|
|
2020-05-15 07:20:44 +00:00
|
|
|
var checkBoxIconBorder = geom.PolF32(
|
|
|
|
geom.PtF32(48, 80),
|
|
|
|
geom.PtF32(400, 80),
|
|
|
|
geom.PtF32(400, 432),
|
|
|
|
geom.PtF32(48, 432),
|
|
|
|
)
|
2019-04-11 19:23:51 +00:00
|
|
|
|
2020-05-15 07:20:44 +00:00
|
|
|
var checkBoxCheckMark = geom.PointsF32{
|
|
|
|
geom.PtF32(96, 256),
|
|
|
|
geom.PtF32(180, 340),
|
|
|
|
geom.PtF32(340, 150),
|
2019-04-11 21:30:26 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 07:20:44 +00:00
|
|
|
func (c *Checkbox) hoverIcon(pt geom.PointF32) bool {
|
|
|
|
return (pt.DistanceToPolygon(checkBoxIconBorder) < 48 && !pt.InPolygon(checkBoxIconBorder)) || pt.DistanceToLines(checkBoxCheckMark) < 24
|
2019-04-11 21:30:26 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 07:20:44 +00:00
|
|
|
func (c *Checkbox) normalIcon(pt geom.PointF32) bool {
|
|
|
|
return pt.DistanceToPolygon(checkBoxIconBorder) < 48 && !pt.InPolygon(checkBoxIconBorder)
|
2019-04-11 19:23:51 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 07:20:44 +00:00
|
|
|
func (c *Checkbox) selectedIcon(pt geom.PointF32) bool {
|
|
|
|
if pt.DistanceToPolygon(checkBoxIconBorder) < 48 || pt.InPolygon(checkBoxIconBorder) {
|
|
|
|
return pt.DistanceToLines(checkBoxCheckMark) > 24
|
2019-04-11 19:23:51 +00:00
|
|
|
}
|
2020-05-15 07:20:44 +00:00
|
|
|
return false
|
2019-04-11 19:23:51 +00:00
|
|
|
}
|
|
|
|
|
2020-05-16 13:37:53 +00:00
|
|
|
func (c *Checkbox) DesiredSize(ctx Context, _ geom.PointF32) geom.PointF32 { return c.desiredSize(ctx) }
|
2019-04-11 19:23:51 +00:00
|
|
|
|
2020-05-15 17:00:43 +00:00
|
|
|
func (c *Checkbox) Handle(ctx Context, e Event) bool {
|
|
|
|
result := c.ControlBase.Handle(ctx, e)
|
|
|
|
if c.over {
|
2020-05-16 11:46:07 +00:00
|
|
|
if c.Disabled {
|
|
|
|
ctx.Renderer().SetMouseCursor(MouseCursorNotAllowed)
|
|
|
|
return true
|
|
|
|
}
|
2020-05-15 17:00:43 +00:00
|
|
|
ctx.Renderer().SetMouseCursor(MouseCursorPointer)
|
|
|
|
}
|
|
|
|
if result {
|
|
|
|
return true
|
|
|
|
}
|
2019-04-11 19:23:51 +00:00
|
|
|
switch e := e.(type) {
|
|
|
|
case *MouseButtonDownEvent:
|
|
|
|
if e.Button == MouseButtonLeft && c.over {
|
|
|
|
c.Selected = !c.Selected
|
2020-05-15 17:00:43 +00:00
|
|
|
return c.selectedChanged.Notify(ctx, c.Selected)
|
2019-04-11 19:23:51 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-15 17:00:43 +00:00
|
|
|
return false
|
2019-04-11 19:23:51 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 17:00:43 +00:00
|
|
|
func (c *Checkbox) SelectedChanged() EventHandler { return &c.selectedChanged }
|
2019-04-11 21:30:26 +00:00
|
|
|
|
2019-04-11 19:23:51 +00:00
|
|
|
func (c *Checkbox) Render(ctx Context) {
|
2019-04-11 21:30:26 +00:00
|
|
|
c.RenderBackground(ctx)
|
|
|
|
|
2019-04-11 19:23:51 +00:00
|
|
|
var style = ctx.Style()
|
|
|
|
var palette = style.Palette
|
2020-05-16 11:46:07 +00:00
|
|
|
fore := c.TextColor(ctx)
|
2019-04-11 19:23:51 +00:00
|
|
|
bounds := c.bounds
|
|
|
|
|
|
|
|
var pad = style.Dimensions.TextPadding
|
|
|
|
bounds = bounds.Inset(pad)
|
2020-05-15 07:20:44 +00:00
|
|
|
boundsH := bounds.Dy()
|
2019-04-11 19:23:51 +00:00
|
|
|
pos := bounds.Min
|
2020-05-15 07:20:44 +00:00
|
|
|
icon := c.icon(ctx)
|
2019-04-11 19:23:51 +00:00
|
|
|
if icon != nil {
|
|
|
|
iconColor := fore
|
2020-05-16 11:46:07 +00:00
|
|
|
if c.Selected {
|
|
|
|
iconColor = c.FontColor(ctx, palette.Primary)
|
2019-04-11 19:23:51 +00:00
|
|
|
}
|
2020-05-15 07:20:44 +00:00
|
|
|
scaledIcon, _ := ctx.Textures().ScaledHeight(icon, boundsH) // try to pre-scale icon
|
|
|
|
if scaledIcon == nil { // let the renderer scale
|
|
|
|
scaledIcon = icon
|
|
|
|
}
|
2020-05-17 09:12:45 +00:00
|
|
|
_, iconWidth := ScaleToHeight(SizeOfTexture(scaledIcon), boundsH)
|
|
|
|
rect := geom.RectRelF32(pos.X, pos.Y, iconWidth, boundsH)
|
|
|
|
ctx.Renderer().DrawTextureOptions(scaledIcon, rect, DrawOptions{Tint: iconColor})
|
2020-05-15 07:20:44 +00:00
|
|
|
pos.X += iconWidth + pad
|
2019-04-11 19:23:51 +00:00
|
|
|
}
|
|
|
|
if len(c.Text) != 0 {
|
|
|
|
var fontName = c.FontName(ctx)
|
2020-05-15 13:42:24 +00:00
|
|
|
var font = ctx.Fonts().Font(fontName)
|
|
|
|
ctx.Renderer().Text(font, geom.PtF32(pos.X, pos.Y+.5*(boundsH-font.Height())), fore, c.Text)
|
2019-04-11 19:23:51 +00:00
|
|
|
}
|
|
|
|
}
|