package ui import ( "image/color" "opslag.de/schobers/geom" ) type Button struct { ControlBase Type ButtonType Text string Icon Image IconScale float32 } 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(i Image, text string, fn func(b *Button)) *Button { var b = &Button{Text: text, Icon: i} 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.scale(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 { return b.Background } if b.over { 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) scale(f float32) float32 { if b.IconScale == 0 { return f } return b.IconScale * f } 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) pos := bounds.Min if b.Icon != nil && b.Icon.Height() > 0 { icon, _ := ctx.Images().ScaledHeight(b.Icon, b.scale(bounds.Dy())) if icon != nil { ctx.Renderer().DrawImageOptions(icon, geom.PtF32(pos.X, pos.Y+.5*(bounds.Dy()-icon.Height())), DrawOptions{Tint: textColor}) pos.X += icon.Width() + 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*(bounds.Dy()-font.Height())), fontName, textColor, b.Text) } if b.Type == ButtonTypeOutlined { ctx.Renderer().Rectangle(b.bounds, palette.TextDisabled, 1) } }