diff --git a/ui/button.go b/ui/button.go index 9e638ab..caf6426 100644 --- a/ui/button.go +++ b/ui/button.go @@ -10,7 +10,8 @@ type Button struct { ControlBase HoverColor color.Color - Icon string + Icon string // optional: icon to display in front of the text. + IconHeight float32 // overrides the height of the icon (overrides auto-scaling when text is provided). Text string Type ButtonType @@ -40,25 +41,40 @@ 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 + + icon, iconW, iconH := b.icon(ctx) + if len(b.Text) == 0 { + if icon != nil && iconH > 0 { + w = pad + iconW + pad + h = iconH + } + } else { + w += pad + font.WidthOf(b.Text) + pad + if icon != nil && iconH > 0 { + if b.IconHeight == 0 { + iconW = iconW * h / iconH + // iconH = h + } + w += iconW + pad + } } if w == 0 { return geom.ZeroPtF32 } - return geom.PtF32(w+pad, pad+h+pad) + return geom.PtF32(w, pad+h+pad) } -func (b *Button) icon(ctx Context) Texture { +func (b *Button) icon(ctx Context) (Texture, float32, float32) { if b.Icon == "" { - return nil + return nil, 0, 0 } - return ctx.Textures().Texture(b.Icon) + icon := ctx.Textures().Texture(b.Icon) + iconW, iconH := icon.Width(), icon.Height() + if b.IconHeight != 0 { + iconW = b.IconHeight * iconW / iconH + iconH = b.IconHeight + } + return icon, iconW, iconH } func (b *Button) ButtonClicked() ControlClickedEventHandler { return &b.clicked } @@ -92,6 +108,10 @@ func (b *Button) Notify(ctx Context, state interface{}) bool { } func (b *Button) fillColor(p *Palette) color.Color { + if b.Type == ButtonTypeIcon { + return nil + } + if b.Disabled { if b.Background != nil { return p.Disabled @@ -116,7 +136,6 @@ func (b *Button) fillColor(p *Palette) color.Color { switch b.Type { case ButtonTypeContained: return p.PrimaryLight - case ButtonTypeIcon: default: return p.PrimaryHighlight } @@ -124,8 +143,6 @@ func (b *Button) fillColor(p *Palette) color.Color { switch b.Type { case ButtonTypeContained: return p.Primary - case ButtonTypeIcon: - default: } return nil } @@ -149,6 +166,9 @@ func (b *Button) textColor(p *Palette) color.Color { return p.TextOnPrimary case ButtonTypeIcon: if b.over { + if b.HoverColor != nil { + return b.HoverColor + } return p.Primary } return p.Text @@ -175,15 +195,22 @@ func (b *Button) Render(ctx Context) { 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 + icon, iconW, iconH := b.icon(ctx) + var iconOffsetY float32 + if icon != nil && iconH > 0 { + if b.Text != "" { + if b.IconHeight == 0 { + iconH = boundsH + scaled, _ := ctx.Textures().ScaledHeight(icon, iconH) // try to pre-scale scaled + if scaled != nil { // let the renderer scale + icon = scaled + } + _, iconW = ScaleToHeight(SizeOfTexture(icon), iconH) + } + iconOffsetY = .5 * (boundsH - iconH) } - _, iconWidth := ScaleToHeight(SizeOfTexture(scaled), boundsH) - ctx.Renderer().DrawTextureOptions(scaled, geom.RectRelF32(pos.X, pos.Y, iconWidth, boundsH), DrawOptions{Tint: textColor}) - pos.X += iconWidth + pad + ctx.Renderer().DrawTextureOptions(icon, geom.RectRelF32(pos.X, pos.Y+iconOffsetY, iconW, iconH), DrawOptions{Tint: textColor}) + pos.X += iconW + pad } if len(b.Text) != 0 { fontName := b.FontName(ctx)