aboutsummaryrefslogtreecommitdiff
path: root/go/ui/button.go
blob: 42cbe3046ba7e4c2f65eb5928e71c100da5fb5d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package ui

import (
	"image/color"

	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/text/v2"
	"github.com/hajimehoshi/ebiten/v2/vector"

	"muhq.space/muhqs-game/go/font"
)

type Button interface {
	Widget
}

type SimpleButton struct {
	WidgetBase
	label       string
	Bg          color.Color
	Fg          color.Color
	font        *text.GoTextFace
	lineSpacing float64
}

func NewSimpleButton(x, y, w, h int, label string, onClick func(b *SimpleButton)) *SimpleButton {
	sb := &SimpleButton{NewWidgetBase(x, y, w, h), label, Gray, color.White, font.Font24, 1.5}
	sb.EventHandlersMap["click"] = func(int, int) { onClick(sb) }
	sb.renderImpl = func() *ebiten.Image {
		if sb.img == nil {
			sb.img = sb.renderRect()
		}
		return sb.img
	}
	return sb
}

// NewRoundSimpleButton creates a circular SimpleButton.
// The shape used for click detection is still a square.
// x and y define the left upper corner of the square (x, y) rect (x+r, y+r).
func NewRoundSimpleButton(x, y, r int, label string, onClick func(b *SimpleButton)) *SimpleButton {
	sb := &SimpleButton{NewWidgetBase(x, y, r, r), label, Gray, color.White, font.Font24, 1.5}
	sb.EventHandlersMap["click"] = func(int, int) { onClick(sb) }
	sb.renderImpl = func() *ebiten.Image {
		if sb.img == nil {
			sb.img = sb.renderCircle()
		}
		return sb.img
	}
	return sb
}

func (b *SimpleButton) drawLabel(img *ebiten.Image) {
	w, h := text.Measure(b.label, b.font, b.font.Size*b.lineSpacing)
	x := float64(b.Width)/2 - w/2
	y := float64(b.Height)/2 - h/2
	op := &text.DrawOptions{}
	op.GeoM.Translate(x, y)
	op.ColorScale.ScaleWithColor(b.Fg)
	text.Draw(img, b.label, font.Font24, op)
}

func (b *SimpleButton) renderRect() *ebiten.Image {
	img := ebiten.NewImage(b.Width, b.Height)

	vector.FillRect(img, float32(0), float32(0), float32(b.Width), float32(b.Height), b.Bg, false)
	b.drawLabel(img)
	return img
}

func (b *SimpleButton) renderCircle() *ebiten.Image {
	img := ebiten.NewImage(b.Width, b.Height)

	vector.FillCircle(img, float32(b.Width)/2, float32(b.Height)/2, float32(b.Width/2), b.Bg, false)
	b.drawLabel(img)
	return img
}

func (b *SimpleButton) UpdateLabel(label string) {
	if b.label != label {
		b.label = label
		b.ForceRedraw()
	}
}

type ImageButton struct {
	WidgetBase
	img *ebiten.Image
}

func NewImageButton(x, y int, img *ebiten.Image, onClick func(b *ImageButton)) *ImageButton {
	bounds := img.Bounds()
	sb := &ImageButton{NewWidgetBase(x, y, bounds.Dx(), bounds.Dy()), img}
	sb.EventHandlersMap["click"] = func(int, int) { onClick(sb) }
	sb.renderImpl = func() *ebiten.Image {
		return sb.img
	}
	return sb
}