Container sort of conforms to the new API
Keynav is half working
This commit is contained in:
parent
410c65c072
commit
354d5f205d
@ -103,7 +103,7 @@ func (element *Button) HandleSelection (
|
||||
) (
|
||||
accepted bool,
|
||||
) {
|
||||
if direction == tomo.SelectionDirectionNeutral {
|
||||
if direction == tomo.SelectionDirectionNeutral && element.enabled {
|
||||
element.selected = true
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
|
@ -12,10 +12,12 @@ type Container struct {
|
||||
*core.Core
|
||||
core core.CoreControl
|
||||
|
||||
layout tomo.Layout
|
||||
children []tomo.LayoutEntry
|
||||
drags [10]tomo.Element
|
||||
warping bool
|
||||
layout tomo.Layout
|
||||
children []tomo.LayoutEntry
|
||||
drags [10]tomo.MouseTarget
|
||||
warping bool
|
||||
selected bool
|
||||
selectable bool
|
||||
}
|
||||
|
||||
// NewContainer creates a new container.
|
||||
@ -44,18 +46,10 @@ func (element *Container) Adopt (child tomo.Element, expand bool) {
|
||||
MinimumSizeChange: func (int, int) {
|
||||
element.updateMinimumSize()
|
||||
},
|
||||
SelectabilityChange: func (bool) {
|
||||
element.updateSelectable()
|
||||
},
|
||||
SelectionRequest: func () (granted bool) {
|
||||
if !child.Selectable() { return }
|
||||
if element.core.Select() {
|
||||
element.propogateToSelected(tomo.EventDeselect { })
|
||||
child.Handle(tomo.EventSelect { })
|
||||
return true
|
||||
}
|
||||
|
||||
return
|
||||
child, selectable := child.(tomo.Selectable)
|
||||
if !selectable { return }
|
||||
return element.childSelectionRequestCallback(child)
|
||||
},
|
||||
Draw: func (region tomo.Canvas) {
|
||||
element.drawChildRegion(child, region)
|
||||
@ -176,122 +170,172 @@ func (element *Container) childPosition (child tomo.Element) (position image.Poi
|
||||
return
|
||||
}
|
||||
|
||||
func (element *Container) Handle (event tomo.Event) {
|
||||
switch event.(type) {
|
||||
case tomo.EventResize:
|
||||
resizeEvent := event.(tomo.EventResize)
|
||||
element.core.AllocateCanvas (
|
||||
resizeEvent.Width,
|
||||
resizeEvent.Height)
|
||||
element.recalculate()
|
||||
element.draw()
|
||||
|
||||
case tomo.EventMouseDown:
|
||||
mouseDownEvent := event.(tomo.EventMouseDown)
|
||||
child := element.ChildAt (image.Pt (
|
||||
mouseDownEvent.X,
|
||||
mouseDownEvent.Y))
|
||||
if child == nil { break }
|
||||
element.drags[mouseDownEvent.Button] = child
|
||||
childPosition := element.childPosition(child)
|
||||
child.Handle (tomo.EventMouseDown {
|
||||
Button: mouseDownEvent.Button,
|
||||
X: mouseDownEvent.X - childPosition.X,
|
||||
Y: mouseDownEvent.Y - childPosition.Y,
|
||||
})
|
||||
|
||||
case tomo.EventMouseUp:
|
||||
mouseUpEvent := event.(tomo.EventMouseUp)
|
||||
child := element.drags[mouseUpEvent.Button]
|
||||
if child == nil { break }
|
||||
element.drags[mouseUpEvent.Button] = nil
|
||||
childPosition := element.childPosition(child)
|
||||
child.Handle (tomo.EventMouseUp {
|
||||
Button: mouseUpEvent.Button,
|
||||
X: mouseUpEvent.X - childPosition.X,
|
||||
Y: mouseUpEvent.Y - childPosition.Y,
|
||||
})
|
||||
|
||||
case tomo.EventMouseMove:
|
||||
mouseMoveEvent := event.(tomo.EventMouseMove)
|
||||
for _, child := range element.drags {
|
||||
if child == nil { continue }
|
||||
childPosition := element.childPosition(child)
|
||||
child.Handle (tomo.EventMouseMove {
|
||||
X: mouseMoveEvent.X - childPosition.X,
|
||||
Y: mouseMoveEvent.Y - childPosition.Y,
|
||||
})
|
||||
}
|
||||
|
||||
case tomo.EventSelect:
|
||||
if !element.Selectable() { break }
|
||||
element.core.SetSelected(true)
|
||||
|
||||
// select the first selectable element
|
||||
for _, entry := range element.children {
|
||||
if entry.Selectable() {
|
||||
entry.Handle(event)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
case tomo.EventDeselect:
|
||||
element.core.SetSelected(false)
|
||||
element.propogateToSelected(event)
|
||||
|
||||
default:
|
||||
// other events are just directly sent to the selected child.
|
||||
element.propogateToSelected(event)
|
||||
}
|
||||
return
|
||||
func (element *Container) Resize (width, height int) {
|
||||
element.core.AllocateCanvas(width, height)
|
||||
element.recalculate()
|
||||
element.draw()
|
||||
}
|
||||
|
||||
func (element *Container) propogateToSelected (event tomo.Event) {
|
||||
for _, entry := range element.children {
|
||||
if entry.Selected() {
|
||||
entry.Handle(event)
|
||||
}
|
||||
// TODO: implement KeyboardTarget
|
||||
|
||||
func (element *Container) HandleMouseDown (x, y int, button tomo.Button) {
|
||||
child, handlesMouse := element.ChildAt(image.Pt(x, y)).(tomo.MouseTarget)
|
||||
if !handlesMouse { return }
|
||||
element.drags[button] = child
|
||||
childPosition := element.childPosition(child)
|
||||
child.HandleMouseDown(x - childPosition.X, y - childPosition.Y, button)
|
||||
}
|
||||
|
||||
func (element *Container) HandleMouseUp (x, y int, button tomo.Button) {
|
||||
child := element.drags[button]
|
||||
if child == nil { return }
|
||||
element.drags[button] = nil
|
||||
childPosition := element.childPosition(child)
|
||||
child.HandleMouseUp(x - childPosition.X, y - childPosition.Y, button)
|
||||
}
|
||||
|
||||
func (element *Container) HandleMouseMove (x, y int) {
|
||||
for _, child := range element.drags {
|
||||
if child == nil { continue }
|
||||
childPosition := element.childPosition(child)
|
||||
child.HandleMouseMove(x - childPosition.X, y - childPosition.Y)
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Container) AdvanceSelection (direction int) (ok bool) {
|
||||
if !element.Selectable() { return }
|
||||
func (element *Container) HandleScroll (x, y int, deltaX, deltaY float64) {
|
||||
child, handlesMouse := element.ChildAt(image.Pt(x, y)).(tomo.MouseTarget)
|
||||
if !handlesMouse { return }
|
||||
childPosition := element.childPosition(child)
|
||||
child.HandleScroll(x - childPosition.X, y - childPosition.Y, deltaX, deltaY)
|
||||
}
|
||||
|
||||
func (element *Container) HandleKeyDown (
|
||||
key tomo.Key,
|
||||
modifiers tomo.Modifiers,
|
||||
repeated bool,
|
||||
) {
|
||||
element.forSelected (func (child tomo.Selectable) bool {
|
||||
child0, handlesKeyboard := child.(tomo.KeyboardTarget)
|
||||
if handlesKeyboard {
|
||||
child0.HandleKeyDown(key, modifiers, repeated)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (element *Container) HandleKeyUp(key tomo.Key, modifiers tomo.Modifiers) {
|
||||
element.forSelected (func (child tomo.Selectable) bool {
|
||||
child0, handlesKeyboard := child.(tomo.KeyboardTarget)
|
||||
if handlesKeyboard {
|
||||
child0.HandleKeyUp(key, modifiers)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (element *Container) Selected () (selected bool) {
|
||||
return element.selected
|
||||
}
|
||||
|
||||
func (element *Container) Select () {
|
||||
element.core.RequestSelection()
|
||||
}
|
||||
|
||||
// FIXME
|
||||
func (element *Container) HandleSelection (direction tomo.SelectionDirection) (ok bool) {
|
||||
if !element.selectable { return false }
|
||||
|
||||
firstSelected := element.firstSelected()
|
||||
if firstSelected < 0 {
|
||||
for _, entry := range element.children {
|
||||
if entry.Selectable() {
|
||||
entry.Handle(tomo.EventSelect { })
|
||||
switch direction {
|
||||
case tomo.SelectionDirectionNeutral,
|
||||
tomo.SelectionDirectionBackward:
|
||||
element.forSelectableBackward (func (child tomo.Selectable) bool {
|
||||
if child.HandleSelection (
|
||||
tomo.SelectionDirectionNeutral,
|
||||
) {
|
||||
element.selected = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
case tomo.SelectionDirectionForward:
|
||||
element.forSelectable (func (child tomo.Selectable) bool {
|
||||
if child.HandleSelection (
|
||||
tomo.SelectionDirectionNeutral,
|
||||
) {
|
||||
element.selected = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
return false
|
||||
} else {
|
||||
nextSelectable := -1
|
||||
firstSelectedChild :=
|
||||
element.children[firstSelected].Element.(tomo.Selectable)
|
||||
step := 1
|
||||
if direction < 0 { step = - 1 }
|
||||
|
||||
for index := firstSelected + step;
|
||||
index < len(element.children) && index > 0;
|
||||
index < len(element.children) && index >= 0;
|
||||
index += step {
|
||||
|
||||
if element.children[index].Selectable() {
|
||||
nextSelectable = index
|
||||
break
|
||||
child, selectable :=
|
||||
element.children[index].
|
||||
Element.(tomo.Selectable)
|
||||
if selectable && child.HandleSelection(direction) {
|
||||
firstSelectedChild.HandleDeselection()
|
||||
element.selected = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if nextSelectable > 0 {
|
||||
element.children[firstSelected ].Handle(tomo.EventDeselect { })
|
||||
element.children[nextSelectable].Handle(tomo.EventSelect { })
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (element *Container) HandleDeselection () {
|
||||
element.selected = false
|
||||
element.forSelected (func (child tomo.Selectable) bool {
|
||||
child.HandleDeselection()
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (element *Container) forSelected (callback func (child tomo.Selectable) bool) {
|
||||
for _, entry := range element.children {
|
||||
child, selectable := entry.Element.(tomo.Selectable)
|
||||
if selectable && child.Selected() {
|
||||
if !callback(child) { break }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Container) forSelectable (callback func (child tomo.Selectable) bool) {
|
||||
for _, entry := range element.children {
|
||||
child, selectable := entry.Element.(tomo.Selectable)
|
||||
if selectable {
|
||||
if !callback(child) { break }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Container) forSelectableBackward (callback func (child tomo.Selectable) bool) {
|
||||
for index := len(element.children) - 1; index >= 0; index -- {
|
||||
child, selectable := element.children[index].Element.(tomo.Selectable)
|
||||
if selectable {
|
||||
if !callback(child) { break }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Container) firstSelected () (index int) {
|
||||
for currentIndex, entry := range element.children {
|
||||
if entry.Selected() {
|
||||
child, selectable := entry.Element.(tomo.Selectable)
|
||||
if selectable && child.Selected() {
|
||||
return currentIndex
|
||||
}
|
||||
}
|
||||
@ -299,15 +343,36 @@ func (element *Container) firstSelected () (index int) {
|
||||
}
|
||||
|
||||
func (element *Container) updateSelectable () {
|
||||
selectable := false
|
||||
for _, entry := range element.children {
|
||||
if entry.Selectable() { selectable = true }
|
||||
element.selectable = false
|
||||
element.forSelectable (func (tomo.Selectable) bool {
|
||||
element.selectable = true
|
||||
return false
|
||||
})
|
||||
if !element.selectable {
|
||||
element.selected = false
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Container) childSelectionRequestCallback (
|
||||
child tomo.Selectable,
|
||||
) (
|
||||
granted bool,
|
||||
) {
|
||||
if element.core.RequestSelection() {
|
||||
element.forSelected (func (child tomo.Selectable) bool {
|
||||
child.HandleDeselection()
|
||||
return true
|
||||
})
|
||||
child.HandleSelection(tomo.SelectionDirectionNeutral)
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
element.core.SetSelectable(selectable)
|
||||
}
|
||||
|
||||
func (element *Container) updateMinimumSize () {
|
||||
element.core.SetMinimumSize(element.layout.MinimumSize(element.children))
|
||||
element.core.SetMinimumSize (
|
||||
element.layout.MinimumSize(element.children, 1e9))
|
||||
}
|
||||
|
||||
func (element *Container) recalculate () {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package basic
|
||||
|
||||
import "image"
|
||||
import "git.tebibyte.media/sashakoshka/tomo"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/theme"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||
@ -29,15 +28,12 @@ func NewLabel (text string, wrap bool) (element *Label) {
|
||||
}
|
||||
|
||||
func (element *Label) Resize (width, height int) {
|
||||
switch event.(type) {
|
||||
case tomo.EventResize:
|
||||
element.core.AllocateCanvas(width, height)
|
||||
if element.wrap {
|
||||
element.drawer.SetMaxWidth(width)
|
||||
element.drawer.SetMaxHeight(height)
|
||||
}
|
||||
element.draw()
|
||||
element.core.AllocateCanvas(width, height)
|
||||
if element.wrap {
|
||||
element.drawer.SetMaxWidth(width)
|
||||
element.drawer.SetMaxHeight(height)
|
||||
}
|
||||
element.draw()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -23,5 +23,5 @@ type Layout interface {
|
||||
// needs to properly arrange the given slice of layout entries, given a
|
||||
// "suqeeze" width so that the height can be determined for elements
|
||||
// fulfilling the Expanding interface.
|
||||
MinimumSize (entries []LayoutEntry) (width, height int)
|
||||
MinimumSize (entries []LayoutEntry, squeeze int) (width, height int)
|
||||
}
|
||||
|
Reference in New Issue
Block a user