Added a selectability core to reduce complexity of selectables
This commit is contained in:
parent
b2b2a80a06
commit
9422ff6198
@ -9,24 +9,28 @@ import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||
// Button is a clickable button.
|
||||
type Button struct {
|
||||
*core.Core
|
||||
*core.SelectableCore
|
||||
core core.CoreControl
|
||||
|
||||
pressed bool
|
||||
enabled bool
|
||||
selected bool
|
||||
|
||||
text string
|
||||
selectableControl core.SelectableCoreControl
|
||||
drawer artist.TextDrawer
|
||||
|
||||
pressed bool
|
||||
text string
|
||||
|
||||
onClick func ()
|
||||
onSelectionRequest func () (granted bool)
|
||||
onSelectionMotionRequest func (tomo.SelectionDirection) (granted bool)
|
||||
}
|
||||
|
||||
// NewButton creates a new button with the specified label text.
|
||||
func NewButton (text string) (element *Button) {
|
||||
element = &Button { enabled: true }
|
||||
element = &Button { }
|
||||
element.Core, element.core = core.NewCore(element)
|
||||
element.SelectableCore,
|
||||
element.selectableControl = core.NewSelectableCore (func () {
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
})
|
||||
element.drawer.SetFace(theme.FontFaceRegular())
|
||||
element.SetText(text)
|
||||
return
|
||||
@ -38,8 +42,8 @@ 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.Enabled() { return }
|
||||
if !element.Selected() { element.Select() }
|
||||
if button != tomo.ButtonLeft { return }
|
||||
element.pressed = true
|
||||
if element.core.HasImage() {
|
||||
@ -59,7 +63,7 @@ func (element *Button) HandleMouseUp (x, y int, button tomo.Button) {
|
||||
within := image.Point { x, y }.
|
||||
In(element.Bounds())
|
||||
|
||||
if !element.enabled { return }
|
||||
if !element.Enabled() { return }
|
||||
if within && element.onClick != nil {
|
||||
element.onClick()
|
||||
}
|
||||
@ -69,7 +73,7 @@ func (element *Button) HandleMouseMove (x, y int) { }
|
||||
func (element *Button) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
|
||||
|
||||
func (element *Button) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) {
|
||||
if !element.enabled { return }
|
||||
if !element.Enabled() { return }
|
||||
if key == tomo.KeyEnter {
|
||||
element.pressed = true
|
||||
if element.core.HasImage() {
|
||||
@ -86,61 +90,13 @@ func (element *Button) HandleKeyUp(key tomo.Key, modifiers tomo.Modifiers) {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
if !element.enabled { return }
|
||||
if !element.Enabled() { return }
|
||||
if element.onClick != nil {
|
||||
element.onClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Button) Selected () (selected bool) {
|
||||
return element.selected
|
||||
}
|
||||
|
||||
func (element *Button) Select () {
|
||||
if !element.enabled { return }
|
||||
if element.onSelectionRequest != nil {
|
||||
element.onSelectionRequest()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Button) HandleSelection (
|
||||
direction tomo.SelectionDirection,
|
||||
) (
|
||||
accepted bool,
|
||||
) {
|
||||
direction = direction.Canon()
|
||||
if !element.enabled { return false }
|
||||
if element.selected && direction != tomo.SelectionDirectionNeutral {
|
||||
return false
|
||||
}
|
||||
|
||||
element.selected = true
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (element *Button) HandleDeselection () {
|
||||
element.selected = false
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Button) OnSelectionRequest (callback func () (granted bool)) {
|
||||
element.onSelectionRequest = callback
|
||||
}
|
||||
|
||||
func (element *Button) OnSelectionMotionRequest (
|
||||
callback func (direction tomo.SelectionDirection) (granted bool),
|
||||
) {
|
||||
element.onSelectionMotionRequest = callback
|
||||
}
|
||||
|
||||
// OnClick sets the function to be called when the button is clicked.
|
||||
func (element *Button) OnClick (callback func ()) {
|
||||
element.onClick = callback
|
||||
@ -148,12 +104,7 @@ func (element *Button) OnClick (callback func ()) {
|
||||
|
||||
// SetEnabled sets whether this button can be clicked or not.
|
||||
func (element *Button) SetEnabled (enabled bool) {
|
||||
if element.enabled == enabled { return }
|
||||
element.enabled = enabled
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
element.selectableControl.SetEnabled(enabled)
|
||||
}
|
||||
|
||||
// SetText sets the button's label text.
|
||||
@ -178,7 +129,7 @@ func (element *Button) draw () {
|
||||
artist.FillRectangle (
|
||||
element.core,
|
||||
theme.ButtonPattern (
|
||||
element.enabled,
|
||||
element.Enabled(),
|
||||
element.Selected(),
|
||||
element.pressed),
|
||||
bounds)
|
||||
@ -204,6 +155,6 @@ func (element *Button) draw () {
|
||||
offset = offset.Add(theme.SinkOffsetVector())
|
||||
}
|
||||
|
||||
foreground := theme.ForegroundPattern(element.enabled)
|
||||
foreground := theme.ForegroundPattern(element.Enabled())
|
||||
element.drawer.Draw(element.core, foreground, offset)
|
||||
}
|
||||
|
@ -9,25 +9,29 @@ import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||
// Checkbox is a toggle-able checkbox with a label.
|
||||
type Checkbox struct {
|
||||
*core.Core
|
||||
*core.SelectableCore
|
||||
core core.CoreControl
|
||||
|
||||
pressed bool
|
||||
checked bool
|
||||
enabled bool
|
||||
selected bool
|
||||
|
||||
text string
|
||||
selectableControl core.SelectableCoreControl
|
||||
drawer artist.TextDrawer
|
||||
|
||||
pressed bool
|
||||
checked bool
|
||||
text string
|
||||
|
||||
onClick func ()
|
||||
onSelectionRequest func () (granted bool)
|
||||
onSelectionMotionRequest func (tomo.SelectionDirection) (granted bool)
|
||||
onToggle func ()
|
||||
}
|
||||
|
||||
// NewCheckbox creates a new cbeckbox with the specified label text.
|
||||
func NewCheckbox (text string, checked bool) (element *Checkbox) {
|
||||
element = &Checkbox { enabled: true, checked: checked }
|
||||
element = &Checkbox { checked: checked }
|
||||
element.Core, element.core = core.NewCore(element)
|
||||
element.SelectableCore,
|
||||
element.selectableControl = core.NewSelectableCore (func () {
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
})
|
||||
element.drawer.SetFace(theme.FontFaceRegular())
|
||||
element.SetText(text)
|
||||
return
|
||||
@ -40,6 +44,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.pressed = true
|
||||
if element.core.HasImage() {
|
||||
@ -49,7 +54,7 @@ func (element *Checkbox) HandleMouseDown (x, y int, button tomo.Button) {
|
||||
}
|
||||
|
||||
func (element *Checkbox) HandleMouseUp (x, y int, button tomo.Button) {
|
||||
if button != tomo.ButtonLeft { return }
|
||||
if button != tomo.ButtonLeft || !element.pressed { return }
|
||||
|
||||
element.pressed = false
|
||||
within := image.Point { x, y }.
|
||||
@ -62,8 +67,8 @@ func (element *Checkbox) HandleMouseUp (x, y int, button tomo.Button) {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
if within && element.onClick != nil {
|
||||
element.onClick()
|
||||
if within && element.onToggle != nil {
|
||||
element.onToggle()
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,65 +93,15 @@ func (element *Checkbox) HandleKeyUp (key tomo.Key, modifiers tomo.Modifiers) {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
if element.onClick != nil {
|
||||
element.onClick()
|
||||
if element.onToggle != nil {
|
||||
element.onToggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Selected returns whether or not this element is selected.
|
||||
func (element *Checkbox) Selected () (selected bool) {
|
||||
return element.selected
|
||||
}
|
||||
|
||||
// Select requests that this element be selected.
|
||||
func (element *Checkbox) Select () {
|
||||
if !element.enabled { return }
|
||||
if element.onSelectionRequest != nil {
|
||||
element.onSelectionRequest()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Checkbox) HandleSelection (
|
||||
direction tomo.SelectionDirection,
|
||||
) (
|
||||
accepted bool,
|
||||
) {
|
||||
direction = direction.Canon()
|
||||
if !element.enabled { return false }
|
||||
if element.selected && direction != tomo.SelectionDirectionNeutral {
|
||||
return false
|
||||
}
|
||||
|
||||
element.selected = true
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (element *Checkbox) HandleDeselection () {
|
||||
element.selected = false
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Checkbox) OnSelectionRequest (callback func () (granted bool)) {
|
||||
element.onSelectionRequest = callback
|
||||
}
|
||||
|
||||
func (element *Checkbox) OnSelectionMotionRequest (
|
||||
callback func (direction tomo.SelectionDirection) (granted bool),
|
||||
) {
|
||||
element.onSelectionMotionRequest = callback
|
||||
}
|
||||
|
||||
// OnClick sets the function to be called when the checkbox is toggled.
|
||||
func (element *Checkbox) OnClick (callback func ()) {
|
||||
element.onClick = callback
|
||||
// OnToggle sets the function to be called when the checkbox is toggled.
|
||||
func (element *Checkbox) OnToggle (callback func ()) {
|
||||
element.onToggle = callback
|
||||
}
|
||||
|
||||
// Value reports whether or not the checkbox is currently checked.
|
||||
@ -156,12 +111,7 @@ func (element *Checkbox) Value () (checked bool) {
|
||||
|
||||
// SetEnabled sets whether this checkbox can be toggled or not.
|
||||
func (element *Checkbox) SetEnabled (enabled bool) {
|
||||
if element.enabled == enabled { return }
|
||||
element.enabled = enabled
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
element.selectableControl.SetEnabled(enabled)
|
||||
}
|
||||
|
||||
// SetText sets the checkbox's label text.
|
||||
@ -171,9 +121,15 @@ func (element *Checkbox) SetText (text string) {
|
||||
element.text = text
|
||||
element.drawer.SetText([]rune(text))
|
||||
textBounds := element.drawer.LayoutBounds()
|
||||
element.core.SetMinimumSize (
|
||||
textBounds.Dy() + theme.Padding() + textBounds.Dx(),
|
||||
textBounds.Dy())
|
||||
|
||||
if text == "" {
|
||||
element.core.SetMinimumSize(textBounds.Dy(), textBounds.Dy())
|
||||
} else {
|
||||
element.core.SetMinimumSize (
|
||||
textBounds.Dy() + theme.Padding() + textBounds.Dx(),
|
||||
textBounds.Dy())
|
||||
}
|
||||
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
@ -188,16 +144,10 @@ func (element *Checkbox) draw () {
|
||||
artist.FillRectangle (
|
||||
element.core,
|
||||
theme.ButtonPattern (
|
||||
element.enabled,
|
||||
element.Enabled(),
|
||||
element.Selected(),
|
||||
element.pressed),
|
||||
boxBounds)
|
||||
|
||||
innerBounds := bounds
|
||||
innerBounds.Min.X += theme.Padding()
|
||||
innerBounds.Min.Y += theme.Padding()
|
||||
innerBounds.Max.X -= theme.Padding()
|
||||
innerBounds.Max.Y -= theme.Padding()
|
||||
|
||||
textBounds := element.drawer.LayoutBounds()
|
||||
offset := image.Point {
|
||||
@ -207,7 +157,7 @@ func (element *Checkbox) draw () {
|
||||
offset.Y -= textBounds.Min.Y
|
||||
offset.X -= textBounds.Min.X
|
||||
|
||||
foreground := theme.ForegroundPattern(element.enabled)
|
||||
foreground := theme.ForegroundPattern(element.Enabled())
|
||||
element.drawer.Draw(element.core, foreground, offset)
|
||||
|
||||
if element.checked {
|
||||
@ -217,7 +167,7 @@ func (element *Checkbox) draw () {
|
||||
}
|
||||
artist.FillRectangle (
|
||||
element.core,
|
||||
theme.ForegroundPattern(element.enabled),
|
||||
theme.ForegroundPattern(element.Enabled()),
|
||||
checkBounds)
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,10 @@ import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||
// List is an element that contains several objects that a user can select.
|
||||
type List struct {
|
||||
*core.Core
|
||||
*core.SelectableCore
|
||||
core core.CoreControl
|
||||
|
||||
enabled bool
|
||||
selected bool
|
||||
selectableControl core.SelectableCoreControl
|
||||
|
||||
pressed bool
|
||||
|
||||
contentHeight int
|
||||
@ -24,16 +24,21 @@ type List struct {
|
||||
scroll int
|
||||
entries []ListEntry
|
||||
|
||||
onSelectionRequest func () (granted bool)
|
||||
onSelectionMotionRequest func (tomo.SelectionDirection) (granted bool)
|
||||
onScrollBoundsChange func ()
|
||||
onNoEntrySelected func ()
|
||||
}
|
||||
|
||||
// NewList creates a new list element with the specified entries.
|
||||
func NewList (entries ...ListEntry) (element *List) {
|
||||
element = &List { enabled: true, selectedEntry: -1 }
|
||||
element = &List { selectedEntry: -1 }
|
||||
element.Core, element.core = core.NewCore(element)
|
||||
element.SelectableCore,
|
||||
element.selectableControl = core.NewSelectableCore (func () {
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
})
|
||||
|
||||
element.entries = make([]ListEntry, len(entries))
|
||||
for index, entry := range entries {
|
||||
@ -70,8 +75,8 @@ 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.Enabled() { return }
|
||||
if !element.Selected() { element.Select() }
|
||||
if button != tomo.ButtonLeft { return }
|
||||
element.pressed = true
|
||||
if element.selectUnderMouse(x, y) && element.core.HasImage() {
|
||||
@ -97,7 +102,7 @@ func (element *List) HandleMouseMove (x, y int) {
|
||||
func (element *List) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
|
||||
|
||||
func (element *List) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) {
|
||||
if !element.enabled { return }
|
||||
if !element.Enabled() { return }
|
||||
|
||||
altered := false
|
||||
switch key {
|
||||
@ -119,54 +124,6 @@ func (element *List) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) {
|
||||
|
||||
func (element *List) HandleKeyUp(key tomo.Key, modifiers tomo.Modifiers) { }
|
||||
|
||||
func (element *List) Selected () (selected bool) {
|
||||
return element.selected
|
||||
}
|
||||
|
||||
func (element *List) Select () {
|
||||
if !element.enabled { return }
|
||||
if element.onSelectionRequest != nil {
|
||||
element.onSelectionRequest()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *List) HandleSelection (
|
||||
direction tomo.SelectionDirection,
|
||||
) (
|
||||
accepted bool,
|
||||
) {
|
||||
direction = direction.Canon()
|
||||
if !element.enabled { return false }
|
||||
if element.selected && direction != tomo.SelectionDirectionNeutral {
|
||||
return false
|
||||
}
|
||||
|
||||
element.selected = true
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (element *List) HandleDeselection () {
|
||||
element.selected = false
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *List) OnSelectionRequest (callback func () (granted bool)) {
|
||||
element.onSelectionRequest = callback
|
||||
}
|
||||
|
||||
func (element *List) OnSelectionMotionRequest (
|
||||
callback func (direction tomo.SelectionDirection) (granted bool),
|
||||
) {
|
||||
element.onSelectionMotionRequest = callback
|
||||
}
|
||||
|
||||
// ScrollContentBounds returns the full content size of the element.
|
||||
func (element *List) ScrollContentBounds () (bounds image.Rectangle) {
|
||||
return image.Rect (
|
||||
@ -222,16 +179,6 @@ func (element *List) OnScrollBoundsChange (callback func ()) {
|
||||
element.onScrollBoundsChange = callback
|
||||
}
|
||||
|
||||
// SetEnabled sets whether this list can be interacted with or not.
|
||||
func (element *List) SetEnabled (enabled bool) {
|
||||
if element.enabled == enabled { return }
|
||||
element.enabled = enabled
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
// OnNoEntrySelected sets a function to be called when the user chooses to
|
||||
// deselect the current selected entry by clicking on empty space within the
|
||||
// list or by pressing the escape key.
|
||||
@ -416,7 +363,7 @@ func (element *List) draw () {
|
||||
|
||||
artist.FillRectangle (
|
||||
element,
|
||||
theme.ListPattern(element.selected),
|
||||
theme.ListPattern(element.Selected()),
|
||||
bounds)
|
||||
|
||||
dot := image.Point {
|
||||
@ -437,6 +384,6 @@ func (element *List) draw () {
|
||||
}
|
||||
entry.Draw (
|
||||
element, entryPosition,
|
||||
element.selectedEntry == index && element.selected)
|
||||
element.selectedEntry == index && element.Selected())
|
||||
}
|
||||
}
|
||||
|
1
elements/basic/switch.go
Normal file
1
elements/basic/switch.go
Normal file
@ -0,0 +1 @@
|
||||
package basic
|
@ -10,11 +10,10 @@ import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||
// TextBox is a single-line text input.
|
||||
type TextBox struct {
|
||||
*core.Core
|
||||
*core.SelectableCore
|
||||
core core.CoreControl
|
||||
selectableControl core.SelectableCoreControl
|
||||
|
||||
enabled bool
|
||||
selected bool
|
||||
|
||||
cursor int
|
||||
scroll int
|
||||
placeholder string
|
||||
@ -25,8 +24,6 @@ type TextBox struct {
|
||||
|
||||
onKeyDown func (key tomo.Key, modifiers tomo.Modifiers) (handled bool)
|
||||
onChange func ()
|
||||
onSelectionRequest func () (granted bool)
|
||||
onSelectionMotionRequest func (tomo.SelectionDirection) (granted bool)
|
||||
onScrollBoundsChange func ()
|
||||
}
|
||||
|
||||
@ -34,8 +31,15 @@ type TextBox struct {
|
||||
// a value. When the value is empty, the placeholder will be displayed in gray
|
||||
// text.
|
||||
func NewTextBox (placeholder, value string) (element *TextBox) {
|
||||
element = &TextBox { enabled: true }
|
||||
element = &TextBox { }
|
||||
element.Core, element.core = core.NewCore(element)
|
||||
element.SelectableCore,
|
||||
element.selectableControl = core.NewSelectableCore (func () {
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
})
|
||||
element.placeholderDrawer.SetFace(theme.FontFaceRegular())
|
||||
element.valueDrawer.SetFace(theme.FontFaceRegular())
|
||||
element.placeholder = placeholder
|
||||
@ -55,8 +59,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.Selected() { element.Select() }
|
||||
}
|
||||
|
||||
func (element *TextBox) HandleMouseUp (x, y int, button tomo.Button) { }
|
||||
@ -133,62 +137,6 @@ func (element *TextBox) HandleKeyDown(key tomo.Key, modifiers tomo.Modifiers) {
|
||||
|
||||
func (element *TextBox) HandleKeyUp(key tomo.Key, modifiers tomo.Modifiers) { }
|
||||
|
||||
func (element *TextBox) Selected () (selected bool) {
|
||||
return element.selected
|
||||
}
|
||||
|
||||
func (element *TextBox) Select () {
|
||||
if element.onSelectionRequest != nil {
|
||||
element.onSelectionRequest()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *TextBox) HandleSelection (
|
||||
direction tomo.SelectionDirection,
|
||||
) (
|
||||
accepted bool,
|
||||
) {
|
||||
direction = direction.Canon()
|
||||
if !element.enabled { return false }
|
||||
if element.selected && direction != tomo.SelectionDirectionNeutral {
|
||||
return false
|
||||
}
|
||||
|
||||
element.selected = true
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (element *TextBox) HandleDeselection () {
|
||||
element.selected = false
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *TextBox) OnSelectionRequest (callback func () (granted bool)) {
|
||||
element.onSelectionRequest = callback
|
||||
}
|
||||
|
||||
func (element *TextBox) OnSelectionMotionRequest (
|
||||
callback func (direction tomo.SelectionDirection) (granted bool),
|
||||
) {
|
||||
element.onSelectionMotionRequest = callback
|
||||
}
|
||||
|
||||
func (element *TextBox) SetEnabled (enabled bool) {
|
||||
if element.enabled == enabled { return }
|
||||
element.enabled = enabled
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *TextBox) SetPlaceholder (placeholder string) {
|
||||
if element.placeholder == placeholder { return }
|
||||
|
||||
@ -325,11 +273,11 @@ func (element *TextBox) draw () {
|
||||
artist.FillRectangle (
|
||||
element.core,
|
||||
theme.InputPattern (
|
||||
element.enabled,
|
||||
element.Enabled(),
|
||||
element.Selected()),
|
||||
bounds)
|
||||
|
||||
if len(element.text) == 0 && !element.selected {
|
||||
if len(element.text) == 0 && !element.Selected() {
|
||||
// draw placeholder
|
||||
textBounds := element.placeholderDrawer.LayoutBounds()
|
||||
offset := image.Point {
|
||||
@ -348,13 +296,13 @@ func (element *TextBox) draw () {
|
||||
X: theme.Padding() - element.scroll,
|
||||
Y: theme.Padding(),
|
||||
}
|
||||
foreground := theme.ForegroundPattern(element.enabled)
|
||||
foreground := theme.ForegroundPattern(element.Enabled())
|
||||
element.valueDrawer.Draw (
|
||||
element.core,
|
||||
foreground,
|
||||
offset.Sub(textBounds.Min))
|
||||
|
||||
if element.selected {
|
||||
if element.Selected() {
|
||||
// cursor
|
||||
cursorPosition := element.valueDrawer.PositionOf (
|
||||
element.cursor)
|
||||
|
111
elements/core/selectable.go
Normal file
111
elements/core/selectable.go
Normal file
@ -0,0 +1,111 @@
|
||||
package core
|
||||
|
||||
import "git.tebibyte.media/sashakoshka/tomo"
|
||||
|
||||
// SelectableCore is a struct that can be embedded into objects to make them
|
||||
// selectable, giving them the default selectability behavior.
|
||||
type SelectableCore struct {
|
||||
selected bool
|
||||
enabled bool
|
||||
drawSelectionChange func ()
|
||||
onSelectionRequest func () (granted bool)
|
||||
onSelectionMotionRequest func(tomo.SelectionDirection) (granted bool)
|
||||
}
|
||||
|
||||
// NewSelectableCore creates a new selectability core and its corresponding
|
||||
// control. If your element needs to visually update itself when it's selection
|
||||
// state changes (which it should), a callback to draw and push the update can
|
||||
// be specified.
|
||||
func NewSelectableCore (
|
||||
drawSelectionChange func (),
|
||||
) (
|
||||
core *SelectableCore,
|
||||
control SelectableCoreControl,
|
||||
) {
|
||||
core = &SelectableCore {
|
||||
drawSelectionChange: drawSelectionChange,
|
||||
enabled: true,
|
||||
}
|
||||
control = SelectableCoreControl { core: core }
|
||||
return
|
||||
}
|
||||
|
||||
// Selected returns whether or not this element is currently selected.
|
||||
func (core *SelectableCore) Selected () (selected bool) {
|
||||
return core.selected
|
||||
}
|
||||
|
||||
// Select selects this element, if its parent element grants the request.
|
||||
func (core *SelectableCore) Select () {
|
||||
if !core.enabled { return }
|
||||
if core.onSelectionRequest != nil {
|
||||
core.onSelectionRequest()
|
||||
}
|
||||
}
|
||||
|
||||
// HandleSelection causes this element to mark itself as selected, if it can
|
||||
// currently be. Otherwise, it will return false and do nothing.
|
||||
func (core *SelectableCore) HandleSelection (
|
||||
direction tomo.SelectionDirection,
|
||||
) (
|
||||
accepted bool,
|
||||
) {
|
||||
direction = direction.Canon()
|
||||
if !core.enabled { return false }
|
||||
if core.selected && direction != tomo.SelectionDirectionNeutral {
|
||||
return false
|
||||
}
|
||||
|
||||
core.selected = true
|
||||
if core.drawSelectionChange != nil { core.drawSelectionChange() }
|
||||
return true
|
||||
}
|
||||
|
||||
// HandleDeselection causes this element to mark itself as deselected.
|
||||
func (core *SelectableCore) HandleDeselection () {
|
||||
core.selected = false
|
||||
if core.drawSelectionChange != nil { core.drawSelectionChange() }
|
||||
}
|
||||
|
||||
// OnSelectionRequest sets a function to be called when this element
|
||||
// wants its parent element to select it. Parent elements should return
|
||||
// true if the request was granted, and false if it was not.
|
||||
func (core *SelectableCore) OnSelectionRequest (callback func () (granted bool)) {
|
||||
core.onSelectionRequest = callback
|
||||
}
|
||||
|
||||
// OnSelectionMotionRequest sets a function to be called when this
|
||||
// element wants its parent element to select the element behind or in
|
||||
// front of it, depending on the specified direction. Parent elements
|
||||
// should return true if the request was granted, and false if it was
|
||||
// not.
|
||||
func (core *SelectableCore) OnSelectionMotionRequest (
|
||||
callback func (direction tomo.SelectionDirection) (granted bool),
|
||||
) {
|
||||
core.onSelectionMotionRequest = callback
|
||||
}
|
||||
|
||||
// Enabled returns whether or not the element is enabled.
|
||||
func (core *SelectableCore) Enabled () (enabled bool) {
|
||||
return core.enabled
|
||||
}
|
||||
|
||||
// SelectableCoreControl is a struct that can be used to exert control over a
|
||||
// selectability core. It must not be directly embedded into an element, but
|
||||
// instead kept as a private member. When a SelectableCore struct is created, a
|
||||
// corresponding SelectableCoreControl struct is linked to it and returned
|
||||
// alongside it.
|
||||
type SelectableCoreControl struct {
|
||||
core *SelectableCore
|
||||
}
|
||||
|
||||
// SetEnabled sets whether the selectability core is enabled. If the state
|
||||
// changes, this will call drawSelectionChange.
|
||||
func (control SelectableCoreControl) SetEnabled (enabled bool) {
|
||||
if control.core.enabled == enabled { return }
|
||||
control.core.enabled = enabled
|
||||
if !enabled { control.core.selected = false }
|
||||
if control.core.drawSelectionChange != nil {
|
||||
control.core.drawSelectionChange()
|
||||
}
|
||||
}
|
@ -30,7 +30,7 @@ func run () {
|
||||
disabledCheckbox.SetEnabled(false)
|
||||
container.Adopt(disabledCheckbox, false)
|
||||
vsync := basic.NewCheckbox("Enable vsync", false)
|
||||
vsync.OnClick (func () {
|
||||
vsync.OnToggle (func () {
|
||||
if vsync.Value() {
|
||||
popups.NewDialog (
|
||||
popups.DialogKindInfo,
|
||||
|
Reference in New Issue
Block a user