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) } }