Added support for tooltips.

This commit is contained in:
Sander Schobers 2020-05-15 16:39:53 +02:00
parent 6db13c8f46
commit 3a18d3adf9
6 changed files with 97 additions and 2 deletions

View File

@ -1,12 +1,18 @@
package ui package ui
import (
"opslag.de/schobers/geom"
)
type Context interface { type Context interface {
Animate() Animate()
Fonts() *Fonts Fonts() *Fonts
HasQuit() bool HasQuit() bool
MousePosition() geom.PointF32
Overlays() *Overlays Overlays() *Overlays
Quit() Quit()
Renderer() Renderer Renderer() Renderer
ShowTooltip(t string)
Style() *Style Style() *Style
Textures() *Textures Textures() *Textures
} }
@ -19,6 +25,8 @@ type context struct {
quit chan struct{} quit chan struct{}
renderer Renderer renderer Renderer
view Control view Control
mouse geom.PointF32
tooltip *Tooltip
overlays *Overlays overlays *Overlays
fonts *Fonts fonts *Fonts
textures *Textures textures *Textures
@ -26,14 +34,17 @@ type context struct {
} }
func newContext(r Renderer, s *Style, view Control) *context { func newContext(r Renderer, s *Style, view Control) *context {
return &context{ ctx := &context{
quit: make(chan struct{}), quit: make(chan struct{}),
renderer: r, renderer: r,
style: s, style: s,
view: view, view: view,
tooltip: &Tooltip{},
overlays: NewOverlays(view), overlays: NewOverlays(view),
fonts: NewFonts(r), fonts: NewFonts(r),
textures: NewTextures(r)} textures: NewTextures(r)}
ctx.overlays.AddOnTop(uiDefaultTooltipOverlay, ctx.tooltip, false)
return ctx
} }
func (c *context) Animate() { c.animate = true } func (c *context) Animate() { c.animate = true }
@ -54,10 +65,17 @@ func (c *context) HasQuit() bool {
} }
} }
func (c *context) MousePosition() geom.PointF32 { return c.mouse }
func (c *context) Overlays() *Overlays { return c.overlays } func (c *context) Overlays() *Overlays { return c.overlays }
func (c *context) Renderer() Renderer { return c.renderer } func (c *context) Renderer() Renderer { return c.renderer }
func (c *context) ShowTooltip(t string) {
c.overlays.Show(uiDefaultTooltipOverlay)
c.tooltip.Text = t
}
func (c *context) Style() *Style { return c.style } func (c *context) Style() *Style { return c.style }
func (c *context) Quit() { func (c *context) Quit() {
@ -71,10 +89,12 @@ func (c *context) Textures() *Textures { return c.textures }
// Handle implement EventTarget // Handle implement EventTarget
func (c *context) Handle(e Event) { func (c *context) Handle(e Event) {
switch e.(type) { switch e := e.(type) {
case *DisplayCloseEvent: case *DisplayCloseEvent:
c.Quit() c.Quit()
return return
case *MouseMoveEvent:
c.mouse = e.Pos()
} }
c.overlays.Handle(c, e) c.overlays.Handle(c, e)
} }

View File

@ -31,6 +31,8 @@ type ControlBase struct {
Background color.Color Background color.Color
Font FontStyle Font FontStyle
TextAlignment HorizontalAlignment TextAlignment HorizontalAlignment
Tooltip string
} }
func (c *ControlBase) Arrange(ctx Context, bounds geom.RectangleF32, offset geom.PointF32, parent Control) { func (c *ControlBase) Arrange(ctx Context, bounds geom.RectangleF32, offset geom.PointF32, parent Control) {
@ -100,6 +102,10 @@ func (c *ControlBase) Handle(ctx Context, e Event) {
c.pressed = false c.pressed = false
} }
} }
if c.Tooltip != "" && c.over {
ctx.ShowTooltip(c.Tooltip)
}
} }
func (c *ControlBase) FontColor(ctx Context) color.Color { func (c *ControlBase) FontColor(ctx Context) color.Color {

View File

@ -62,6 +62,7 @@ func (b *basic) Init(ctx ui.Context) error {
b.OnClick(func(geom.PointF32, ui.MouseButton) { b.OnClick(func(geom.PointF32, ui.MouseButton) {
ctx.Quit() ctx.Quit()
}) })
b.Tooltip = "Will quit the application"
}), 8), }), 8),
ui.BuildLabel("Status...", func(l *ui.Label) { ui.BuildLabel("Status...", func(l *ui.Label) {
l.Background = style.Palette.PrimaryDark l.Background = style.Palette.PrimaryDark

View File

@ -19,6 +19,7 @@ type Dimensions struct {
type FontNames struct { type FontNames struct {
Default string Default string
Tooltip string
} }
type Palette struct { type Palette struct {
@ -63,6 +64,7 @@ func DefaultDimensions() *Dimensions {
func DefaultFontNames() *FontNames { func DefaultFontNames() *FontNames {
return &FontNames{ return &FontNames{
Default: "default", Default: "default",
Tooltip: "default",
} }
} }

64
ui/tooltip.go Normal file
View File

@ -0,0 +1,64 @@
package ui
import (
"image/color"
"opslag.de/schobers/geom"
"opslag.de/schobers/zntg"
)
const tooltipBorderThickness = 1
const tooltipHorizontalPadding = 6
const tooltipVerticalPadding = 2
const tooltipMouseDistance = 12
const uiDefaultTooltipOverlay = "ui-default-tooltip"
type Tooltip struct {
ControlBase
Text string
}
func (t *Tooltip) FontName(ctx Context) string {
var name = t.Font.Name
if len(name) == 0 {
name = ctx.Style().Fonts.Tooltip
}
return name
}
func (t *Tooltip) Handle(Context, Event) {}
func (t *Tooltip) Render(ctx Context) {
if len(t.Text) == 0 {
return
}
fontName := t.FontName(ctx)
size := ctx.Fonts().Font(fontName).Measure(t.Text)
offset := t.Offset()
mouse := ctx.MousePosition().Sub(offset)
width := size.Dx() + 2*tooltipBorderThickness + 2*tooltipHorizontalPadding
height := size.Dy() + 2*tooltipBorderThickness + 2*tooltipVerticalPadding
left := mouse.X + tooltipMouseDistance
top := mouse.Y + tooltipMouseDistance
if left+width > t.bounds.Max.X {
left = mouse.X - tooltipMouseDistance - width
}
if top+height > t.bounds.Max.Y {
top = mouse.Y - tooltipMouseDistance - height
}
bounds := geom.RectRelF32(left, top, width, height)
almostBlack := zntg.MustHexColor("#000000bf")
almostWhite := zntg.MustHexColor("ffffffbf")
ctx.Renderer().FillRectangle(bounds, almostBlack)
ctx.Renderer().Rectangle(bounds, almostWhite, 1)
bottomLeft := bounds.Min.Add2D(tooltipBorderThickness+tooltipHorizontalPadding, tooltipBorderThickness+tooltipVerticalPadding)
ctx.Fonts().Text(fontName, bottomLeft, color.White, t.Text)
}

View File

@ -49,6 +49,8 @@ func RunWait(r Renderer, s *Style, view Control, wait bool) error {
if ctx.HasQuit() { if ctx.HasQuit() {
return nil return nil
} }
ctx.overlays.Hide("ui-default-tooltip")
r.PushEvents(ctx, wait) r.PushEvents(ctx, wait)
} }
return nil return nil