zntg/ui/button.go
Sander Schobers cdfb863ab0 Added SDL backend.
Added Action{,s}. List of actions that can be used to defer cleanup code (see NewRenderer implementations).
Added TextInputEvent (replaces the old KeyPressEvent) and added to new events KeyDown & KeyUp.
Added VSync to NewRendererOptions.
Removed IconScale from button.
Added ImageSource interface that replaces the Image/Texture method on the Texture interface. This makes converting back a texture to an image optional (since this is atypical for a hardware texture for instance).
Added new KeyModifier: OSCommand (Windows/Command key).
Added KeyState that can keep the state of keys (pressed or not).
Added KeyEnter, representing the Enter key.
Changed signatures of CreateTexture methods in Renderer.
Changed signatures of icon related method (removed factories).
Basic example now depends on sdlgui.
2020-05-15 09:20:44 +02:00

147 lines
3.2 KiB
Go

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