diff options
Diffstat (limited to 'go/ui/collection.go')
| -rw-r--r-- | go/ui/collection.go | 153 |
1 files changed, 138 insertions, 15 deletions
diff --git a/go/ui/collection.go b/go/ui/collection.go index 58cc4b85..bb7a4d53 100644 --- a/go/ui/collection.go +++ b/go/ui/collection.go @@ -8,10 +8,14 @@ import ( "golang.org/x/exp/slices" ) +// Container to organise multiple Widgets +// A collection does implement the Widget interface and thus can be nested in +// another Collection. type Collection struct { Width, Height int hoverDetector hoverDetector widgets []Widget + focused Widget } func (c *Collection) Layout() (int, int) { @@ -69,10 +73,17 @@ func (c *Collection) Draw(screen *ebiten.Image) { } } -func (c *Collection) Update() error { - x, y := ebiten.CursorPosition() +func (c *Collection) Contains(x, y int) bool { + for _, w := range c.widgets { + if w.Contains(x, y) { + return true + } + } + return false +} + +func (c *Collection) FindWidgetAt(x, y int) Widget { - var activeWidget Widget // Iterate the widget in reverse order to ensure that upper widgets are // considered first for i := len(c.widgets) - 1; i >= 0; i-- { @@ -80,37 +91,149 @@ func (c *Collection) Update() error { if !w.Contains(x, y) { continue } - activeWidget = w - break + return w + } + return nil +} + +func (c *Collection) FindObjectAt(x, y int) interface{} { + + // Iterate the widget in reverse order to ensure that upper widgets are + // considered first + for i := len(c.widgets) - 1; i >= 0; i-- { + w := c.widgets[i] + if o := w.FindObjectAt(x, y); o != nil { + return o + } + } + + return nil +} + +func (c *Collection) switchFocus(fcsbl Widget) { + log.Printf("switch focus from %v to %v\n", c.focused, fcsbl) + if c.focused != nil { + c.focused.Focus(false) + + } + if fcsbl != nil { + fcsbl.Focus(true) + c.focused = fcsbl + } else { + c.focused = nil + } +} + +func (c *Collection) handleTouchInputs() error { + for _, tap := range TouchManager.Taps { + for i := len(c.widgets) - 1; i >= 0; i-- { + w := c.widgets[i] + if !w.Contains(tap.X, tap.Y) { + continue + } + if w.IsClickable() { + w.Click(tap.X, tap.Y) + } + if w.IsFocusable() { + c.switchFocus(w) + } else if c.focused != nil { + c.switchFocus(nil) + } + break + } + } + + // TODO: handle pinching + if TouchManager.Pan != nil { + pan := TouchManager.Pan + iX, iY := pan.Incremental() + + w := c.FindWidgetAt(int(pan.originX), (pan.originY)) + if w != nil && w.IsScrollable() { + w.Scroll(int(iX)/10, int(iY)/10) + } } + return nil +} + +func passInput(textInput *TextInput) { + var input []rune + input = ebiten.AppendInputChars(input) + if len(input) > 0 { + textInput.AddInput(input) + } + textInput.HandleKey() +} + +func (c *Collection) IsUpdatable() bool { + return true +} + +func (c *Collection) Update() error { + // Update all updatables + for _, w := range c.widgets { + if w.IsUpdatable() { + if err := w.Update(); err != nil { + return err + } + } + } + + if err := c.handleTouchInputs(); err != nil { + return err + } + + x, y := ebiten.CursorPosition() + + activeWidget := c.FindWidgetAt(x, y) + c.hoverDetector.update(c, x, y, activeWidget) if activeWidget == nil { + if txt, ok := c.focused.(*TextInput); ok { + if ebiten.IsKeyPressed(ebiten.KeyA) { + txt.AddInput([]rune{'a'}) + } + passInput(txt) + } return nil } scrollX, scrollY := ebiten.Wheel() if scrollX != 0 || scrollY != 0 { - if scrollable, ok := activeWidget.(Scrollable); ok { - scrollable.Scroll(int(scrollX), int(scrollY)) + if activeWidget.IsScrollable() { + activeWidget.Scroll(int(scrollX), int(scrollY)) } } if textInput, ok := activeWidget.(*TextInput); ok { - var input []rune - input = ebiten.AppendInputChars(input) - if len(input) > 0 { - textInput.AddInput(input) - } - textInput.HandleKey() + passInput(textInput) } if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) { - if btn, ok := activeWidget.(Clickable); ok { - btn.Click(x, y) + if activeWidget.IsClickable() { + activeWidget.Click(x, y) } } return nil } + +// The events for the contained widgets +// are emitted during the collections +// Update method. +func (c *Collection) IsClickable() bool { + return false +} +func (c *Collection) Click(int, int) {} + +func (c *Collection) IsScrollable() bool { + return false +} +func (c *Collection) Scroll(int, int) {} + +func (c *Collection) IsFocusable() bool { + return false +} +func (c *Collection) Focus(bool) {} |
