mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-04 01:19:12 +08:00
Merge pull request #4116 from IanVS/fix-hidden-menuitem
[V3] Fix initially-hidden menuItem [mac/win]
This commit is contained in:
commit
8abcd81f30
@ -75,6 +75,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Add method `Close` on `sqlite` service to close the DB manually by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067)
|
- Add method `Close` on `sqlite` service to close the DB manually by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067)
|
||||||
- Add cancellation support for query methods on `sqlite` service by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067)
|
- Add cancellation support for query methods on `sqlite` service by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067)
|
||||||
- Add prepared statement support to `sqlite` service with JS bindings by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067)
|
- Add prepared statement support to `sqlite` service with JS bindings by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067)
|
||||||
|
- Add `SetMenu()` on window to allow for setting a menu on a window by [@leaanthony](https://github.com/leaanthony)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
@ -107,6 +108,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Ensure menu updates occur on the main thread by [@leaanthony](https://github.com/leaanthony)
|
- Ensure menu updates occur on the main thread by [@leaanthony](https://github.com/leaanthony)
|
||||||
- The dragging and resizing mechanism is now more robust and matches expected platform behaviour more closely by [@fbbdev](https://github.com/fbbdev) in [#4100](https://github.com/wailsapp/wails/pull/4100)
|
- The dragging and resizing mechanism is now more robust and matches expected platform behaviour more closely by [@fbbdev](https://github.com/fbbdev) in [#4100](https://github.com/wailsapp/wails/pull/4100)
|
||||||
- Fixed [#4097](https://github.com/wailsapp/wails/issues/4097) Webpack/angular discards runtime init code by [@fbbdev](https://github.com/fbbdev) in [#4100](https://github.com/wailsapp/wails/pull/4100)
|
- Fixed [#4097](https://github.com/wailsapp/wails/issues/4097) Webpack/angular discards runtime init code by [@fbbdev](https://github.com/fbbdev) in [#4100](https://github.com/wailsapp/wails/pull/4100)
|
||||||
|
- Fixed initially-hidden menu items by [@IanVS](https://github.com/IanVS) in [#4116](https://github.com/wailsapp/wails/pull/4116)
|
||||||
- Fixed assetFileServer not serving `.html` files when non-extension request when `[request]` doesn't exist but `[request].html` does
|
- Fixed assetFileServer not serving `.html` files when non-extension request when `[request]` doesn't exist but `[request].html` does
|
||||||
- Fixed icon generation paths by [@robin-samuel](https://github.com/robin-samuel) in [#4125](https://github.com/wailsapp/wails/pull/4125)
|
- Fixed icon generation paths by [@robin-samuel](https://github.com/robin-samuel) in [#4125](https://github.com/wailsapp/wails/pull/4125)
|
||||||
|
|
||||||
|
@ -16,6 +16,43 @@ Create a new application menu using the `NewMenu` method:
|
|||||||
menu := app.NewMenu()
|
menu := app.NewMenu()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Setting the Menu
|
||||||
|
|
||||||
|
The way to set the menu varies on the platform:
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<TabItem label="macOS" icon="fa-brands:apple">
|
||||||
|
|
||||||
|
On macOS, there is only one menu bar per application. Set the menu using the `SetMenu` method of the application:
|
||||||
|
|
||||||
|
```go
|
||||||
|
app.SetMenu(menu)
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
<TabItem label="Windows" icon="fa-brands:windows">
|
||||||
|
|
||||||
|
On Windows, there is a menu bar per window. Set the menu using the `SetMenu` method of the window:
|
||||||
|
|
||||||
|
```go
|
||||||
|
window.SetMenu(menu)
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
<TabItem label="Linux" icon="fa-brands:linux">
|
||||||
|
|
||||||
|
On Linux, the menu bar is typically per window. Set the menu using the `SetMenu` method of the window:
|
||||||
|
|
||||||
|
```go
|
||||||
|
window.SetMenu(menu)
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
|
||||||
## Menu Roles
|
## Menu Roles
|
||||||
|
|
||||||
Wails provides predefined menu roles that automatically create platform-appropriate menu structures:
|
Wails provides predefined menu roles that automatically create platform-appropriate menu structures:
|
||||||
|
@ -27,16 +27,7 @@ func main() {
|
|||||||
if runtime.GOOS == "darwin" {
|
if runtime.GOOS == "darwin" {
|
||||||
menu.AddRole(application.AppMenu)
|
menu.AddRole(application.AppMenu)
|
||||||
}
|
}
|
||||||
fileMenu := menu.AddRole(application.FileMenu)
|
menu.AddRole(application.FileMenu)
|
||||||
_ = fileMenu
|
|
||||||
//fileMenu.FindByRole(application.Open).OnClick(func(context *application.Context) {
|
|
||||||
// selection, err := application.OpenFileDialog().PromptForSingleSelection()
|
|
||||||
// if err != nil {
|
|
||||||
// println("Error: " + err.Error())
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// println("You selected: " + selection)
|
|
||||||
//})
|
|
||||||
menu.AddRole(application.EditMenu)
|
menu.AddRole(application.EditMenu)
|
||||||
menu.AddRole(application.WindowMenu)
|
menu.AddRole(application.WindowMenu)
|
||||||
menu.AddRole(application.HelpMenu)
|
menu.AddRole(application.HelpMenu)
|
||||||
@ -44,6 +35,12 @@ func main() {
|
|||||||
// Let's make a "Demo" menu
|
// Let's make a "Demo" menu
|
||||||
myMenu := menu.AddSubmenu("Demo")
|
myMenu := menu.AddSubmenu("Demo")
|
||||||
|
|
||||||
|
// Hidden menu item that can be unhidden
|
||||||
|
hidden := myMenu.Add("I was hidden").SetHidden(true)
|
||||||
|
myMenu.Add("Toggle the hidden menu").OnClick(func(ctx *application.Context) {
|
||||||
|
hidden.SetHidden(!hidden.Hidden())
|
||||||
|
})
|
||||||
|
|
||||||
// Disabled menu item
|
// Disabled menu item
|
||||||
myMenu.Add("Not Enabled").SetEnabled(false)
|
myMenu.Add("Not Enabled").SetEnabled(false)
|
||||||
|
|
||||||
@ -118,7 +115,8 @@ func main() {
|
|||||||
})
|
})
|
||||||
app.SetMenu(menu)
|
app.SetMenu(menu)
|
||||||
|
|
||||||
app.NewWebviewWindow().SetBackgroundColour(application.NewRGB(33, 37, 41))
|
window := app.NewWebviewWindow().SetBackgroundColour(application.NewRGB(33, 37, 41))
|
||||||
|
window.SetMenu(menu)
|
||||||
|
|
||||||
err := app.Run()
|
err := app.Run()
|
||||||
|
|
||||||
|
@ -84,9 +84,6 @@ func (m *macosMenu) update() {
|
|||||||
|
|
||||||
func (m *macosMenu) processMenu(parent unsafe.Pointer, menu *Menu) {
|
func (m *macosMenu) processMenu(parent unsafe.Pointer, menu *Menu) {
|
||||||
for _, item := range menu.items {
|
for _, item := range menu.items {
|
||||||
if item.hidden {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch item.itemType {
|
switch item.itemType {
|
||||||
case submenu:
|
case submenu:
|
||||||
submenu := item.submenu
|
submenu := item.submenu
|
||||||
@ -102,6 +99,9 @@ func (m *macosMenu) processMenu(parent unsafe.Pointer, menu *Menu) {
|
|||||||
case text, checkbox, radio:
|
case text, checkbox, radio:
|
||||||
menuItem := newMenuItemImpl(item)
|
menuItem := newMenuItemImpl(item)
|
||||||
item.impl = menuItem
|
item.impl = menuItem
|
||||||
|
if item.hidden {
|
||||||
|
menuItem.setHidden(true)
|
||||||
|
}
|
||||||
C.addMenuItem(parent, menuItem.nsMenuItem)
|
C.addMenuItem(parent, menuItem.nsMenuItem)
|
||||||
case separator:
|
case separator:
|
||||||
C.addMenuSeparator(parent)
|
C.addMenuSeparator(parent)
|
||||||
|
@ -36,6 +36,14 @@ func (w *windowsMenu) update() {
|
|||||||
|
|
||||||
func (w *windowsMenu) processMenu(parentMenu w32.HMENU, inputMenu *Menu) {
|
func (w *windowsMenu) processMenu(parentMenu w32.HMENU, inputMenu *Menu) {
|
||||||
for _, item := range inputMenu.items {
|
for _, item := range inputMenu.items {
|
||||||
|
w.currentMenuID++
|
||||||
|
itemID := w.currentMenuID
|
||||||
|
w.menuMapping[itemID] = item
|
||||||
|
|
||||||
|
menuItemImpl := newMenuItemImpl(item, parentMenu, itemID)
|
||||||
|
menuItemImpl.parent = inputMenu
|
||||||
|
item.impl = menuItemImpl
|
||||||
|
|
||||||
if item.Hidden() {
|
if item.Hidden() {
|
||||||
if item.accelerator != nil && item.callback != nil {
|
if item.accelerator != nil && item.callback != nil {
|
||||||
if w.parentWindow != nil {
|
if w.parentWindow != nil {
|
||||||
@ -44,11 +52,7 @@ func (w *windowsMenu) processMenu(parentMenu w32.HMENU, inputMenu *Menu) {
|
|||||||
globalApplication.removeKeyBinding(item.accelerator.String())
|
globalApplication.removeKeyBinding(item.accelerator.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
w.currentMenuID++
|
|
||||||
itemID := w.currentMenuID
|
|
||||||
w.menuMapping[itemID] = item
|
|
||||||
|
|
||||||
flags := uint32(w32.MF_STRING)
|
flags := uint32(w32.MF_STRING)
|
||||||
if item.disabled {
|
if item.disabled {
|
||||||
@ -84,6 +88,11 @@ func (w *windowsMenu) processMenu(parentMenu w32.HMENU, inputMenu *Menu) {
|
|||||||
}
|
}
|
||||||
var menuText = w32.MustStringToUTF16Ptr(thisText)
|
var menuText = w32.MustStringToUTF16Ptr(thisText)
|
||||||
|
|
||||||
|
// If the item is hidden, don't append
|
||||||
|
if item.Hidden() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
w32.AppendMenu(parentMenu, flags, uintptr(itemID), menuText)
|
w32.AppendMenu(parentMenu, flags, uintptr(itemID), menuText)
|
||||||
if item.bitmap != nil {
|
if item.bitmap != nil {
|
||||||
w32.SetMenuIcons(parentMenu, itemID, item.bitmap, nil)
|
w32.SetMenuIcons(parentMenu, itemID, item.bitmap, nil)
|
||||||
|
@ -24,9 +24,9 @@ type windowsMenuItem struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *windowsMenuItem) setHidden(hidden bool) {
|
func (m *windowsMenuItem) setHidden(hidden bool) {
|
||||||
m.hidden = hidden
|
if hidden && !m.hidden {
|
||||||
if m.hidden {
|
m.hidden = true
|
||||||
// iterate the parent items and find the menu item before us
|
// iterate the parent items and find the menu item after us
|
||||||
for i, item := range m.parent.items {
|
for i, item := range m.parent.items {
|
||||||
if item == m.menuItem {
|
if item == m.menuItem {
|
||||||
if i < len(m.parent.items)-1 {
|
if i < len(m.parent.items)-1 {
|
||||||
@ -37,13 +37,11 @@ func (m *windowsMenuItem) setHidden(hidden bool) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get the position of this menu item in the parent menu
|
|
||||||
// m.pos = w32.GetMenuItemPosition(m.hMenu, uint32(m.id))
|
|
||||||
// Remove from parent menu
|
// Remove from parent menu
|
||||||
w32.RemoveMenu(m.hMenu, m.id, w32.MF_BYCOMMAND)
|
w32.RemoveMenu(m.hMenu, m.id, w32.MF_BYCOMMAND)
|
||||||
} else {
|
} else if !hidden && m.hidden {
|
||||||
// Add to parent menu
|
m.hidden = false
|
||||||
// Get the position of the item before us
|
// Add to parent menu before the "itemAfter"
|
||||||
var pos int
|
var pos int
|
||||||
if m.itemAfter != nil {
|
if m.itemAfter != nil {
|
||||||
for i, item := range m.parent.items {
|
for i, item := range m.parent.items {
|
||||||
|
@ -61,6 +61,14 @@ func (p *Win32Menu) newMenu() w32.HMENU {
|
|||||||
func (p *Win32Menu) buildMenu(parentMenu w32.HMENU, inputMenu *Menu) {
|
func (p *Win32Menu) buildMenu(parentMenu w32.HMENU, inputMenu *Menu) {
|
||||||
currentRadioGroup := RadioGroup{}
|
currentRadioGroup := RadioGroup{}
|
||||||
for _, item := range inputMenu.items {
|
for _, item := range inputMenu.items {
|
||||||
|
p.currentMenuID++
|
||||||
|
itemID := p.currentMenuID
|
||||||
|
p.menuMapping[itemID] = item
|
||||||
|
|
||||||
|
menuItemImpl := newMenuItemImpl(item, parentMenu, itemID)
|
||||||
|
menuItemImpl.parent = inputMenu
|
||||||
|
item.impl = menuItemImpl
|
||||||
|
|
||||||
if item.Hidden() {
|
if item.Hidden() {
|
||||||
if item.accelerator != nil {
|
if item.accelerator != nil {
|
||||||
if p.parentWindow != nil {
|
if p.parentWindow != nil {
|
||||||
@ -71,14 +79,7 @@ func (p *Win32Menu) buildMenu(parentMenu w32.HMENU, inputMenu *Menu) {
|
|||||||
globalApplication.removeKeyBinding(item.accelerator.String())
|
globalApplication.removeKeyBinding(item.accelerator.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
p.currentMenuID++
|
|
||||||
itemID := p.currentMenuID
|
|
||||||
p.menuMapping[itemID] = item
|
|
||||||
|
|
||||||
menuItemImpl := newMenuItemImpl(item, parentMenu, itemID)
|
|
||||||
menuItemImpl.parent = inputMenu
|
|
||||||
|
|
||||||
flags := uint32(w32.MF_STRING)
|
flags := uint32(w32.MF_STRING)
|
||||||
if item.disabled {
|
if item.disabled {
|
||||||
@ -131,6 +132,12 @@ func (p *Win32Menu) buildMenu(parentMenu w32.HMENU, inputMenu *Menu) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the item is hidden, don't append
|
||||||
|
if item.Hidden() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
ok := w32.AppendMenu(parentMenu, flags, uintptr(itemID), w32.MustStringToUTF16Ptr(menuText))
|
ok := w32.AppendMenu(parentMenu, flags, uintptr(itemID), w32.MustStringToUTF16Ptr(menuText))
|
||||||
if !ok {
|
if !ok {
|
||||||
globalApplication.fatal("error adding menu item '%s'", menuText)
|
globalApplication.fatal("error adding menu item '%s'", menuText)
|
||||||
@ -141,8 +148,6 @@ func (p *Win32Menu) buildMenu(parentMenu w32.HMENU, inputMenu *Menu) {
|
|||||||
globalApplication.fatal("error setting menu icons: %w", err)
|
globalApplication.fatal("error setting menu icons: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
item.impl = menuItemImpl
|
|
||||||
}
|
}
|
||||||
if len(currentRadioGroup) > 0 {
|
if len(currentRadioGroup) > 0 {
|
||||||
for _, radioMember := range currentRadioGroup {
|
for _, radioMember := range currentRadioGroup {
|
||||||
|
@ -108,6 +108,7 @@ type (
|
|||||||
showMenuBar()
|
showMenuBar()
|
||||||
hideMenuBar()
|
hideMenuBar()
|
||||||
toggleMenuBar()
|
toggleMenuBar()
|
||||||
|
setMenu(menu *Menu)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -168,6 +169,22 @@ type WebviewWindow struct {
|
|||||||
unconditionallyClose bool
|
unconditionallyClose bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *WebviewWindow) SetMenu(menu *Menu) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin":
|
||||||
|
return
|
||||||
|
case "windows":
|
||||||
|
w.options.Windows.Menu = menu
|
||||||
|
case "linux":
|
||||||
|
w.options.Linux.Menu = menu
|
||||||
|
}
|
||||||
|
if w.impl != nil {
|
||||||
|
InvokeSync(func() {
|
||||||
|
w.impl.setMenu(menu)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// EmitEvent emits an event from the window
|
// EmitEvent emits an event from the window
|
||||||
func (w *WebviewWindow) EmitEvent(name string, data ...any) {
|
func (w *WebviewWindow) EmitEvent(name string, data ...any) {
|
||||||
globalApplication.emitEvent(&CustomEvent{
|
globalApplication.emitEvent(&CustomEvent{
|
||||||
|
@ -1427,6 +1427,7 @@ func (w *macosWebviewWindow) delete() {
|
|||||||
func (w *macosWebviewWindow) redo() {
|
func (w *macosWebviewWindow) redo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *macosWebviewWindow) showMenuBar() {}
|
func (w *macosWebviewWindow) showMenuBar() {}
|
||||||
func (w *macosWebviewWindow) hideMenuBar() {}
|
func (w *macosWebviewWindow) hideMenuBar() {}
|
||||||
func (w *macosWebviewWindow) toggleMenuBar() {}
|
func (w *macosWebviewWindow) toggleMenuBar() {}
|
||||||
|
func (w *macosWebviewWindow) setMenu(_ *Menu) {}
|
||||||
|
@ -235,6 +235,15 @@ func (w *linuxWebviewWindow) setPhysicalBounds(physicalBounds Rect) {
|
|||||||
w.setBounds(physicalBounds)
|
w.setBounds(physicalBounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *linuxWebviewWindow) setMenu(menu *Menu) {
|
||||||
|
if menu == nil {
|
||||||
|
w.gtkmenu = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.parent.options.Linux.Menu = menu
|
||||||
|
w.gtkmenu = (menu.impl).(*linuxMenu).native
|
||||||
|
}
|
||||||
|
|
||||||
func (w *linuxWebviewWindow) run() {
|
func (w *linuxWebviewWindow) run() {
|
||||||
for eventId := range w.parent.eventListeners {
|
for eventId := range w.parent.eventListeners {
|
||||||
w.on(eventId)
|
w.on(eventId)
|
||||||
|
@ -73,6 +73,13 @@ type windowsWebviewWindow struct {
|
|||||||
isMinimizing bool
|
isMinimizing bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *windowsWebviewWindow) setMenu(menu *Menu) {
|
||||||
|
menu.Update()
|
||||||
|
w.menu = NewApplicationMenu(w, menu)
|
||||||
|
w.menu.parentWindow = w
|
||||||
|
w32.SetMenu(w.hwnd, w.menu.menu)
|
||||||
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) cut() {
|
func (w *windowsWebviewWindow) cut() {
|
||||||
w.execJS("document.execCommand('cut')")
|
w.execJS("document.execCommand('cut')")
|
||||||
}
|
}
|
||||||
|
@ -84,4 +84,5 @@ type Window interface {
|
|||||||
ZoomIn()
|
ZoomIn()
|
||||||
ZoomOut()
|
ZoomOut()
|
||||||
ZoomReset() Window
|
ZoomReset() Window
|
||||||
|
SetMenu(menu *Menu)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user