diff --git a/checkbox.go b/checkbox.go new file mode 100644 index 0000000..e25ed2a --- /dev/null +++ b/checkbox.go @@ -0,0 +1,69 @@ +package objects + +import "git.tebibyte.media/tomo/tomo" +import "git.tebibyte.media/tomo/tomo/theme" +import "git.tebibyte.media/tomo/tomo/input" +import "git.tebibyte.media/tomo/tomo/event" + +// Checkbox is a control that can be toggled. +type Checkbox struct { + tomo.Box + value bool + on struct { + valueChange event.FuncBroadcaster + } +} + +// NewCheckbox creates a new checkbox with the specified value. +func NewCheckbox (value bool) *Checkbox { + box := &Checkbox { + Box: tomo.NewBox(), + } + theme.Apply(box, theme.R("objects", "Checkbox", "")) + box.SetValue(false) + + box.OnMouseUp(box.handleMouseUp) + box.OnKeyUp(box.handleKeyUp) + box.SetFocusable(true) + return box +} + +// SetValue sets the value of the checkbox. +func (this *Checkbox) SetValue (value bool) { + this.value = value + if this.value { + // TODO perhaps have IconStatusOkay/Cancel in actions, and have + // a status icon for checked checkboxes. + this.SetTexture(theme.IconStatusOkay.Texture(theme.IconSizeSmall)) + } else { + this.SetTexture(nil) + } +} + +// Toggle toggles the value of the checkbox between true and false. +func (this *Checkbox) Toggle () { + this.SetValue(!this.Value()) +} + +// Value returns the value of the checkbox. +func (this *Checkbox) Value () bool { + return this.value +} + +// OnValueChange specifies a function to be called when the checkbox's value +// changes. +func (this *Checkbox) OnValueChange (callback func ()) event.Cookie { + return this.on.valueChange.Connect(callback) +} + +func (this *Checkbox) handleKeyUp (key input.Key, numberPad bool) { + if key != input.KeyEnter && key != input.Key(' ') { return } + this.Toggle() +} + +func (this *Checkbox) handleMouseUp (button input.Button) { + if button != input.ButtonLeft { return } + if this.MousePosition().In(this.Bounds()) { + this.Toggle() + } +} diff --git a/labelcheckbox.go b/labelcheckbox.go new file mode 100644 index 0000000..fe938b0 --- /dev/null +++ b/labelcheckbox.go @@ -0,0 +1,62 @@ +package objects + +import "git.tebibyte.media/tomo/tomo" +import "git.tebibyte.media/tomo/tomo/theme" +import "git.tebibyte.media/tomo/tomo/input" +import "git.tebibyte.media/tomo/tomo/event" +import "git.tebibyte.media/tomo/objects/layouts" + +// LabelCheckbox is a checkbox with a label. +type LabelCheckbox struct { + tomo.ContainerBox + checkbox *Checkbox + label *Label +} + +// NewLabelCheckbox creates a new labeled checkbox with the specified value and +// label text. +func NewLabelCheckbox (value bool, text string) *LabelCheckbox { + box := &LabelCheckbox { + ContainerBox: tomo.NewContainerBox(), + checkbox: NewCheckbox(value), + label: NewLabel(text), + } + theme.Apply(box, theme.R("objects", "LabelCheckbox", "")) + box.label.SetAlign(tomo.AlignStart, tomo.AlignMiddle) + box.Add(box.checkbox) + box.Add(box.label) + box.SetLayout(layouts.NewGrid([]bool { false, true }, []bool { true })) + + box.OnMouseUp(box.handleMouseUp) + box.label.OnMouseUp(box.handleMouseUp) + return box +} + +// SetValue sets the value of the checkbox. +func (this *LabelCheckbox) SetValue (value bool) { + this.checkbox.SetValue(value) +} + +// Toggle toggles the value of the checkbox between true and false. +func (this *LabelCheckbox) Toggle () { + this.checkbox.Toggle() +} + +// Value returns the value of the checkbox. +func (this *LabelCheckbox) Value () bool { + return this.checkbox.Value() +} + +// OnValueChange specifies a function to be called when the checkbox's value +// changes. +func (this *LabelCheckbox) OnValueChange (callback func ()) event.Cookie { + return this.checkbox.OnValueChange(callback) +} + +func (this *LabelCheckbox) handleMouseUp (button input.Button) { + if button != input.ButtonLeft { return } + if this.MousePosition().In(this.Bounds()) { + this.checkbox.SetFocused(true) + this.checkbox.Toggle() + } +}