package objects import "git.tebibyte.media/tomo/tomo" import "git.tebibyte.media/tomo/tomo/input" import "git.tebibyte.media/tomo/tomo/event" import "git.tebibyte.media/tomo/objects/layouts" var _ tomo.Object = new(Button) var buttonLayout = layouts.Row { true } var iconButtonLayout = layouts.Row { true } var bothButtonLayout = layouts.Row { false, true } // Button is a clickable button. // // Tags: // - [icon] The button has an icon. type Button struct { box tomo.ContainerBox label *Label icon *Icon labelActive bool on struct { click event.FuncBroadcaster } } // NewButton creates a new button with the specified text. func NewButton (text string) *Button { button := &Button { box: tomo.NewContainerBox(), label: NewLabel(text), } button.box.SetRole(tomo.R("objects", "Button")) button.label.SetAlign(tomo.AlignMiddle, tomo.AlignMiddle) button.box.SetAttr(tomo.ALayout(buttonLayout)) button.SetText(text) button.box.SetInputMask(true) button.box.OnButtonDown(button.handleButtonDown) button.box.OnButtonUp(button.handleButtonUp) button.box.OnKeyDown(button.handleKeyDown) button.box.OnKeyUp(button.handleKeyUp) button.box.SetFocusable(true) return button } // GetBox returns the underlying box. func (this *Button) GetBox () tomo.Box { return this.box } // SetFocused sets whether or not this button has keyboard focus. If set to // true, this method will steal focus away from whichever object currently has // focus. func (this *Button) SetFocused (focused bool) { this.box.SetFocused(focused) } // SetText sets the text of the button's label. func (this *Button) SetText (text string) { this.label.SetText(text) if this.labelActive && text == "" { this.box.Remove(this.label) this.labelActive = false } if !this.labelActive && text != "" { this.box.Add(this.label) this.labelActive = true } this.applyLayout() } // SetIcon sets an icon for this button. Setting the icon to IconUnknown will // remove it. func (this *Button) SetIcon (id tomo.Icon) { if this.icon != nil { this.box.Remove(this.icon) } var icon *Icon; if id != tomo.IconUnknown { icon = NewIcon(id, tomo.IconSizeSmall) } this.icon = icon if this.icon != nil { this.box.Insert(this.icon, this.label) } this.box.SetTag("icon", this.icon != nil) this.applyLayout() } // OnClick specifies a function to be called when the button is clicked. func (this *Button) OnClick (callback func ()) event.Cookie { return this.on.click.Connect(callback) } func (this *Button) applyLayout () { if this.labelActive && this.icon == nil { this.box.SetAttr(tomo.ALayout(buttonLayout)) } else if !this.labelActive && this.icon != nil { this.box.SetAttr(tomo.ALayout(iconButtonLayout)) } else { this.box.SetAttr(tomo.ALayout(bothButtonLayout)) } } func (this *Button) handleKeyDown (key input.Key, numberPad bool) bool { if !isClickingKey(key) { return false } this.on.click.Broadcast() return true } func (this *Button) handleKeyUp (key input.Key, numberPad bool) bool { if !isClickingKey(key) { return false } return true } func (this *Button) handleButtonDown (button input.Button) bool { if !isClickingButton(button) { return false } return true } func (this *Button) handleButtonUp (button input.Button) bool { if !isClickingButton(button) { return false } if this.box.Window().MousePosition().In(this.box.Bounds()) { this.on.click.Broadcast() } return true }