From eb0bf589615fc1948914ac0ec69440f238104495 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Wed, 14 Aug 2024 11:44:47 -0400 Subject: [PATCH] Improvements to menus Major progress on #4 --- menu.go | 38 ++++++++++++++++++++++---------------- menuitem.go | 10 +++++++--- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/menu.go b/menu.go index 49528dc..620227e 100644 --- a/menu.go +++ b/menu.go @@ -18,23 +18,28 @@ type Menu struct { } // NewMenu creates a new menu with the specified items. The menu will appear -// directly under the anchor Object. If the anchor is nil, it will appear -// directly under the mouse pointer instead. -func NewMenu (anchor tomo.Object, items ...tomo.Object) (*Menu, error) { - menu := &Menu { } - if anchor == nil { - // TODO: *actually* put it under the mouse - window, err := tomo.NewWindow(menu.bounds) - if err != nil { return nil, err } - menu.Window = window - } else { - menu.bounds = menuBoundsFromAnchor(anchor) - menu.parent = anchor.GetBox().Window() - window, err := menu.parent.NewMenu(menu.bounds) - if err != nil { return nil, err } - menu.Window = window - } +// directly under the mouse pointer. +func NewMenu (parent tomo.Window, items ...tomo.Object) (*Menu, error) { + bounds := (image.Rectangle { }).Add(parent.MousePosition()) + return newMenu(parent, bounds, items...) +} +// NewAnchoredMenu creates a new menu with the specified items. The menu will +// appear directly under the anchor. +func NewAnchoredMenu (anchor tomo.Object, items ...tomo.Object) (*Menu, error) { + parent := anchor.GetBox().Window() + bounds := menuBoundsFromAnchor(anchor) + return newMenu(parent, bounds, items...) +} + +func newMenu (parent tomo.Window, bounds image.Rectangle, items ...tomo.Object) (*Menu, error) { + menu := &Menu { } + menu.bounds = bounds + menu.parent = parent + window, err := menu.parent.NewMenu(menu.bounds) + if err != nil { return nil, err } + menu.Window = window + menu.rootContainer = tomo.NewContainerBox() menu.rootContainer.SetAttr(tomo.ALayout(layouts.ContractVertical)) @@ -74,6 +79,7 @@ func (this *Menu) TearOff () { this.Window.Close() this.rootContainer.Remove(this.tearLine) + this.rootContainer.SetTag("torn", true) this.Window = window this.Window.SetRoot(this.rootContainer) diff --git a/menuitem.go b/menuitem.go index 7049093..6ab84bf 100644 --- a/menuitem.go +++ b/menuitem.go @@ -20,10 +20,15 @@ type MenuItem struct { // NewMenuItem creates a new menu item with the specified text. func NewMenuItem (text string) *MenuItem { + return NewIconMenuItem(tomo.IconUnknown, text) +} + +// NewIconMenuItem creates a new menu item with the specified icon and text. +func NewIconMenuItem (icon tomo.Icon, text string) *MenuItem { box := &MenuItem { ContainerBox: tomo.NewContainerBox(), label: NewLabel(text), - icon: NewIcon("", tomo.IconSizeSmall), + icon: NewIcon(icon, tomo.IconSizeSmall), } box.SetRole(tomo.R("objects", "MenuItem")) box.label.SetAttr(tomo.AAlign(tomo.AlignStart, tomo.AlignMiddle)) @@ -49,8 +54,7 @@ func (this *MenuItem) SetText (text string) { // SetIcon sets an icon for this item. Setting the icon to IconUnknown will // remove it. func (this *MenuItem) SetIcon (id tomo.Icon) { - if this.icon != nil { this.Remove(this.icon) } - this.Insert(NewIcon(id, tomo.IconSizeSmall), this.label) + this.icon.SetIcon(id, tomo.IconSizeSmall) } // OnClick specifies a function to be called when the menu item is clicked.