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,
|
accepted bool,
|
||||||
) {
|
) {
|
||||||
if direction == tomo.SelectionDirectionNeutral {
|
if direction == tomo.SelectionDirectionNeutral && element.enabled {
|
||||||
element.selected = true
|
element.selected = true
|
||||||
if element.core.HasImage() {
|
if element.core.HasImage() {
|
||||||
element.draw()
|
element.draw()
|
||||||
|
@ -12,10 +12,12 @@ type Container struct {
|
|||||||
*core.Core
|
*core.Core
|
||||||
core core.CoreControl
|
core core.CoreControl
|
||||||
|
|
||||||
layout tomo.Layout
|
layout tomo.Layout
|
||||||
children []tomo.LayoutEntry
|
children []tomo.LayoutEntry
|
||||||
drags [10]tomo.Element
|
drags [10]tomo.MouseTarget
|
||||||
warping bool
|
warping bool
|
||||||
|
selected bool
|
||||||
|
selectable bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContainer creates a new container.
|
// NewContainer creates a new container.
|
||||||
@ -44,18 +46,10 @@ func (element *Container) Adopt (child tomo.Element, expand bool) {
|
|||||||
MinimumSizeChange: func (int, int) {
|
MinimumSizeChange: func (int, int) {
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
},
|
},
|
||||||
SelectabilityChange: func (bool) {
|
|
||||||
element.updateSelectable()
|
|
||||||
},
|
|
||||||
SelectionRequest: func () (granted bool) {
|
SelectionRequest: func () (granted bool) {
|
||||||
if !child.Selectable() { return }
|
child, selectable := child.(tomo.Selectable)
|
||||||
if element.core.Select() {
|
if !selectable { return }
|
||||||
element.propogateToSelected(tomo.EventDeselect { })
|
return element.childSelectionRequestCallback(child)
|
||||||
child.Handle(tomo.EventSelect { })
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
},
|
},
|
||||||
Draw: func (region tomo.Canvas) {
|
Draw: func (region tomo.Canvas) {
|
||||||
element.drawChildRegion(child, region)
|
element.drawChildRegion(child, region)
|
||||||
@ -176,122 +170,172 @@ func (element *Container) childPosition (child tomo.Element) (position image.Poi
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Container) Handle (event tomo.Event) {
|
func (element *Container) Resize (width, height int) {
|
||||||
switch event.(type) {
|
element.core.AllocateCanvas(width, height)
|
||||||
case tomo.EventResize:
|
element.recalculate()
|
||||||
resizeEvent := event.(tomo.EventResize)
|
element.draw()
|
||||||
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) propogateToSelected (event tomo.Event) {
|
// TODO: implement KeyboardTarget
|
||||||
for _, entry := range element.children {
|
|
||||||
if entry.Selected() {
|
func (element *Container) HandleMouseDown (x, y int, button tomo.Button) {
|
||||||
entry.Handle(event)
|
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) {
|
func (element *Container) HandleScroll (x, y int, deltaX, deltaY float64) {
|
||||||
if !element.Selectable() { return }
|
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()
|
firstSelected := element.firstSelected()
|
||||||
if firstSelected < 0 {
|
if firstSelected < 0 {
|
||||||
for _, entry := range element.children {
|
switch direction {
|
||||||
if entry.Selectable() {
|
case tomo.SelectionDirectionNeutral,
|
||||||
entry.Handle(tomo.EventSelect { })
|
tomo.SelectionDirectionBackward:
|
||||||
|
element.forSelectableBackward (func (child tomo.Selectable) bool {
|
||||||
|
if child.HandleSelection (
|
||||||
|
tomo.SelectionDirectionNeutral,
|
||||||
|
) {
|
||||||
|
element.selected = true
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
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 {
|
} else {
|
||||||
nextSelectable := -1
|
firstSelectedChild :=
|
||||||
|
element.children[firstSelected].Element.(tomo.Selectable)
|
||||||
step := 1
|
step := 1
|
||||||
if direction < 0 { step = - 1 }
|
if direction < 0 { step = - 1 }
|
||||||
|
|
||||||
for index := firstSelected + step;
|
for index := firstSelected + step;
|
||||||
index < len(element.children) && index > 0;
|
index < len(element.children) && index >= 0;
|
||||||
index += step {
|
index += step {
|
||||||
|
|
||||||
if element.children[index].Selectable() {
|
child, selectable :=
|
||||||
nextSelectable = index
|
element.children[index].
|
||||||
break
|
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
|
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) {
|
func (element *Container) firstSelected () (index int) {
|
||||||
for currentIndex, entry := range element.children {
|
for currentIndex, entry := range element.children {
|
||||||
if entry.Selected() {
|
child, selectable := entry.Element.(tomo.Selectable)
|
||||||
|
if selectable && child.Selected() {
|
||||||
return currentIndex
|
return currentIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,15 +343,36 @@ func (element *Container) firstSelected () (index int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (element *Container) updateSelectable () {
|
func (element *Container) updateSelectable () {
|
||||||
selectable := false
|
element.selectable = false
|
||||||
for _, entry := range element.children {
|
element.forSelectable (func (tomo.Selectable) bool {
|
||||||
if entry.Selectable() { selectable = true }
|
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 () {
|
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 () {
|
func (element *Container) recalculate () {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package basic
|
package basic
|
||||||
|
|
||||||
import "image"
|
import "image"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
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) {
|
func (element *Label) Resize (width, height int) {
|
||||||
switch event.(type) {
|
element.core.AllocateCanvas(width, height)
|
||||||
case tomo.EventResize:
|
if element.wrap {
|
||||||
element.core.AllocateCanvas(width, height)
|
element.drawer.SetMaxWidth(width)
|
||||||
if element.wrap {
|
element.drawer.SetMaxHeight(height)
|
||||||
element.drawer.SetMaxWidth(width)
|
|
||||||
element.drawer.SetMaxHeight(height)
|
|
||||||
}
|
|
||||||
element.draw()
|
|
||||||
}
|
}
|
||||||
|
element.draw()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,5 +23,5 @@ type Layout interface {
|
|||||||
// needs to properly arrange the given slice of layout entries, given a
|
// needs to properly arrange the given slice of layout entries, given a
|
||||||
// "suqeeze" width so that the height can be determined for elements
|
// "suqeeze" width so that the height can be determined for elements
|
||||||
// fulfilling the Expanding interface.
|
// 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