Added tooltips.
This commit is contained in:
parent
f57a9dd845
commit
013fe4bdb6
@ -21,7 +21,7 @@ type BuyFlowerButton struct {
|
||||
|
||||
func NewBuyFlowerButton(icon, iconDisabled, flowerID string, flower FlowerDescriptor, onClick EventContextFn) *BuyFlowerButton {
|
||||
return &BuyFlowerButton{
|
||||
IconButton: *NewIconButtonConfig(icon, onClick, func(b *IconButton) {
|
||||
IconButton: *NewIconButtonConfigure(icon, onClick, func(b *IconButton) {
|
||||
b.IconDisabled = iconDisabled
|
||||
b.IsDisabled = !flower.Unlocked
|
||||
}),
|
||||
|
@ -136,6 +136,8 @@ func run() error {
|
||||
app.Arrange(ctx, tins2020.RectAbs(0, 0, w, h))
|
||||
ctx.Settings.Window.Size = tins2020.PtPtr(w, h)
|
||||
}
|
||||
case *sdl.MouseMotionEvent:
|
||||
ctx.MousePosition = tins2020.Pt(e.X, e.Y)
|
||||
}
|
||||
app.Handle(ctx, event)
|
||||
}
|
||||
|
13
context.go
13
context.go
@ -6,12 +6,13 @@ import (
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
Renderer *sdl.Renderer
|
||||
Fonts Fonts
|
||||
Resources Resources
|
||||
Textures Textures
|
||||
Settings Settings
|
||||
ShouldQuit bool
|
||||
Renderer *sdl.Renderer
|
||||
Fonts Fonts
|
||||
Resources Resources
|
||||
Textures Textures
|
||||
Settings Settings
|
||||
MousePosition Point
|
||||
ShouldQuit bool
|
||||
}
|
||||
|
||||
func NewContext(res *rice.Box) (*Context, error) {
|
||||
|
23
control.go
23
control.go
@ -22,12 +22,35 @@ func EmptyEvent(fn EventFn) EventContextFn {
|
||||
type ControlBase struct {
|
||||
Bounds Rectangle
|
||||
|
||||
FontName string
|
||||
Foreground sdl.Color
|
||||
|
||||
IsDisabled bool
|
||||
IsMouseOver bool
|
||||
|
||||
OnLeftMouseButtonClick EventContextFn
|
||||
}
|
||||
|
||||
func (c *ControlBase) ActualForeground() sdl.Color {
|
||||
var none sdl.Color
|
||||
if c.Foreground == none {
|
||||
return MustHexColor("#ffffff")
|
||||
}
|
||||
return c.Foreground
|
||||
}
|
||||
|
||||
func (c *ControlBase) ActualFont(ctx *Context) *Font {
|
||||
name := c.ActualFontName()
|
||||
return ctx.Fonts.Font(name)
|
||||
}
|
||||
|
||||
func (c *ControlBase) ActualFontName() string {
|
||||
if len(c.FontName) == 0 {
|
||||
return "default"
|
||||
}
|
||||
return c.FontName
|
||||
}
|
||||
|
||||
func (b *ControlBase) Arrange(ctx *Context, bounds Rectangle) { b.Bounds = bounds }
|
||||
|
||||
func (b *ControlBase) Init(*Context) error { return nil }
|
||||
|
@ -100,44 +100,61 @@ func (c *GameControls) Init(ctx *Context) error {
|
||||
}
|
||||
|
||||
c.top.Orientation = OrientationHorizontal
|
||||
c.pause = NewIconButtonConfig("control-pause", EmptyEvent(func() {
|
||||
c.pause = NewIconButtonConfigure("control-pause", EmptyEvent(func() {
|
||||
c.game.Pause()
|
||||
}), func(b *IconButton) {
|
||||
b.IconDisabled = "control-pause-disabled"
|
||||
b.Tooltip.Text = "Pause game"
|
||||
})
|
||||
c.run = NewIconButtonConfig("control-run", EmptyEvent(func() {
|
||||
c.run = NewIconButtonConfigure("control-run", EmptyEvent(func() {
|
||||
c.game.Run()
|
||||
}), func(b *IconButton) {
|
||||
b.IconDisabled = "control-run-disabled"
|
||||
b.Tooltip.Text = "Run game at normal speed"
|
||||
})
|
||||
c.runFast = NewIconButtonConfig("control-run-fast", EmptyEvent(func() {
|
||||
c.runFast = NewIconButtonConfigure("control-run-fast", EmptyEvent(func() {
|
||||
c.game.RunFast()
|
||||
}), func(b *IconButton) {
|
||||
b.IconDisabled = "control-run-fast-disabled"
|
||||
b.Tooltip.Text = "Run game at fast speed"
|
||||
})
|
||||
c.speedChanged(c.game.Speed)
|
||||
c.top.Buttons = []Control{c.pause, c.run, c.runFast}
|
||||
|
||||
c.menu.Background = MustHexColor("#356dad")
|
||||
c.menu.Buttons = []Control{
|
||||
NewIconButtonConfig("control-settings", c.dialogs.ShowSettings, func(b *IconButton) {
|
||||
NewIconButtonConfigure("control-settings", c.dialogs.ShowSettings, func(b *IconButton) {
|
||||
b.IsDisabled = true
|
||||
b.IconDisabled = "#afafaf"
|
||||
}),
|
||||
NewIconButton("control-save", func(*Context) { c.game.Save() }),
|
||||
NewIconButton("control-load", func(ctx *Context) {
|
||||
NewIconButtonConfigure("control-save", func(*Context) { c.game.Save() }, func(b *IconButton) {
|
||||
b.Tooltip.Text = "Save game (overwrites previous save; no confirmation)"
|
||||
}),
|
||||
NewIconButtonConfigure("control-load", func(ctx *Context) {
|
||||
c.game.Load()
|
||||
c.updateFlowerControls(ctx)
|
||||
}, func(b *IconButton) {
|
||||
b.Tooltip.Text = "Load last saved game (no confirmation)"
|
||||
}),
|
||||
NewIconButton("control-new", func(ctx *Context) {
|
||||
NewIconButtonConfigure("control-new", func(ctx *Context) {
|
||||
c.game.New()
|
||||
c.updateFlowerControls(ctx)
|
||||
}, func(b *IconButton) {
|
||||
b.Tooltip.Text = "Start new game (no confirmation)"
|
||||
}),
|
||||
NewIconButtonConfigure("control-information", c.dialogs.ShowIntro, func(b *IconButton) {
|
||||
b.Tooltip.Text = "Show information/intro"
|
||||
}),
|
||||
NewIconButton("control-information", c.dialogs.ShowIntro),
|
||||
}
|
||||
|
||||
c.shovel = NewIconButtonConfig("control-shovel", func(*Context) { c.game.SelectShovel() }, func(b *IconButton) { b.IconHeight = 32 })
|
||||
c.research = NewIconButtonConfig("control-research", c.dialogs.ShowResearch, func(b *IconButton) { b.IconHeight = 32 })
|
||||
c.shovel = NewIconButtonConfigure("control-shovel", func(*Context) { c.game.SelectShovel() }, func(b *IconButton) {
|
||||
b.IconHeight = 32
|
||||
b.Tooltip.Text = "Select harvest tool (key: H)"
|
||||
})
|
||||
c.research = NewIconButtonConfigure("control-research", c.dialogs.ShowResearch, func(b *IconButton) {
|
||||
b.IconHeight = 32
|
||||
b.Tooltip.Text = "Conduct research (key: R)"
|
||||
})
|
||||
c.otherTools.Buttons = []Control{c.shovel, c.research}
|
||||
|
||||
c.Container.AddChild(&c.menu)
|
||||
|
@ -1,5 +1,9 @@
|
||||
package tins2020
|
||||
|
||||
import (
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
)
|
||||
|
||||
type HoverEffect int
|
||||
|
||||
const (
|
||||
@ -19,6 +23,7 @@ type IconButton struct {
|
||||
IconActive HoverEffect
|
||||
IconHover HoverEffect
|
||||
|
||||
Tooltip Tooltip
|
||||
IsActive bool
|
||||
}
|
||||
|
||||
@ -31,7 +36,7 @@ func NewIconButton(icon string, onClick EventContextFn) *IconButton {
|
||||
}
|
||||
}
|
||||
|
||||
func NewIconButtonConfig(icon string, onClick EventContextFn, configure func(*IconButton)) *IconButton {
|
||||
func NewIconButtonConfigure(icon string, onClick EventContextFn, configure func(*IconButton)) *IconButton {
|
||||
button := NewIconButton(icon, onClick)
|
||||
configure(button)
|
||||
return button
|
||||
@ -57,6 +62,31 @@ func (b *IconButton) activeTexture(ctx *Context) *Texture {
|
||||
return ctx.Textures.Texture(b.Icon)
|
||||
}
|
||||
|
||||
func (b *IconButton) Arrange(ctx *Context, bounds Rectangle) {
|
||||
b.ControlBase.Arrange(ctx, bounds)
|
||||
b.Tooltip.Arrange(ctx, bounds)
|
||||
}
|
||||
|
||||
func (b *IconButton) Handle(ctx *Context, event sdl.Event) bool {
|
||||
if b.ControlBase.Handle(ctx, event) {
|
||||
return true
|
||||
}
|
||||
if b.Tooltip.Handle(ctx, event) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (b *IconButton) Init(ctx *Context) error {
|
||||
if err := b.ControlBase.Init(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := b.Tooltip.Init(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *IconButton) Render(ctx *Context) {
|
||||
iconTexture := b.activeTexture(ctx)
|
||||
|
||||
@ -81,6 +111,10 @@ func (b *IconButton) Render(ctx *Context) {
|
||||
ctx.Renderer.FillRect(b.Bounds.SDLPtr())
|
||||
}
|
||||
iconTexture.SetColor(White)
|
||||
|
||||
if len(b.Tooltip.Text) > 0 && b.IsMouseOver {
|
||||
b.Tooltip.Render(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
type Scale int
|
||||
|
27
label.go
27
label.go
@ -2,37 +2,18 @@ package tins2020
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
)
|
||||
|
||||
type Label struct {
|
||||
ControlBase
|
||||
|
||||
FontColor sdl.Color
|
||||
FontName string
|
||||
Text string
|
||||
Alignment TextAlignment
|
||||
}
|
||||
|
||||
func (l *Label) fontColor() sdl.Color {
|
||||
var none sdl.Color
|
||||
if l.FontColor == none {
|
||||
return MustHexColor("#ffffff")
|
||||
}
|
||||
return l.FontColor
|
||||
}
|
||||
|
||||
func (l *Label) fontName() string {
|
||||
if len(l.FontName) == 0 {
|
||||
return "default"
|
||||
}
|
||||
return l.FontName
|
||||
}
|
||||
|
||||
func (l *Label) Render(ctx *Context) {
|
||||
font := ctx.Fonts.Font(l.fontName())
|
||||
color := l.fontColor()
|
||||
font := ctx.Fonts.Font(l.ActualFontName())
|
||||
color := l.ActualForeground()
|
||||
bottom := l.Bounds.Y + l.Bounds.H
|
||||
switch l.Alignment {
|
||||
case TextAlignmentCenter:
|
||||
@ -49,8 +30,8 @@ type Paragraph struct {
|
||||
}
|
||||
|
||||
func (p *Paragraph) Render(ctx *Context) {
|
||||
font := ctx.Fonts.Font(p.fontName())
|
||||
color := p.fontColor()
|
||||
font := ctx.Fonts.Font(p.ActualFontName())
|
||||
color := p.ActualForeground()
|
||||
fontHeight := int32(font.Height())
|
||||
lines := strings.Split(p.Text, "\n")
|
||||
|
||||
|
@ -62,11 +62,10 @@ func (d *LargeDialog) Arrange(ctx *Context, bounds Rectangle) {
|
||||
}
|
||||
|
||||
func (d *LargeDialog) Init(ctx *Context) error {
|
||||
d.title = Label{
|
||||
Text: "Botanim",
|
||||
FontName: "title",
|
||||
Alignment: TextAlignmentCenter,
|
||||
}
|
||||
d.title.Text = "Botanim"
|
||||
d.title.FontName = "title"
|
||||
d.title.Alignment = TextAlignmentCenter
|
||||
|
||||
d.close = IconButton{
|
||||
Icon: "control-cancel",
|
||||
IconHover: HoverEffectColor,
|
||||
|
59
tooltip.go
Normal file
59
tooltip.go
Normal file
@ -0,0 +1,59 @@
|
||||
package tins2020
|
||||
|
||||
import "github.com/veandco/go-sdl2/sdl"
|
||||
|
||||
type Tooltip struct {
|
||||
ControlBase
|
||||
|
||||
Text string
|
||||
}
|
||||
|
||||
const tooltipBorderThickness = 1
|
||||
const tooltipHorizontalPadding = 4
|
||||
const tooltipMouseDistance = 12
|
||||
|
||||
func (t *Tooltip) Handle(ctx *Context, event sdl.Event) bool {
|
||||
if len(t.Text) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
font := ctx.Fonts.Font(t.ActualFontName())
|
||||
windowW, windowH, err := ctx.Renderer.GetOutputSize()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
labelW, labelH, err := font.SizeUTF8(t.Text)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
mouse := ctx.MousePosition
|
||||
width := int32(labelW) + 2*tooltipBorderThickness + 2*tooltipHorizontalPadding
|
||||
height := int32(labelH) + 2*tooltipBorderThickness
|
||||
|
||||
left := mouse.X + tooltipMouseDistance
|
||||
top := mouse.Y + tooltipMouseDistance
|
||||
if left+width > windowW {
|
||||
left = mouse.X - tooltipMouseDistance - width
|
||||
}
|
||||
if top+height > windowH {
|
||||
top = mouse.Y - tooltipMouseDistance - height
|
||||
}
|
||||
|
||||
t.Bounds = Rect(left, top, width, height)
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *Tooltip) Render(ctx *Context) {
|
||||
SetDrawColor(ctx.Renderer, Black)
|
||||
ctx.Renderer.FillRect(t.Bounds.SDLPtr())
|
||||
|
||||
SetDrawColor(ctx.Renderer, White)
|
||||
ctx.Renderer.DrawRect(t.Bounds.SDLPtr())
|
||||
|
||||
font := t.ActualFont(ctx)
|
||||
|
||||
bottomLeft := Pt(t.Bounds.X+tooltipBorderThickness+tooltipHorizontalPadding, t.Bounds.Y+t.Bounds.H-tooltipBorderThickness)
|
||||
font.RenderCopy(ctx.Renderer, t.Text, bottomLeft, White)
|
||||
}
|
Loading…
Reference in New Issue
Block a user