package basicElements import "image" import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/textdraw" import "git.tebibyte.media/sashakoshka/tomo/elements/core" // 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 = theme.C("basic", "checkbox") element.Core, element.core = core.NewCore(element, element.draw) element.FocusableCore, element.focusableControl = core.NewFocusableCore(element.core, element.redo) 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 theme.Theme) { if new == element.theme.Theme { return } element.theme.Theme = new element.drawer.SetFace (element.theme.FontFace ( theme.FontStyleRegular, theme.FontSizeNormal)) element.updateMinimumSize() element.redo() } // SetConfig sets the element's configuration. func (element *Checkbox) SetConfig (new config.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(theme.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 := theme.State { Disabled: !element.Enabled(), Focused: element.Focused(), Pressed: element.pressed, On: element.checked, } backgroundPattern := element.theme.Pattern ( theme.PatternBackground, state) backgroundPattern.Draw(element.core, bounds) pattern := element.theme.Pattern(theme.PatternButton, state) pattern.Draw(element.core, boxBounds) textBounds := element.drawer.LayoutBounds() margin := element.theme.Margin(theme.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(theme.ColorForeground, state) element.drawer.Draw(element.core, foreground, offset) }