Added Events and changed event handlers of controls.

Removed EventHandlers from Control interface.
This commit is contained in:
Sander Schobers 2020-05-15 19:00:43 +02:00
parent 4e37f4b23e
commit d742fba7e9
14 changed files with 220 additions and 115 deletions

View File

@ -63,11 +63,12 @@ func (b *Button) DesiredSize(ctx Context) geom.PointF32 {
return b.desiredSize(ctx) return b.desiredSize(ctx)
} }
func (b *Button) Handle(ctx Context, e Event) { func (b *Button) Handle(ctx Context, e Event) bool {
b.ControlBase.Handle(ctx, e) result := b.ControlBase.Handle(ctx, e)
if b.over { if b.over {
ctx.Renderer().SetMouseCursor(MouseCursorPointer) ctx.Renderer().SetMouseCursor(MouseCursorPointer)
} }
return result
} }
func (b *Button) fillColor(p *Palette) color.Color { func (b *Button) fillColor(p *Palette) color.Color {

View File

@ -4,12 +4,10 @@ import (
"opslag.de/schobers/geom" "opslag.de/schobers/geom"
) )
type SelectedChangedFn func(selected bool)
type Checkbox struct { type Checkbox struct {
ControlBase ControlBase
onSelectedChanged SelectedChangedFn selectedChanged Events
Selected bool Selected bool
Text string Text string
@ -79,26 +77,25 @@ func (c *Checkbox) selectedIcon(pt geom.PointF32) bool {
func (c *Checkbox) DesiredSize(ctx Context) geom.PointF32 { return c.desiredSize(ctx) } func (c *Checkbox) DesiredSize(ctx Context) geom.PointF32 { return c.desiredSize(ctx) }
func (c *Checkbox) Handle(ctx Context, e Event) { func (c *Checkbox) Handle(ctx Context, e Event) bool {
result := c.ControlBase.Handle(ctx, e)
if c.over {
ctx.Renderer().SetMouseCursor(MouseCursorPointer)
}
if result {
return true
}
switch e := e.(type) { switch e := e.(type) {
case *MouseButtonDownEvent: case *MouseButtonDownEvent:
if e.Button == MouseButtonLeft && c.over { if e.Button == MouseButtonLeft && c.over {
c.Selected = !c.Selected c.Selected = !c.Selected
onSelectedChanged := c.onSelectedChanged return c.selectedChanged.Notify(ctx, c.Selected)
if onSelectedChanged != nil {
onSelectedChanged(c.Selected)
}
} }
} }
c.ControlBase.Handle(ctx, e) return false
if c.over {
ctx.Renderer().SetMouseCursor(MouseCursorPointer)
}
} }
func (c *Checkbox) OnSelectedChanged(fn SelectedChangedFn) { func (c *Checkbox) SelectedChanged() EventHandler { return &c.selectedChanged }
c.onSelectedChanged = fn
}
func (c *Checkbox) Render(ctx Context) { func (c *Checkbox) Render(ctx Context) {
c.RenderBackground(ctx) c.RenderBackground(ctx)

View File

@ -26,11 +26,16 @@ func (c *ContainerBase) Arrange(ctx Context, bounds geom.RectangleF32, offset ge
c.ControlBase.Arrange(ctx, bounds, offset, parent) c.ControlBase.Arrange(ctx, bounds, offset, parent)
} }
func (c *ContainerBase) Handle(ctx Context, e Event) { func (c *ContainerBase) Handle(ctx Context, e Event) bool {
c.ControlBase.Handle(ctx, e) if c.ControlBase.Handle(ctx, e) {
for _, child := range c.Children { return true
child.Handle(ctx, e)
} }
for _, child := range c.Children {
if child.Handle(ctx, e) {
return true
}
}
return false
} }
func (c *ContainerBase) Render(ctx Context) { func (c *ContainerBase) Render(ctx Context) {

View File

@ -7,17 +7,14 @@ import (
type Control interface { type Control interface {
Arrange(Context, geom.RectangleF32, geom.PointF32, Control) Arrange(Context, geom.RectangleF32, geom.PointF32, Control)
DesiredSize(Context) geom.PointF32 DesiredSize(Context) geom.PointF32
Handle(Context, Event) Handle(Context, Event) bool
Render(Context) Render(Context)
Bounds() geom.RectangleF32 Bounds() geom.RectangleF32
IsInBounds(p geom.PointF32) bool IsInBounds(p geom.PointF32) bool
IsOver() bool IsOver() bool
Offset() geom.PointF32 Offset() geom.PointF32
OnClick(ClickFn)
OnDragStart(DragStartFn)
OnDragMove(DragMoveFn)
OnDragEnd(DragEndFn)
Parent() Control Parent() Control
} }

View File

@ -6,12 +6,84 @@ import (
"opslag.de/schobers/geom" "opslag.de/schobers/geom"
) )
type ClickFn func(pos geom.PointF32, btn MouseButton) type ControlClickedArgs struct {
type DragEndFn func(start, end geom.PointF32) Position geom.PointF32
type DragMoveFn func(start, move geom.PointF32) Button MouseButton
type DragStartFn func(start geom.PointF32) }
type MouseEnterFn func()
type MouseLeaveFn func() type ControlClickedEventHandler interface {
AddHandler(func(Context, ControlClickedArgs)) uint
}
type ControlClickedEvents struct {
Events
}
func (e *ControlClickedEvents) AddHandler(handler func(Context, ControlClickedArgs)) uint {
return e.Events.AddHandlerState(func(ctx Context, state interface{}) {
args := state.(ControlClickedArgs)
handler(ctx, args)
})
}
type DragEndedArgs struct {
Start geom.PointF32
End geom.PointF32
}
type DragEndedEventHandler interface {
AddHandler(func(Context, DragEndedArgs)) uint
}
type DragEndedEvents struct {
Events
}
func (e *DragEndedEvents) AddHandler(handler func(Context, DragEndedArgs)) uint {
return e.Events.AddHandlerState(func(ctx Context, state interface{}) {
args := state.(DragEndedArgs)
handler(ctx, args)
})
}
type DragMovedArgs struct {
Start geom.PointF32
Current geom.PointF32
}
type DragMovedEventHandler interface {
AddHandler(func(Context, DragMovedArgs)) uint
}
type DragMovedEvents struct {
Events
}
func (e *DragMovedEvents) AddHandler(handler func(Context, DragMovedArgs)) uint {
return e.Events.AddHandlerState(func(ctx Context, state interface{}) {
args := state.(DragMovedArgs)
handler(ctx, args)
})
}
type DragStartedArgs struct {
Start geom.PointF32
}
type DragStartedEventHandler interface {
AddHandler(func(Context, DragStartedArgs)) uint
}
type DragStartedEvents struct {
Events
}
func (e *DragStartedEvents) AddHandler(handler func(Context, DragStartedArgs)) uint {
return e.Events.AddHandlerState(func(ctx Context, state interface{}) {
args := state.(DragStartedArgs)
handler(ctx, args)
})
}
var _ Control = &ControlBase{} var _ Control = &ControlBase{}
@ -23,10 +95,10 @@ type ControlBase struct {
over bool over bool
pressed bool pressed bool
onClick ClickFn clicked ControlClickedEvents
onDragEnd DragEndFn dragEnded DragEndedEvents
onDragMove DragMoveFn dragMoved DragMovedEvents
onDragStart DragStartFn dragStarted DragStartedEvents
Background color.Color Background color.Color
Font FontStyle Font FontStyle
@ -45,7 +117,13 @@ func (c *ControlBase) Bounds() geom.RectangleF32 { return c.bounds }
func (c *ControlBase) DesiredSize(Context) geom.PointF32 { return geom.ZeroPtF32 } func (c *ControlBase) DesiredSize(Context) geom.PointF32 { return geom.ZeroPtF32 }
func (c *ControlBase) Handle(ctx Context, e Event) { func (c *ControlBase) Handle(ctx Context, e Event) bool {
defer func() {
if c.Tooltip != "" && c.over {
ctx.ShowTooltip(c.Tooltip)
}
}()
var over = func(e MouseEvent) bool { var over = func(e MouseEvent) bool {
pos := e.Pos() pos := e.Pos()
if !c.IsInBounds(pos) { if !c.IsInBounds(pos) {
@ -67,16 +145,11 @@ func (c *ControlBase) Handle(ctx Context, e Event) {
if start, ok := c.drag.IsDragging(); ok { if start, ok := c.drag.IsDragging(); ok {
var move = c.ToControlPosition(e.Pos()) var move = c.ToControlPosition(e.Pos())
c.drag.Move(move) c.drag.Move(move)
if c.onDragMove != nil { return c.dragMoved.Notify(ctx, DragMovedArgs{Start: start, Current: move})
c.onDragMove(start, move)
}
} else {
var start = c.ToControlPosition(e.Pos())
c.drag.Start(start)
if c.onDragStart != nil {
c.onDragStart(start)
}
} }
var start = c.ToControlPosition(e.Pos())
c.drag.Start(start)
return c.dragStarted.Notify(ctx, DragStartedArgs{Start: start})
} }
case *MouseLeaveEvent: case *MouseLeaveEvent:
c.over = false c.over = false
@ -84,28 +157,19 @@ func (c *ControlBase) Handle(ctx Context, e Event) {
c.over = over(e.MouseEvent) c.over = over(e.MouseEvent)
if c.over && e.Button == MouseButtonLeft { if c.over && e.Button == MouseButtonLeft {
c.pressed = true c.pressed = true
return c.clicked.Notify(ctx, ControlClickedArgs{Position: e.Pos(), Button: e.Button})
} }
case *MouseButtonUpEvent: case *MouseButtonUpEvent:
if e.Button == MouseButtonLeft { if e.Button == MouseButtonLeft {
c.pressed = false
if start, ok := c.drag.IsDragging(); ok { if start, ok := c.drag.IsDragging(); ok {
var end = c.ToControlPosition(e.Pos()) var end = c.ToControlPosition(e.Pos())
c.drag.Cancel() c.drag.Cancel()
if c.onDragEnd != nil { return c.dragEnded.Notify(ctx, DragEndedArgs{Start: start, End: end})
c.onDragEnd(start, end)
}
} }
if c.pressed {
if c.onClick != nil {
c.onClick(c.ToControlPosition(e.Pos()), e.Button)
}
}
c.pressed = false
} }
} }
return 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 {
@ -143,17 +207,13 @@ func (c *ControlBase) IsPressed() bool { return c.pressed }
func (c *ControlBase) Offset() geom.PointF32 { return c.offset } func (c *ControlBase) Offset() geom.PointF32 { return c.offset }
func (c *ControlBase) OnClick(fn ClickFn) { c.onClick = fn } func (c *ControlBase) ControlClicked() ControlClickedEventHandler { return &c.clicked }
func (c *ControlBase) OnDragStart(fn DragStartFn) { func (c *ControlBase) DragEnded() DragEndedEventHandler { return &c.dragEnded }
c.onDragStart = fn
}
func (c *ControlBase) OnDragMove(fn DragMoveFn) { func (c *ControlBase) DragMoved() DragMovedEventHandler { return &c.dragMoved }
c.onDragMove = fn
}
func (c *ControlBase) OnDragEnd(fn DragEndFn) { c.onDragEnd = fn } func (c *ControlBase) DragStarted() DragStartedEventHandler { return &c.dragStarted }
func (c *ControlBase) Render(Context) {} func (c *ControlBase) Render(Context) {}

46
ui/events.go Normal file
View File

@ -0,0 +1,46 @@
package ui
type EventFn func(Context) bool
type EventStateFn func(Context, interface{})
func NewEvents() *Events {
return &Events{events: map[uint]EventStateFn{}}
}
type Events struct {
nextID uint
events map[uint]EventStateFn
}
type EventHandler interface {
AddHandler(EventFn) uint
AddHandlerState(EventStateFn) uint
RemoveHandler(uint)
}
func (e *Events) Notify(ctx Context, state interface{}) bool {
if e.events == nil {
return false
}
for _, handler := range e.events {
handler(ctx, state)
}
return len(e.events) > 0
}
func (e *Events) AddHandler(handler EventFn) uint {
return e.AddHandlerState(func(ctx Context, _ interface{}) { handler(ctx) })
}
func (e *Events) AddHandlerState(handler EventStateFn) uint {
if e.events == nil {
e.events = map[uint]EventStateFn{}
}
id := e.nextID
e.nextID++
e.events[id] = handler
return id
}
func (e *Events) RemoveHandler(id uint) { delete(e.events, id) }

View File

@ -4,10 +4,9 @@ import (
"image/color" "image/color"
"log" "log"
// _ "opslag.de/schobers/zntg/sdlui" // import the renderer for the UI _ "opslag.de/schobers/zntg/sdlui" // import the renderer for the UI
_ "opslag.de/schobers/zntg/allg5ui" // import the renderer for the UI // _ "opslag.de/schobers/zntg/allg5ui" // import the renderer for the UI
"opslag.de/schobers/geom"
"opslag.de/schobers/zntg/ui" "opslag.de/schobers/zntg/ui"
) )
@ -59,7 +58,7 @@ func (b *basic) Init(ctx ui.Context) error {
b.Text = "Type here..." b.Text = "Type here..."
})), 8), })), 8),
ui.Margin(ui.BuildButton("Quit", func(b *ui.Button) { ui.Margin(ui.BuildButton("Quit", func(b *ui.Button) {
b.OnClick(func(geom.PointF32, ui.MouseButton) { b.ControlClicked().AddHandler(func(ui.Context, ui.ControlClickedArgs) {
ctx.Quit() ctx.Quit()
}) })
b.Tooltip = "Will quit the application" b.Tooltip = "Will quit the application"

View File

@ -95,7 +95,7 @@ func (o *overflow) DesiredSize(ctx Context) geom.PointF32 {
return geom.PtF32(geom.NaN32(), geom.NaN32()) return geom.PtF32(geom.NaN32(), geom.NaN32())
} }
func (o *overflow) Handle(ctx Context, e Event) { func (o *overflow) Handle(ctx Context, e Event) bool {
if o.Content != o.proxied { if o.Content != o.proxied {
o.hor.ContentOffset = 0 o.hor.ContentOffset = 0
o.ver.ContentOffset = 0 o.ver.ContentOffset = 0
@ -117,10 +117,11 @@ func (o *overflow) Handle(ctx Context, e Event) {
content.Max = content.Max.Add(contentO) content.Max = content.Max.Add(contentO)
if e.MouseWheel != 0 && e.Pos().In(content) { if e.MouseWheel != 0 && e.Pos().In(content) {
o.ver.ContentOffset = geom.Max32(0, geom.Min32(o.ver.ContentLength-content.Dy(), o.ver.ContentOffset-36*e.MouseWheel)) o.ver.ContentOffset = geom.Max32(0, geom.Min32(o.ver.ContentLength-content.Dy(), o.ver.ContentOffset-36*e.MouseWheel))
return true
} }
} }
} }
o.Content.Handle(ctx, e) return o.Content.Handle(ctx, e)
} }
func (o *overflow) IsInBounds(p geom.PointF32) bool { return p.Sub(o.offset).In(o.bounds) } func (o *overflow) IsInBounds(p geom.PointF32) bool { return p.Sub(o.offset).In(o.bounds) }

View File

@ -40,13 +40,13 @@ func (o *Overlays) Arrange(ctx Context, bounds geom.RectangleF32, offset geom.Po
} }
} }
func (o *Overlays) Handle(ctx Context, e Event) { func (o *Overlays) Handle(ctx Context, e Event) bool {
for overlay, visible := range o.visible { for overlay, visible := range o.visible {
if visible { if visible {
o.overlays[overlay].Handle(ctx, e) o.overlays[overlay].Handle(ctx, e) // ignore handled state on overlays
} }
} }
o.Proxy.Handle(ctx, e) return o.Proxy.Handle(ctx, e)
} }
func (o *Overlays) Hide(name string) { func (o *Overlays) Hide(name string) {

View File

@ -16,8 +16,8 @@ func (p *Proxy) DesiredSize(ctx Context) geom.PointF32 {
return p.Content.DesiredSize(ctx) return p.Content.DesiredSize(ctx)
} }
func (p *Proxy) Handle(ctx Context, e Event) { func (p *Proxy) Handle(ctx Context, e Event) bool {
p.Content.Handle(ctx, e) return p.Content.Handle(ctx, e)
} }
func (p *Proxy) Render(ctx Context) { func (p *Proxy) Render(ctx Context) {
@ -34,20 +34,4 @@ func (p *Proxy) IsOver() bool { return p.Content.IsOver() }
func (p *Proxy) Offset() geom.PointF32 { return p.Content.Offset() } func (p *Proxy) Offset() geom.PointF32 { return p.Content.Offset() }
func (p *Proxy) OnClick(fn ClickFn) {
p.Content.OnClick(fn)
}
func (p *Proxy) OnDragStart(fn DragStartFn) {
p.Content.OnDragStart(fn)
}
func (p *Proxy) OnDragMove(fn DragMoveFn) {
p.Content.OnDragMove(fn)
}
func (p *Proxy) OnDragEnd(fn DragEndFn) {
p.Content.OnDragEnd(fn)
}
func (p *Proxy) Parent() Control { return p.Content.Parent() } func (p *Proxy) Parent() Control { return p.Content.Parent() }

View File

@ -19,14 +19,14 @@ type Scrollbar struct {
func BuildScrollbar(o Orientation, fn func(s *Scrollbar)) *Scrollbar { func BuildScrollbar(o Orientation, fn func(s *Scrollbar)) *Scrollbar {
var s = &Scrollbar{Orientation: o, ContentLength: 0, ContentOffset: 0} var s = &Scrollbar{Orientation: o, ContentLength: 0, ContentOffset: 0}
s.handle.OnDragStart(func(_ geom.PointF32) { s.handle.DragStarted().AddHandler(func(Context, DragStartedArgs) {
s.startDragOffset = s.ContentOffset s.startDragOffset = s.ContentOffset
}) })
s.handle.OnDragMove(func(start, move geom.PointF32) { s.handle.DragMoved().AddHandler(func(_ Context, args DragMovedArgs) {
var length = s.Orientation.SizeParallel(s.bounds) var length = s.Orientation.SizeParallel(s.bounds)
var handleMaxOffset = length - s.Orientation.SizeParallel(s.handle.bounds) var handleMaxOffset = length - s.Orientation.SizeParallel(s.handle.bounds)
var hidden = s.ContentLength - length var hidden = s.ContentLength - length
var offset = (s.Orientation.LengthParallel(move) - s.Orientation.LengthParallel(start)) / handleMaxOffset var offset = (s.Orientation.LengthParallel(args.Current) - s.Orientation.LengthParallel(args.Start)) / handleMaxOffset
s.ContentOffset = geom.Max32(0, geom.Min32(s.startDragOffset+offset*hidden, hidden)) s.ContentOffset = geom.Max32(0, geom.Min32(s.startDragOffset+offset*hidden, hidden))
}) })
if fn != nil { if fn != nil {
@ -44,15 +44,16 @@ func (s *Scrollbar) DesiredSize(ctx Context) geom.PointF32 {
return s.Orientation.Pt(geom.NaN32(), ctx.Style().Dimensions.ScrollbarWidth) return s.Orientation.Pt(geom.NaN32(), ctx.Style().Dimensions.ScrollbarWidth)
} }
func (s *Scrollbar) Handle(ctx Context, e Event) { func (s *Scrollbar) Handle(ctx Context, e Event) bool {
s.handle.Handle(ctx, e) s.handle.Handle(ctx, e)
switch e := e.(type) { switch e := e.(type) {
case *MouseMoveEvent: case *MouseMoveEvent:
if e.MouseWheel != 0 && e.Pos().Sub(s.offset).In(s.bounds) { if e.MouseWheel != 0 && e.Pos().Sub(s.offset).In(s.bounds) {
s.ContentOffset = geom.Max32(0, geom.Min32(s.ContentLength-s.Orientation.SizeParallel(s.bounds), s.ContentOffset-36*e.MouseWheel)) s.ContentOffset = geom.Max32(0, geom.Min32(s.ContentLength-s.Orientation.SizeParallel(s.bounds), s.ContentOffset-36*e.MouseWheel))
return true
} }
} }
s.ControlBase.Handle(ctx, e) return s.ControlBase.Handle(ctx, e)
} }
func (s *Scrollbar) Render(ctx Context) { func (s *Scrollbar) Render(ctx Context) {

View File

@ -20,8 +20,8 @@ type Slider struct {
func BuildSlider(o Orientation, fn func(s *Slider)) *Slider { func BuildSlider(o Orientation, fn func(s *Slider)) *Slider {
s := &Slider{Orientation: o} s := &Slider{Orientation: o}
s.handle.OnDragStart(func(start geom.PointF32) { s.handleDrag(start) }) s.handle.DragStarted().AddHandler(func(_ Context, args DragStartedArgs) { s.handleDrag(args.Start) })
s.handle.OnDragMove(func(_, pos geom.PointF32) { s.handleDrag(pos) }) s.handle.DragMoved().AddHandler(func(_ Context, args DragMovedArgs) { s.handleDrag(args.Current) })
if fn != nil { if fn != nil {
fn(s) fn(s)
} }
@ -109,10 +109,15 @@ func (s *Slider) DesiredSize(ctx Context) geom.PointF32 {
return geom.PtF32(w, geom.NaN32()) return geom.PtF32(w, geom.NaN32())
} }
func (s *Slider) Handle(ctx Context, e Event) { func (s *Slider) Handle(ctx Context, e Event) bool {
s.handle.Handle(ctx, e) defer s.setValue(s.Value)
s.ControlBase.Handle(ctx, e) if s.handle.Handle(ctx, e) {
s.setValue(s.Value) return true
}
if s.ControlBase.Handle(ctx, e) {
return true
}
return false
} }
func (s *Slider) Render(ctx Context) { func (s *Slider) Render(ctx Context) {
@ -157,11 +162,12 @@ func (h *sliderHandle) texture(ctx Context) Texture {
return h.handle return h.handle
} }
func (h *sliderHandle) Handle(ctx Context, e Event) { func (h *sliderHandle) Handle(ctx Context, e Event) bool {
h.ControlBase.Handle(ctx, e) h.ControlBase.Handle(ctx, e)
if h.IsOver() { if h.IsOver() {
ctx.Renderer().SetMouseCursor(MouseCursorPointer) ctx.Renderer().SetMouseCursor(MouseCursorPointer)
} }
return true
} }
func (h *sliderHandle) Render(ctx Context) { func (h *sliderHandle) Render(ctx Context) {

View File

@ -125,9 +125,17 @@ func (b *TextBox) selectionRange() (int, int) {
return start, end return start, end
} }
func (b *TextBox) Handle(ctx Context, e Event) { func (b *TextBox) Handle(ctx Context, e Event) bool {
b.ControlBase.Handle(ctx, e) if b.ControlBase.Handle(ctx, e) {
return true
}
b.box.Handle(ctx, e) b.box.Handle(ctx, e)
if b.over {
ctx.Renderer().SetMouseCursor(MouseCursorText)
}
ctx.Animate()
switch e := e.(type) { switch e := e.(type) {
case *MouseButtonDownEvent: case *MouseButtonDownEvent:
if b.over { if b.over {
@ -135,13 +143,14 @@ func (b *TextBox) Handle(ctx Context, e Event) {
b.Selection.Caret = b.mousePosToCaretPos(ctx, e.MouseEvent) b.Selection.Caret = b.mousePosToCaretPos(ctx, e.MouseEvent)
b.Selection.SetSelectionToCaret() b.Selection.SetSelectionToCaret()
b.blink = time.Now() b.blink = time.Now()
} else { return true
b.Focus = false
} }
b.Focus = false
case *MouseMoveEvent: case *MouseMoveEvent:
if b.Focus && b.pressed && b.over { if b.Focus && b.pressed && b.over {
b.Selection.Caret = b.mousePosToCaretPos(ctx, e.MouseEvent) b.Selection.Caret = b.mousePosToCaretPos(ctx, e.MouseEvent)
b.Selection.End = b.Selection.Caret b.Selection.End = b.Selection.Caret
return true
} }
case *KeyDownEvent: case *KeyDownEvent:
if !b.Focus { if !b.Focus {
@ -217,16 +226,15 @@ func (b *TextBox) Handle(ctx Context, e Event) {
DefaultClipboard.WriteText(b.cut()) DefaultClipboard.WriteText(b.cut())
} }
} }
return true
case *TextInputEvent: case *TextInputEvent:
caret := b.Selection.Caret caret := b.Selection.Caret
b.Text = fmt.Sprintf("%s%c%s", b.Text[:caret], e.Character, b.Text[caret:]) b.Text = fmt.Sprintf("%s%c%s", b.Text[:caret], e.Character, b.Text[caret:])
b.Selection.Caret = caret + 1 b.Selection.Caret = caret + 1
b.Selection.SetSelectionToCaret() b.Selection.SetSelectionToCaret()
return true
} }
if b.over { return false
ctx.Renderer().SetMouseCursor(MouseCursorText)
}
ctx.Animate()
} }
func (b *TextBox) Render(ctx Context) { func (b *TextBox) Render(ctx Context) {

View File

@ -27,7 +27,7 @@ func (t *Tooltip) FontName(ctx Context) string {
return name return name
} }
func (t *Tooltip) Handle(Context, Event) {} func (t *Tooltip) Handle(Context, Event) bool { return false }
func (t *Tooltip) Render(ctx Context) { func (t *Tooltip) Render(ctx Context) {
if len(t.Text) == 0 { if len(t.Text) == 0 {