Sasha Koshka
6ede0d0770
Parents are now able to draw backgrounds for their children. This means we can now have elements inside other elements that aren't restricted to one background color.
192 lines
4.9 KiB
Go
192 lines
4.9 KiB
Go
package elements
|
|
|
|
import "image"
|
|
import "git.tebibyte.media/sashakoshka/tomo"
|
|
import "git.tebibyte.media/sashakoshka/tomo/input"
|
|
import "git.tebibyte.media/sashakoshka/tomo/textdraw"
|
|
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
|
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
|
|
|
// Checkbox is a toggle-able checkbox with a label.
|
|
type Checkbox struct {
|
|
*core.Core
|
|
*core.FocusableCore
|
|
core core.CoreControl
|
|
focusableControl core.FocusableCoreControl
|
|
drawer textdraw.Drawer
|
|
|
|
pressed bool
|
|
checked bool
|
|
text string
|
|
|
|
config config.Wrapped
|
|
theme theme.Wrapped
|
|
|
|
onToggle func ()
|
|
}
|
|
|
|
// NewCheckbox creates a new cbeckbox with the specified label text.
|
|
func NewCheckbox (text string, checked bool) (element *Checkbox) {
|
|
element = &Checkbox { checked: checked }
|
|
element.theme.Case = tomo.C("tomo", "checkbox")
|
|
element.Core, element.core = core.NewCore(element, element.draw)
|
|
element.FocusableCore,
|
|
element.focusableControl = core.NewFocusableCore(element.core, element.redo)
|
|
element.drawer.SetFace (element.theme.FontFace (
|
|
tomo.FontStyleRegular,
|
|
tomo.FontSizeNormal))
|
|
element.SetText(text)
|
|
return
|
|
}
|
|
|
|
func (element *Checkbox) HandleMouseDown (x, y int, button input.Button) {
|
|
if !element.Enabled() { return }
|
|
element.Focus()
|
|
element.pressed = true
|
|
if element.core.HasImage() {
|
|
element.draw()
|
|
element.core.DamageAll()
|
|
}
|
|
}
|
|
|
|
func (element *Checkbox) HandleMouseUp (x, y int, button input.Button) {
|
|
if button != input.ButtonLeft || !element.pressed { return }
|
|
|
|
element.pressed = false
|
|
within := image.Point { x, y }.
|
|
In(element.Bounds())
|
|
if within {
|
|
element.checked = !element.checked
|
|
}
|
|
|
|
if element.core.HasImage() {
|
|
element.draw()
|
|
element.core.DamageAll()
|
|
}
|
|
if within && element.onToggle != nil {
|
|
element.onToggle()
|
|
}
|
|
}
|
|
|
|
func (element *Checkbox) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
|
|
if key == input.KeyEnter {
|
|
element.pressed = true
|
|
if element.core.HasImage() {
|
|
element.draw()
|
|
element.core.DamageAll()
|
|
}
|
|
}
|
|
}
|
|
|
|
func (element *Checkbox) HandleKeyUp (key input.Key, modifiers input.Modifiers) {
|
|
if key == input.KeyEnter && element.pressed {
|
|
element.pressed = false
|
|
element.checked = !element.checked
|
|
if element.core.HasImage() {
|
|
element.draw()
|
|
element.core.DamageAll()
|
|
}
|
|
if element.onToggle != nil {
|
|
element.onToggle()
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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.
|
|
func (element *Checkbox) Value () (checked bool) {
|
|
return element.checked
|
|
}
|
|
|
|
// SetEnabled sets whether this checkbox can be toggled or not.
|
|
func (element *Checkbox) SetEnabled (enabled bool) {
|
|
element.focusableControl.SetEnabled(enabled)
|
|
}
|
|
|
|
// SetText sets the checkbox's label text.
|
|
func (element *Checkbox) SetText (text string) {
|
|
if element.text == text { return }
|
|
|
|
element.text = text
|
|
element.drawer.SetText([]rune(text))
|
|
element.updateMinimumSize()
|
|
|
|
if element.core.HasImage () {
|
|
element.draw()
|
|
element.core.DamageAll()
|
|
}
|
|
}
|
|
|
|
// SetTheme sets the element's theme.
|
|
func (element *Checkbox) SetTheme (new tomo.Theme) {
|
|
if new == element.theme.Theme { return }
|
|
element.theme.Theme = new
|
|
element.drawer.SetFace (element.theme.FontFace (
|
|
tomo.FontStyleRegular,
|
|
tomo.FontSizeNormal))
|
|
element.updateMinimumSize()
|
|
element.redo()
|
|
}
|
|
|
|
// SetConfig sets the element's configuration.
|
|
func (element *Checkbox) SetConfig (new tomo.Config) {
|
|
if new == element.config.Config { return }
|
|
element.config.Config = new
|
|
element.updateMinimumSize()
|
|
element.redo()
|
|
}
|
|
|
|
func (element *Checkbox) updateMinimumSize () {
|
|
textBounds := element.drawer.LayoutBounds()
|
|
if element.text == "" {
|
|
element.core.SetMinimumSize(textBounds.Dy(), textBounds.Dy())
|
|
} else {
|
|
margin := element.theme.Margin(tomo.PatternBackground)
|
|
element.core.SetMinimumSize (
|
|
textBounds.Dy() + margin.X + textBounds.Dx(),
|
|
textBounds.Dy())
|
|
}
|
|
}
|
|
|
|
func (element *Checkbox) redo () {
|
|
if element.core.HasImage () {
|
|
element.draw()
|
|
element.core.DamageAll()
|
|
}
|
|
}
|
|
|
|
func (element *Checkbox) draw () {
|
|
bounds := element.Bounds()
|
|
boxBounds := image.Rect(0, 0, bounds.Dy(), bounds.Dy()).Add(bounds.Min)
|
|
|
|
state := tomo.State {
|
|
Disabled: !element.Enabled(),
|
|
Focused: element.Focused(),
|
|
Pressed: element.pressed,
|
|
On: element.checked,
|
|
}
|
|
|
|
element.core.DrawBackground (
|
|
element.theme.Pattern(tomo.PatternBackground, state))
|
|
|
|
pattern := element.theme.Pattern(tomo.PatternButton, state)
|
|
pattern.Draw(element.core, boxBounds)
|
|
|
|
textBounds := element.drawer.LayoutBounds()
|
|
margin := element.theme.Margin(tomo.PatternBackground)
|
|
offset := bounds.Min.Add(image.Point {
|
|
X: bounds.Dy() + margin.X,
|
|
})
|
|
|
|
offset.Y -= textBounds.Min.Y
|
|
offset.X -= textBounds.Min.X
|
|
|
|
foreground := element.theme.Color(tomo.ColorForeground, state)
|
|
element.drawer.Draw(element.core, foreground, offset)
|
|
}
|