Skip to content

Commit

Permalink
New ContextMenu API + example
Browse files Browse the repository at this point in the history
  • Loading branch information
leaanthony committed Jan 15, 2025
1 parent 51e3a61 commit 480febc
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 38 deletions.
16 changes: 7 additions & 9 deletions v3/examples/contextmenus/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func main() {
},
})

mainWindow := app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
Title: "Context Menu Demo",
Width: 1024,
Height: 1024,
Expand All @@ -35,22 +35,20 @@ func main() {
},
})

contextMenu := app.NewMenu()
contextMenu.Add("Click Me").OnClick(func(data *application.Context) {
contextMenu := application.NewContextMenu("test")
clickMe := contextMenu.Add("Click Me")
contextDataMenuItem := contextMenu.Add("No Context Data")
clickMe.OnClick(func(data *application.Context) {
app.Logger.Info("Context menu", "context data", data.ContextMenuData())
contextDataMenuItem.SetLabel("My context data: " + data.ContextMenuData().(string))
contextMenu.Update()
})

globalContextMenu := app.NewMenu()
globalContextMenu.Add("Default context menu item").OnClick(func(data *application.Context) {
app.Logger.Info("Context menu", "context data", data.ContextMenuData())
})

// Registering the menu with a window will make it available to that window only
mainWindow.RegisterContextMenu("test", contextMenu)

// Registering the menu with the app will make it available to all windows
app.RegisterContextMenu("test", globalContextMenu)

err := app.Run()

if err != nil {
Expand Down
16 changes: 11 additions & 5 deletions v3/pkg/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ type App struct {
customEventProcessor *EventProcessor
Logger *slog.Logger

contextMenus map[string]*Menu
contextMenus map[string]*ContextMenu
contextMenusLock sync.Mutex

assets *assetserver.AssetServer
Expand Down Expand Up @@ -447,7 +447,7 @@ func (a *App) init() {
a.applicationEventListeners = make(map[uint][]*EventListener)
a.windows = make(map[uint]Window)
a.systemTrays = make(map[uint]*SystemTray)
a.contextMenus = make(map[string]*Menu)
a.contextMenus = make(map[string]*ContextMenu)
a.keyBindings = make(map[string]func(window *WebviewWindow))
a.Logger = a.options.Logger
a.pid = os.Getpid()
Expand Down Expand Up @@ -947,13 +947,19 @@ func (a *App) Show() {
}
}

func (a *App) RegisterContextMenu(name string, menu *Menu) {
func (a *App) registerContextMenu(menu *ContextMenu) {
a.contextMenusLock.Lock()
defer a.contextMenusLock.Unlock()
a.contextMenus[name] = menu
a.contextMenus[menu.name] = menu
}

func (a *App) getContextMenu(name string) (*Menu, bool) {
func (a *App) unregisterContextMenu(name string) {
a.contextMenusLock.Lock()
defer a.contextMenusLock.Unlock()
delete(a.contextMenus, name)
}

func (a *App) getContextMenu(name string) (*ContextMenu, bool) {
a.contextMenusLock.Lock()
defer a.contextMenusLock.Unlock()
menu, ok := a.contextMenus[name]
Expand Down
23 changes: 23 additions & 0 deletions v3/pkg/application/menu.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,29 @@ type menuImpl interface {
update()
}

type ContextMenu struct {
*Menu
name string
}

func NewContextMenu(name string) *ContextMenu {
result := &ContextMenu{
Menu: NewMenu(),
name: name,
}
result.Update()
return result
}

func (m *ContextMenu) Update() {
m.Menu.Update()
globalApplication.registerContextMenu(m)
}

func (m *ContextMenu) Destroy() {
globalApplication.unregisterContextMenu(m.name)
}

type Menu struct {
items []*MenuItem
label string
Expand Down
28 changes: 5 additions & 23 deletions v3/pkg/application/webview_window.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,6 @@ type WebviewWindow struct {
eventHooks map[uint][]*WindowEventListener
eventHooksLock sync.RWMutex

contextMenus map[string]*Menu
contextMenusLock sync.RWMutex

// A map of listener cancellation functions
cancellersLock sync.RWMutex
cancellers []func()
Expand Down Expand Up @@ -247,7 +244,6 @@ func NewWindow(options WebviewWindowOptions) *WebviewWindow {
id: thisWindowID,
options: options,
eventListeners: make(map[uint][]*WindowEventListener),
contextMenus: make(map[string]*Menu),
eventHooks: make(map[uint][]*WindowEventListener),
menuBindings: make(map[string]*MenuItem),
}
Expand Down Expand Up @@ -1173,35 +1169,21 @@ func (w *WebviewWindow) HandleDragAndDropMessage(filenames []string) {
}

func (w *WebviewWindow) OpenContextMenu(data *ContextMenuData) {
menu, ok := w.contextMenus[data.Id]
// try application level context menu
menu, ok := globalApplication.getContextMenu(data.Id)
if !ok {
// try application level context menu
menu, ok = globalApplication.getContextMenu(data.Id)
if !ok {
w.Error("No context menu found for id: %s", data.Id)
return
}
w.Error("No context menu found for id: %s", data.Id)
return
}
menu.setContextData(data)
if w.impl == nil || w.isDestroyed() {
return
}
InvokeSync(func() {
w.impl.openContextMenu(menu, data)
w.impl.openContextMenu(menu.Menu, data)
})
}

// RegisterContextMenu registers a context menu and assigns it the given name.
func (w *WebviewWindow) RegisterContextMenu(name string, menu *Menu) {
if menu == nil {
w.Error("RegisterContextMenu called with nil menu")
return
}
w.contextMenusLock.Lock()
defer w.contextMenusLock.Unlock()
w.contextMenus[name] = menu
}

// NativeWindowHandle returns the platform native window handle for the window.
func (w *WebviewWindow) NativeWindowHandle() (uintptr, error) {
if w.impl == nil || w.isDestroyed() {
Expand Down
1 change: 0 additions & 1 deletion v3/pkg/application/window.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ type Window interface {
OnWindowEvent(eventType events.WindowEventType, callback func(event *WindowEvent)) func()
OpenContextMenu(data *ContextMenuData)
Position() (int, int)
RegisterContextMenu(name string, menu *Menu)
RelativePosition() (int, int)
Reload()
Resizable() bool
Expand Down

0 comments on commit 480febc

Please sign in to comment.