package ui import ( "image/color" "opslag.de/schobers/geom" ) type Button struct { ControlBase HoverColor color.Color Icon Texture Text string Type ButtonType } type ButtonType int const ( ButtonTypeContained ButtonType = iota ButtonTypeIcon ButtonTypeOutlined ButtonTypeText ) func BuildButton(text string, fn func(b *Button)) *Button { return BuildIconButton(nil, text, fn) } func BuildIconButton(icon Texture, text string, fn func(b *Button)) *Button { var b = &Button{Text: text, Icon: icon} if fn != nil { fn(b) } return b } func (b *Button) desiredSize(ctx Context) geom.PointF32 { var pad = ctx.Style().Dimensions.TextPadding var font = ctx.Renderer().Font(b.FontName(ctx)) var w, h float32 = 0, font.Height() if len(b.Text) != 0 { w += pad + font.WidthOf(b.Text) } if b.Icon != nil && b.Icon.Height() > 0 { iconW := b.Icon.Width() * h / b.Icon.Height() w += pad + iconW } if w == 0 { return geom.ZeroPtF32 } return geom.PtF32(w+pad, pad+h+pad) } func (b *Button) DesiredSize(ctx Context) geom.PointF32 { return b.desiredSize(ctx) } func (b *Button) Handle(ctx Context, e Event) { b.ControlBase.Handle(ctx, e) if b.over { ctx.Renderer().SetMouseCursor(MouseCursorPointer) } } func (b *Button) fillColor(p *Palette) color.Color { if b.Background != nil { if b.over && b.HoverColor != nil { return b.HoverColor } return b.Background } if b.over { if b.HoverColor != nil { return b.HoverColor } switch b.Type { case ButtonTypeContained: return p.PrimaryLight case ButtonTypeIcon: default: return p.PrimaryHighlight } } switch b.Type { case ButtonTypeContained: return p.Primary case ButtonTypeIcon: default: } return nil } func (b *Button) textColor(p *Palette) color.Color { if b.Font.Color != nil { return b.Font.Color } switch b.Type { case ButtonTypeContained: return p.TextOnPrimary case ButtonTypeIcon: if b.over { return p.Primary } return p.Text default: return p.Primary } } func (b *Button) Render(ctx Context) { var style = ctx.Style() var palette = style.Palette textColor := b.textColor(palette) fillColor := b.fillColor(palette) if fillColor != nil { ctx.Renderer().FillRectangle(b.bounds, fillColor) } size := b.desiredSize(ctx) bounds := b.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) boundsH := bounds.Dy() pos := bounds.Min if b.Icon != nil && b.Icon.Height() > 0 { icon, _ := ctx.Textures().ScaledHeight(b.Icon, boundsH) // try to pre-scale icon if icon == nil { // let the renderer scale icon = b.Icon } scale, iconWidth := ScaleToHeight(SizeOfTexture(icon), boundsH) ctx.Renderer().DrawTextureOptions(icon, geom.PtF32(pos.X, pos.Y), DrawOptions{Tint: textColor, Scale: scale}) pos.X += iconWidth + pad } if len(b.Text) != 0 { var fontName = b.FontName(ctx) var font = ctx.Renderer().Font(fontName) ctx.Renderer().Text(geom.PtF32(pos.X, pos.Y+.5*(boundsH-font.Height())), fontName, textColor, b.Text) } if b.Type == ButtonTypeOutlined { b.RenderOutline(ctx) } }