package ui import ( "image/color" "opslag.de/schobers/geom" ) type Button struct { ControlBase HoverColor color.Color Icon string 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("", text, fn) } func BuildIconButton(icon, 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.Fonts().Font(b.FontName(ctx)) var w, h float32 = 0, font.Height() if len(b.Text) != 0 { w += pad + font.WidthOf(b.Text) } icon := b.icon(ctx) if icon != nil && icon.Height() > 0 { iconW := icon.Width() * h / icon.Height() w += pad + iconW } if w == 0 { return geom.ZeroPtF32 } return geom.PtF32(w+pad, pad+h+pad) } func (b *Button) icon(ctx Context) Texture { if b.Icon == "" { return nil } return ctx.Textures().Texture(b.Icon) } func (b *Button) DesiredSize(ctx Context) geom.PointF32 { return b.desiredSize(ctx) } func (b *Button) Handle(ctx Context, e Event) bool { result := b.ControlBase.Handle(ctx, e) if b.over { ctx.Renderer().SetMouseCursor(MouseCursorPointer) } return result } 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 icon := b.icon(ctx) if icon != nil && icon.Height() > 0 { scaled, _ := ctx.Textures().ScaledHeight(icon, boundsH) // try to pre-scale scaled if scaled == nil { // let the renderer scale scaled = icon } scale, iconWidth := ScaleToHeight(SizeOfTexture(scaled), boundsH) ctx.Renderer().DrawTextureOptions(scaled, geom.PtF32(pos.X, pos.Y), DrawOptions{Tint: textColor, Scale: scale}) pos.X += iconWidth + pad } if len(b.Text) != 0 { fontName := b.FontName(ctx) font := ctx.Fonts().Font(fontName) ctx.Renderer().Text(font, geom.PtF32(pos.X, pos.Y+.5*(boundsH-font.Height())), textColor, b.Text) } if b.Type == ButtonTypeOutlined { b.RenderOutline(ctx) } }