Added support for tooltips.
This commit is contained in:
parent
6db13c8f46
commit
3a18d3adf9
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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
64
ui/tooltip.go
Normal 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)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user