package objects // import "image" 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" // Dropdown is a non-editable text input that allows the user to pick a value // from a list. type Dropdown struct { tomo.ContainerBox label *Label value string items []string menu *Menu on struct { valueChange event.FuncBroadcaster } } // NewDropdown creates a new dropdown input with the specified items func NewDropdown (items ...string) *Dropdown { dropdown := &Dropdown { ContainerBox: tomo.NewContainerBox(), label: NewLabel(""), } dropdown.SetRole(tomo.R("objects", "Dropdown")) dropdown.SetAttr(tomo.ALayout(layouts.Row { true, false })) dropdown.Add(dropdown.label) // TODO: replace IconValueDecrement with a drop-down expand icon once // we get that dropdown.Add(NewIcon(tomo.IconValueDecrement, tomo.IconSizeSmall)) dropdown.SetItems(items...) if len(items) > 0 { dropdown.SetValue(items[0]) } dropdown.SetInputMask(true) dropdown.OnButtonDown(dropdown.handleButtonDown) dropdown.OnButtonUp(dropdown.handleButtonUp) dropdown.OnKeyDown(dropdown.handleKeyDown) dropdown.OnKeyUp(dropdown.handleKeyUp) dropdown.SetFocusable(true) return dropdown } // Value returns the value of the dropdown. This does not necissarily have to be // in the list of items. func (this *Dropdown) Value () string { return this.value } // SetValue sets the value of the dropdown. This does not necissarily have to be // in the list of items. func (this *Dropdown) SetValue (value string) { this.value = value this.label.SetText(value) } // SetItems sets the items from which the user is able to pick. func (this *Dropdown) SetItems (items ...string) { this.items = items } func (this *Dropdown) itemList () []tomo.Object { items := make([]tomo.Object, len(this.items)) for index, value := range this.items { value := value item := NewMenuItem(value) item.OnClick(func () { this.SetValue(value) this.on.valueChange.Broadcast() }) items[index] = item } return items } func (this *Dropdown) showMenu () { if this.menu != nil { this.menu.Close() } menu, err := NewAnchoredMenu(this, this.itemList()...) if err != nil { return } this.menu = menu menu.SetVisible(true) } func (this *Dropdown) handleKeyDown (key input.Key, numberPad bool) bool { if key != input.KeyEnter && key != input.Key(' ') { return false } this.showMenu() return true } func (this *Dropdown) handleKeyUp (key input.Key, numberPad bool) bool { if key != input.KeyEnter && key != input.Key(' ') { return false } return true } func (this *Dropdown) handleButtonDown (button input.Button) bool { if button != input.ButtonLeft { return false } return true } func (this *Dropdown) handleButtonUp (button input.Button) bool { if button != input.ButtonLeft { return false } if this.Window().MousePosition().In(this.Bounds()) { this.showMenu() } return true }