Hocus focus

This commit is contained in:
2023-01-30 17:01:47 -05:00
parent 35870951a2
commit 801c3ef6f5
15 changed files with 367 additions and 355 deletions

View File

@@ -11,9 +11,9 @@ var buttonCase = theme.C("basic", "button")
// Button is a clickable button.
type Button struct {
*core.Core
*core.SelectableCore
*core.FocusableCore
core core.CoreControl
selectableControl core.SelectableCoreControl
focusableControl core.FocusableCoreControl
drawer artist.TextDrawer
pressed bool
@@ -26,8 +26,8 @@ type Button struct {
func NewButton (text string) (element *Button) {
element = &Button { }
element.Core, element.core = core.NewCore(element)
element.SelectableCore,
element.selectableControl = core.NewSelectableCore (func () {
element.FocusableCore,
element.focusableControl = core.NewFocusableCore (func () {
if element.core.HasImage () {
element.draw()
element.core.DamageAll()
@@ -45,7 +45,7 @@ func (element *Button) Resize (width, height int) {
func (element *Button) HandleMouseDown (x, y int, button tomo.Button) {
if !element.Enabled() { return }
if !element.Selected() { element.Select() }
if !element.Focused() { element.Focus() }
if button != tomo.ButtonLeft { return }
element.pressed = true
if element.core.HasImage() {
@@ -106,7 +106,7 @@ func (element *Button) OnClick (callback func ()) {
// SetEnabled sets whether this button can be clicked or not.
func (element *Button) SetEnabled (enabled bool) {
element.selectableControl.SetEnabled(enabled)
element.focusableControl.SetEnabled(enabled)
}
// SetText sets the button's label text.
@@ -131,7 +131,7 @@ func (element *Button) draw () {
pattern, inset := theme.ButtonPattern(theme.PatternState {
Case: buttonCase,
Disabled: !element.Enabled(),
Selected: element.Selected(),
Focused: element.Focused(),
Pressed: element.pressed,
})

View File

@@ -11,9 +11,9 @@ var checkboxCase = theme.C("basic", "checkbox")
// Checkbox is a toggle-able checkbox with a label.
type Checkbox struct {
*core.Core
*core.SelectableCore
*core.FocusableCore
core core.CoreControl
selectableControl core.SelectableCoreControl
focusableControl core.FocusableCoreControl
drawer artist.TextDrawer
pressed bool
@@ -27,8 +27,8 @@ type Checkbox struct {
func NewCheckbox (text string, checked bool) (element *Checkbox) {
element = &Checkbox { checked: checked }
element.Core, element.core = core.NewCore(element)
element.SelectableCore,
element.selectableControl = core.NewSelectableCore (func () {
element.FocusableCore,
element.focusableControl = core.NewFocusableCore (func () {
if element.core.HasImage () {
element.draw()
element.core.DamageAll()
@@ -47,7 +47,7 @@ func (element *Checkbox) Resize (width, height int) {
func (element *Checkbox) HandleMouseDown (x, y int, button tomo.Button) {
if !element.Enabled() { return }
element.Select()
element.Focus()
element.pressed = true
if element.core.HasImage() {
element.draw()
@@ -113,7 +113,7 @@ func (element *Checkbox) Value () (checked bool) {
// SetEnabled sets whether this checkbox can be toggled or not.
func (element *Checkbox) SetEnabled (enabled bool) {
element.selectableControl.SetEnabled(enabled)
element.focusableControl.SetEnabled(enabled)
}
// SetText sets the checkbox's label text.
@@ -150,7 +150,7 @@ func (element *Checkbox) draw () {
pattern, inset := theme.ButtonPattern(theme.PatternState {
Case: checkboxCase,
Disabled: !element.Enabled(),
Selected: element.Selected(),
Focused: element.Focused(),
Pressed: element.pressed,
})
artist.FillRectangle(element.core, pattern, boxBounds)

View File

@@ -14,16 +14,16 @@ type Container struct {
*core.Core
core core.CoreControl
layout tomo.Layout
children []tomo.LayoutEntry
drags [10]tomo.MouseTarget
warping bool
selected bool
selectable bool
flexible bool
layout tomo.Layout
children []tomo.LayoutEntry
drags [10]tomo.MouseTarget
warping bool
focused bool
focusable bool
flexible bool
onSelectionRequest func () (granted bool)
onSelectionMotionRequest func (tomo.SelectionDirection) (granted bool)
onFocusRequest func () (granted bool)
onFocusMotionRequest func (tomo.KeynavDirection) (granted bool)
onFlexibleHeightChange func ()
}
@@ -57,14 +57,14 @@ func (element *Container) Adopt (child tomo.Element, expand bool) {
if child0, ok := child.(tomo.Flexible); ok {
child0.OnFlexibleHeightChange(element.updateMinimumSize)
}
if child0, ok := child.(tomo.Selectable); ok {
child0.OnSelectionRequest (func () (granted bool) {
return element.childSelectionRequestCallback(child0)
if child0, ok := child.(tomo.Focusable); ok {
child0.OnFocusRequest (func () (granted bool) {
return element.childFocusRequestCallback(child0)
})
child0.OnSelectionMotionRequest (
func (direction tomo.SelectionDirection) (granted bool) {
if element.onSelectionMotionRequest == nil { return }
return element.onSelectionMotionRequest(direction)
child0.OnFocusMotionRequest (
func (direction tomo.KeynavDirection) (granted bool) {
if element.onFocusMotionRequest == nil { return }
return element.onFocusMotionRequest(direction)
})
}
@@ -132,11 +132,11 @@ func (element *Container) Disown (child tomo.Element) {
func (element *Container) clearChildEventHandlers (child tomo.Element) {
child.OnDamage(nil)
child.OnMinimumSizeChange(nil)
if child0, ok := child.(tomo.Selectable); ok {
child0.OnSelectionRequest(nil)
child0.OnSelectionMotionRequest(nil)
if child0.Selected() {
child0.HandleDeselection()
if child0, ok := child.(tomo.Focusable); ok {
child0.OnFocusRequest(nil)
child0.OnFocusMotionRequest(nil)
if child0.Focused() {
child0.HandleUnfocus()
}
}
if child0, ok := child.(tomo.Flexible); ok {
@@ -238,7 +238,7 @@ func (element *Container) HandleMouseScroll (x, y int, deltaX, deltaY float64) {
}
func (element *Container) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) {
element.forSelected (func (child tomo.Selectable) bool {
element.forFocused (func (child tomo.Focusable) bool {
child0, handlesKeyboard := child.(tomo.KeyboardTarget)
if handlesKeyboard {
child0.HandleKeyDown(key, modifiers)
@@ -248,7 +248,7 @@ func (element *Container) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers)
}
func (element *Container) HandleKeyUp (key tomo.Key, modifiers tomo.Modifiers) {
element.forSelected (func (child tomo.Selectable) bool {
element.forFocused (func (child tomo.Focusable) bool {
child0, handlesKeyboard := child.(tomo.KeyboardTarget)
if handlesKeyboard {
child0.HandleKeyUp(key, modifiers)
@@ -257,103 +257,6 @@ func (element *Container) HandleKeyUp (key tomo.Key, modifiers tomo.Modifiers) {
})
}
func (element *Container) Selected () (selected bool) {
return element.selected
}
func (element *Container) Select () {
if element.onSelectionRequest != nil {
element.onSelectionRequest()
}
}
func (element *Container) HandleSelection (direction tomo.SelectionDirection) (ok bool) {
if !element.selectable { return false }
direction = direction.Canon()
firstSelected := element.firstSelected()
if firstSelected < 0 {
// no element is currently selected, so we need to select either
// the first or last selectable element depending on the
// direction.
switch direction {
case tomo.SelectionDirectionNeutral, tomo.SelectionDirectionForward:
// if we recieve a neutral or forward direction, select
// the first selectable element.
return element.selectFirstSelectableElement(direction)
case tomo.SelectionDirectionBackward:
// if we recieve a backward direction, select the last
// selectable element.
return element.selectLastSelectableElement(direction)
}
} else {
// an element is currently selected, so we need to move the
// selection in the specified direction
firstSelectedChild :=
element.children[firstSelected].Element.(tomo.Selectable)
// before we move the selection, the currently selected child
// may also be able to move its selection. if the child is able
// to do that, we will let it and not move ours.
if firstSelectedChild.HandleSelection(direction) {
return true
}
// find the previous/next selectable element relative to the
// currently selected element, if it exists.
for index := firstSelected + int(direction);
index < len(element.children) && index >= 0;
index += int(direction) {
child, selectable :=
element.children[index].
Element.(tomo.Selectable)
if selectable && child.HandleSelection(direction) {
// we have found one, so we now actually move
// the selection.
firstSelectedChild.HandleDeselection()
element.selected = true
return true
}
}
}
return false
}
func (element *Container) selectFirstSelectableElement (
direction tomo.SelectionDirection,
) (
ok bool,
) {
element.forSelectable (func (child tomo.Selectable) bool {
if child.HandleSelection(direction) {
element.selected = true
ok = true
return false
}
return true
})
return
}
func (element *Container) selectLastSelectableElement (
direction tomo.SelectionDirection,
) (
ok bool,
) {
element.forSelectableBackward (func (child tomo.Selectable) bool {
if child.HandleSelection(direction) {
element.selected = true
ok = true
return false
}
return true
})
return
}
func (element *Container) FlexibleHeightFor (width int) (height int) {
return element.layout.FlexibleHeightFor(element.children, width)
}
@@ -362,37 +265,134 @@ func (element *Container) OnFlexibleHeightChange (callback func ()) {
element.onFlexibleHeightChange = callback
}
func (element *Container) HandleDeselection () {
element.selected = false
element.forSelected (func (child tomo.Selectable) bool {
child.HandleDeselection()
func (element *Container) Focused () (focused bool) {
return element.focused
}
func (element *Container) Focus () {
if element.onFocusRequest != nil {
element.onFocusRequest()
}
}
func (element *Container) HandleFocus (direction tomo.KeynavDirection) (ok bool) {
if !element.focusable { return false }
direction = direction.Canon()
firstFocused := element.firstFocused()
if firstFocused < 0 {
// no element is currently focused, so we need to focus either
// the first or last focusable element depending on the
// direction.
switch direction {
case tomo.KeynavDirectionNeutral, tomo.KeynavDirectionForward:
// if we recieve a neutral or forward direction, focus
// the first focusable element.
return element.focusFirstFocusableElement(direction)
case tomo.KeynavDirectionBackward:
// if we recieve a backward direction, focus the last
// focusable element.
return element.focusLastFocusableElement(direction)
}
} else {
// an element is currently focused, so we need to move the
// focus in the specified direction
firstFocusedChild :=
element.children[firstFocused].Element.(tomo.Focusable)
// before we move the focus, the currently focused child
// may also be able to move its focus. if the child is able
// to do that, we will let it and not move ours.
if firstFocusedChild.HandleFocus(direction) {
return true
}
// find the previous/next focusable element relative to the
// currently focused element, if it exists.
for index := firstFocused + int(direction);
index < len(element.children) && index >= 0;
index += int(direction) {
child, focusable :=
element.children[index].
Element.(tomo.Focusable)
if focusable && child.HandleFocus(direction) {
// we have found one, so we now actually move
// the focus.
firstFocusedChild.HandleUnfocus()
element.focused = true
return true
}
}
}
return false
}
func (element *Container) focusFirstFocusableElement (
direction tomo.KeynavDirection,
) (
ok bool,
) {
element.forFocusable (func (child tomo.Focusable) bool {
if child.HandleFocus(direction) {
element.focused = true
ok = true
return false
}
return true
})
return
}
func (element *Container) focusLastFocusableElement (
direction tomo.KeynavDirection,
) (
ok bool,
) {
element.forFocusableBackward (func (child tomo.Focusable) bool {
if child.HandleFocus(direction) {
element.focused = true
ok = true
return false
}
return true
})
return
}
func (element *Container) HandleUnfocus () {
element.focused = false
element.forFocused (func (child tomo.Focusable) bool {
child.HandleUnfocus()
return true
})
}
func (element *Container) OnSelectionRequest (callback func () (granted bool)) {
element.onSelectionRequest = callback
func (element *Container) OnFocusRequest (callback func () (granted bool)) {
element.onFocusRequest = callback
}
func (element *Container) OnSelectionMotionRequest (
callback func (direction tomo.SelectionDirection) (granted bool),
func (element *Container) OnFocusMotionRequest (
callback func (direction tomo.KeynavDirection) (granted bool),
) {
element.onSelectionMotionRequest = callback
element.onFocusMotionRequest = callback
}
func (element *Container) forSelected (callback func (child tomo.Selectable) bool) {
func (element *Container) forFocused (callback func (child tomo.Focusable) bool) {
for _, entry := range element.children {
child, selectable := entry.Element.(tomo.Selectable)
if selectable && child.Selected() {
child, focusable := entry.Element.(tomo.Focusable)
if focusable && child.Focused() {
if !callback(child) { break }
}
}
}
func (element *Container) forSelectable (callback func (child tomo.Selectable) bool) {
func (element *Container) forFocusable (callback func (child tomo.Focusable) bool) {
for _, entry := range element.children {
child, selectable := entry.Element.(tomo.Selectable)
if selectable {
child, focusable := entry.Element.(tomo.Focusable)
if focusable {
if !callback(child) { break }
}
}
@@ -400,26 +400,26 @@ func (element *Container) forSelectable (callback func (child tomo.Selectable) b
func (element *Container) forFlexible (callback func (child tomo.Flexible) bool) {
for _, entry := range element.children {
child, selectable := entry.Element.(tomo.Flexible)
if selectable {
child, flexible := entry.Element.(tomo.Flexible)
if flexible {
if !callback(child) { break }
}
}
}
func (element *Container) forSelectableBackward (callback func (child tomo.Selectable) bool) {
func (element *Container) forFocusableBackward (callback func (child tomo.Focusable) bool) {
for index := len(element.children) - 1; index >= 0; index -- {
child, selectable := element.children[index].Element.(tomo.Selectable)
if selectable {
child, focusable := element.children[index].Element.(tomo.Focusable)
if focusable {
if !callback(child) { break }
}
}
}
func (element *Container) firstSelected () (index int) {
func (element *Container) firstFocused () (index int) {
for currentIndex, entry := range element.children {
child, selectable := entry.Element.(tomo.Selectable)
if selectable && child.Selected() {
child, focusable := entry.Element.(tomo.Focusable)
if focusable && child.Focused() {
return currentIndex
}
}
@@ -427,9 +427,9 @@ func (element *Container) firstSelected () (index int) {
}
func (element *Container) reflectChildProperties () {
element.selectable = false
element.forSelectable (func (tomo.Selectable) bool {
element.selectable = true
element.focusable = false
element.forFocusable (func (tomo.Focusable) bool {
element.focusable = true
return false
})
element.flexible = false
@@ -437,22 +437,22 @@ func (element *Container) reflectChildProperties () {
element.flexible = true
return false
})
if !element.selectable {
element.selected = false
if !element.focusable {
element.focused = false
}
}
func (element *Container) childSelectionRequestCallback (
child tomo.Selectable,
func (element *Container) childFocusRequestCallback (
child tomo.Focusable,
) (
granted bool,
) {
if element.onSelectionRequest != nil && element.onSelectionRequest() {
element.forSelected (func (child tomo.Selectable) bool {
child.HandleDeselection()
if element.onFocusRequest != nil && element.onFocusRequest() {
element.forFocused (func (child tomo.Focusable) bool {
child.HandleUnfocus()
return true
})
child.HandleSelection(tomo.SelectionDirectionNeutral)
child.HandleFocus(tomo.KeynavDirectionNeutral)
return true
} else {
return false

View File

@@ -12,9 +12,9 @@ var listCase = theme.C("basic", "list")
// List is an element that contains several objects that a user can select.
type List struct {
*core.Core
*core.SelectableCore
*core.FocusableCore
core core.CoreControl
selectableControl core.SelectableCoreControl
focusableControl core.FocusableCoreControl
pressed bool
@@ -34,8 +34,8 @@ type List struct {
func NewList (entries ...ListEntry) (element *List) {
element = &List { selectedEntry: -1 }
element.Core, element.core = core.NewCore(element)
element.SelectableCore,
element.selectableControl = core.NewSelectableCore (func () {
element.FocusableCore,
element.focusableControl = core.NewFocusableCore (func () {
if element.core.HasImage () {
element.draw()
element.core.DamageAll()
@@ -78,7 +78,7 @@ func (element *List) Collapse (width, height int) {
func (element *List) HandleMouseDown (x, y int, button tomo.Button) {
if !element.Enabled() { return }
if !element.Selected() { element.Select() }
if !element.Focused() { element.Focus() }
if button != tomo.ButtonLeft { return }
element.pressed = true
if element.selectUnderMouse(x, y) && element.core.HasImage() {
@@ -377,7 +377,7 @@ func (element *List) draw () {
pattern, inset := theme.ListPattern(theme.PatternState {
Case: listCase,
Disabled: !element.Enabled(),
Selected: element.Selected(),
Focused: element.Focused(),
})
artist.FillRectangle(element.core, pattern, bounds)
@@ -394,6 +394,6 @@ func (element *List) draw () {
if entryPosition.Y > bounds.Max.Y { break }
entry.Draw (
innerCanvas, entryPosition,
element.Selected(), element.selectedEntry == index)
element.Focused(), element.selectedEntry == index)
}
}

View File

@@ -55,14 +55,14 @@ func (entry *ListEntry) updateBounds () {
func (entry *ListEntry) Draw (
destination tomo.Canvas,
offset image.Point,
selected bool,
focused bool,
on bool,
) (
updatedRegion image.Rectangle,
) {
pattern, _ := theme.ItemPattern(theme.PatternState {
Case: listEntryCase,
Selected: selected,
Focused: focused,
On: on,
})
artist.FillRectangle (
@@ -71,7 +71,7 @@ func (entry *ListEntry) Draw (
entry.Bounds().Add(offset))
foreground, _ := theme.ForegroundPattern (theme.PatternState {
Case: listEntryCase,
Selected: selected,
Focused: focused,
On: on,
})
return entry.drawer.Draw (

View File

@@ -15,7 +15,7 @@ var scrollBarVerticalCase = theme.C("basic", "scrollBarVertical")
type ScrollContainer struct {
*core.Core
core core.CoreControl
selected bool
focused bool
child tomo.Scrollable
childWidth, childHeight int
@@ -40,8 +40,8 @@ type ScrollContainer struct {
bar image.Rectangle
}
onSelectionRequest func () (granted bool)
onSelectionMotionRequest func (tomo.SelectionDirection) (granted bool)
onFocusRequest func () (granted bool)
onFocusMotionRequest func (tomo.KeynavDirection) (granted bool)
}
// NewScrollContainer creates a new scroll container with the specified scroll
@@ -80,11 +80,11 @@ func (element *ScrollContainer) Adopt (child tomo.Scrollable) {
child.OnDamage(element.childDamageCallback)
child.OnMinimumSizeChange(element.updateMinimumSize)
child.OnScrollBoundsChange(element.childScrollBoundsChangeCallback)
if newChild, ok := child.(tomo.Selectable); ok {
newChild.OnSelectionRequest (
element.childSelectionRequestCallback)
newChild.OnSelectionMotionRequest (
element.childSelectionMotionRequestCallback)
if newChild, ok := child.(tomo.Focusable); ok {
newChild.OnFocusRequest (
element.childFocusRequestCallback)
newChild.OnFocusMotionRequest (
element.childFocusMotionRequestCallback)
}
// TODO: somehow inform the core that we do not in fact want to
@@ -193,82 +193,80 @@ func (element *ScrollContainer) scrollChildBy (x, y int) {
element.child.ScrollTo(scrollPoint)
}
func (element *ScrollContainer) Selected () (selected bool) {
return element.selected
func (element *ScrollContainer) Focused () (focused bool) {
return element.focused
}
func (element *ScrollContainer) Select () {
if element.onSelectionRequest != nil {
element.onSelectionRequest()
func (element *ScrollContainer) Focus () {
if element.onFocusRequest != nil {
element.onFocusRequest()
}
}
func (element *ScrollContainer) HandleSelection (
direction tomo.SelectionDirection,
func (element *ScrollContainer) HandleFocus (
direction tomo.KeynavDirection,
) (
accepted bool,
) {
if child, ok := element.child.(tomo.Selectable); ok {
element.selected = true
return child.HandleSelection(direction)
if child, ok := element.child.(tomo.Focusable); ok {
element.focused = true
return child.HandleFocus(direction)
} else {
element.selected = false
element.focused = false
return false
}
}
func (element *ScrollContainer) HandleDeselection () {
if child, ok := element.child.(tomo.Selectable); ok {
child.HandleDeselection()
func (element *ScrollContainer) HandleUnfocus () {
if child, ok := element.child.(tomo.Focusable); ok {
child.HandleUnfocus()
}
element.selected = false
element.focused = false
}
func (element *ScrollContainer) OnSelectionRequest (callback func () (granted bool)) {
element.onSelectionRequest = callback
func (element *ScrollContainer) OnFocusRequest (callback func () (granted bool)) {
element.onFocusRequest = callback
}
func (element *ScrollContainer) OnSelectionMotionRequest (
callback func (direction tomo.SelectionDirection) (granted bool),
func (element *ScrollContainer) OnFocusMotionRequest (
callback func (direction tomo.KeynavDirection) (granted bool),
) {
element.onSelectionMotionRequest = callback
element.onFocusMotionRequest = callback
}
func (element *ScrollContainer) childDamageCallback (region tomo.Canvas) {
element.core.DamageRegion(artist.Paste(element, region, image.Point { }))
}
func (element *ScrollContainer) childSelectionRequestCallback () (granted bool) {
child, ok := element.child.(tomo.Selectable)
func (element *ScrollContainer) childFocusRequestCallback () (granted bool) {
child, ok := element.child.(tomo.Focusable)
if !ok { return false }
if element.onSelectionRequest != nil && element.onSelectionRequest() {
child.HandleSelection(tomo.SelectionDirectionNeutral)
if element.onFocusRequest != nil && element.onFocusRequest() {
child.HandleFocus(tomo.KeynavDirectionNeutral)
return true
} else {
return false
}
}
func (element *ScrollContainer) childSelectionMotionRequestCallback (
direction tomo.SelectionDirection,
func (element *ScrollContainer) childFocusMotionRequestCallback (
direction tomo.KeynavDirection,
) (
granted bool,
) {
if element.onSelectionMotionRequest == nil {
return
}
return element.onSelectionMotionRequest(direction)
if element.onFocusMotionRequest == nil { return }
return element.onFocusMotionRequest(direction)
}
func (element *ScrollContainer) clearChildEventHandlers (child tomo.Scrollable) {
child.OnDamage(nil)
child.OnMinimumSizeChange(nil)
child.OnScrollBoundsChange(nil)
if child0, ok := child.(tomo.Selectable); ok {
child0.OnSelectionRequest(nil)
child0.OnSelectionMotionRequest(nil)
if child0.Selected() {
child0.HandleDeselection()
if child0, ok := child.(tomo.Focusable); ok {
child0.OnFocusRequest(nil)
child0.OnFocusMotionRequest(nil)
if child0.Focused() {
child0.HandleUnfocus()
}
}
if child0, ok := child.(tomo.Flexible); ok {

View File

@@ -12,9 +12,9 @@ var switchCase = theme.C("basic", "switch")
// functionally identical to Checkbox, but plays a different semantic role.
type Switch struct {
*core.Core
*core.SelectableCore
*core.FocusableCore
core core.CoreControl
selectableControl core.SelectableCoreControl
focusableControl core.FocusableCoreControl
drawer artist.TextDrawer
pressed bool
@@ -28,8 +28,8 @@ type Switch struct {
func NewSwitch (text string, on bool) (element *Switch) {
element = &Switch { checked: on, text: text }
element.Core, element.core = core.NewCore(element)
element.SelectableCore,
element.selectableControl = core.NewSelectableCore (func () {
element.FocusableCore,
element.focusableControl = core.NewFocusableCore (func () {
if element.core.HasImage () {
element.draw()
element.core.DamageAll()
@@ -49,7 +49,7 @@ func (element *Switch) Resize (width, height int) {
func (element *Switch) HandleMouseDown (x, y int, button tomo.Button) {
if !element.Enabled() { return }
element.Select()
element.Focus()
element.pressed = true
if element.core.HasImage() {
element.draw()
@@ -115,7 +115,7 @@ func (element *Switch) Value () (on bool) {
// SetEnabled sets whether this switch can be flipped or not.
func (element *Switch) SetEnabled (enabled bool) {
element.selectableControl.SetEnabled(enabled)
element.focusableControl.SetEnabled(enabled)
}
// SetText sets the checkbox's label text.
@@ -171,7 +171,7 @@ func (element *Switch) draw () {
gutterPattern, _ := theme.GutterPattern(theme.PatternState {
Case: switchCase,
Disabled: !element.Enabled(),
Selected: element.Selected(),
Focused: element.Focused(),
Pressed: element.pressed,
})
artist.FillRectangle(element.core, gutterPattern, gutterBounds)
@@ -179,7 +179,7 @@ func (element *Switch) draw () {
handlePattern, _ := theme.HandlePattern(theme.PatternState {
Case: switchCase,
Disabled: !element.Enabled(),
Selected: element.Selected(),
Focused: element.Focused(),
Pressed: element.pressed,
})
artist.FillRectangle(element.core, handlePattern, handleBounds)

View File

@@ -12,9 +12,9 @@ var textBoxCase = theme.C("basic", "textBox")
// TextBox is a single-line text input.
type TextBox struct {
*core.Core
*core.SelectableCore
*core.FocusableCore
core core.CoreControl
selectableControl core.SelectableCoreControl
focusableControl core.FocusableCoreControl
cursor int
scroll int
@@ -35,8 +35,8 @@ type TextBox struct {
func NewTextBox (placeholder, value string) (element *TextBox) {
element = &TextBox { }
element.Core, element.core = core.NewCore(element)
element.SelectableCore,
element.selectableControl = core.NewSelectableCore (func () {
element.FocusableCore,
element.focusableControl = core.NewFocusableCore (func () {
if element.core.HasImage () {
element.draw()
element.core.DamageAll()
@@ -61,8 +61,8 @@ func (element *TextBox) Resize (width, height int) {
}
func (element *TextBox) HandleMouseDown (x, y int, button tomo.Button) {
if !element.Enabled() { return }
if !element.Selected() { element.Select() }
if !element.Enabled() { return }
if !element.Focused() { element.Focus() }
}
func (element *TextBox) HandleMouseUp (x, y int, button tomo.Button) { }
@@ -277,13 +277,13 @@ func (element *TextBox) draw () {
// FIXME: take index into account
pattern, inset := theme.InputPattern(theme.PatternState {
Case: textBoxCase,
Case: textBoxCase,
Disabled: !element.Enabled(),
Selected: element.Selected(),
Focused: element.Focused(),
})
artist.FillRectangle(element.core, pattern, bounds)
if len(element.text) == 0 && !element.Selected() {
if len(element.text) == 0 && !element.Focused() {
// draw placeholder
textBounds := element.placeholderDrawer.LayoutBounds()
offset := image.Point {
@@ -314,7 +314,7 @@ func (element *TextBox) draw () {
foreground,
offset.Sub(textBounds.Min))
if element.Selected() {
if element.Focused() {
// cursor
cursorPosition := element.valueDrawer.PositionOf (
element.cursor)