[windows] Fixes for radiobox sync

This commit is contained in:
Lea Anthony
2021-07-10 17:03:46 +10:00
parent 856b81ab04
commit 4f2788a294
11 changed files with 212 additions and 17 deletions

View File

@@ -14,7 +14,7 @@ extern void DisableWindowIcon(struct Application* app);
*/
import "C"
import (
"log"
"os"
"github.com/wailsapp/wails/v2/pkg/menu"
)
@@ -105,7 +105,9 @@ been sent.
func checkFatal(err error) {
if err != nil {
log.Fatal(err)
globalRadioGroupCache.Dump()
globalRadioGroupMap.Dump()
os.Exit(1)
}
}
@@ -150,7 +152,7 @@ func menuClicked(id uint32) {
// Determine if the menu is set or not
res, _, err := win32GetMenuState.Call(uintptr(menuItemDetails.parent), uintptr(id), uintptr(MF_BYCOMMAND))
if int(res) == -1 {
log.Fatal(err)
checkFatal(err)
}
flag := MF_CHECKED
@@ -163,11 +165,12 @@ func menuClicked(id uint32) {
menuItemDetails := getMenuCacheEntry(menuid)
res, _, err = win32CheckMenuItem.Call(uintptr(menuItemDetails.parent), uintptr(menuid), uintptr(flag))
if int(res) == -1 {
log.Fatal(err)
checkFatal(err)
}
}
case menu.RadioType:
selectRadioItemFromWailsMenuID(wailsMenuID, win32MenuID)
err := selectRadioItemFromWailsMenuID(wailsMenuID, win32MenuID)
checkFatal(err)
}
// Print the click error - it's not fatal

View File

@@ -3,8 +3,12 @@
package ffenestri
import (
"fmt"
"github.com/leaanthony/slicer"
"github.com/wailsapp/wails/v2/internal/menumanager"
"os"
"sync"
"text/tabwriter"
)
/* ---------------------------------------------------------------------------------
@@ -28,6 +32,26 @@ func NewCheckboxCache() *CheckboxCache {
}
}
func (c *CheckboxCache) Dump() {
// Start a new tabwriter
w := new(tabwriter.Writer)
w.Init(os.Stdout, 8, 8, 0, '\t', 0)
println("---------------- Checkbox", c, "Dump ----------------")
for _, processedMenu := range c.cache {
println("Menu", processedMenu)
for wailsMenuItemID, win32menus := range processedMenu {
println(" WailsMenu: ", wailsMenuItemID)
menus := slicer.String()
for _, win32menu := range win32menus {
menus.Add(fmt.Sprintf("%v", win32menu))
}
_, _ = fmt.Fprintf(w, "%s\t%s\n", wailsMenuItemID, menus.Join(", "))
_ = w.Flush()
}
}
}
func (c *CheckboxCache) addToCheckboxCache(menu *menumanager.ProcessedMenu, item wailsMenuItemID, menuID win32MenuItemID) {
// Get map for menu

View File

@@ -0,0 +1,28 @@
//+build windows,debug
package ffenestri
import (
"fmt"
"github.com/ztrue/tracerr"
"runtime"
"strings"
)
func wall(err error, inputs ...interface{}) error {
if err == nil {
return nil
}
pc, _, _, _ := runtime.Caller(1)
funcName := runtime.FuncForPC(pc).Name()
splitName := strings.Split(funcName, ".")
message := "[" + splitName[len(splitName)-1] + "]"
if len(inputs) > 0 {
params := []string{}
for _, param := range inputs {
params = append(params, fmt.Sprintf("%v", param))
}
message += "(" + strings.Join(params, " ") + ")"
}
return tracerr.Errorf(message)
}

View File

@@ -0,0 +1,47 @@
// +build windows,!debug
package ffenestri
import "C"
import (
"fmt"
"golang.org/x/sys/windows"
"log"
"os"
"runtime"
"strings"
"syscall"
)
func wall(err error, inputs ...interface{}) error {
if err == nil {
return nil
}
pc, _, _, _ := runtime.Caller(1)
funcName := runtime.FuncForPC(pc).Name()
splitName := strings.Split(funcName, ".")
message := "[" + splitName[len(splitName)-1] + "]"
if len(inputs) > 0 {
params := []string{}
for _, param := range inputs {
params = append(params, fmt.Sprintf("%v", param))
}
message += "(" + strings.Join(params, " ") + ")"
}
title, err := syscall.UTF16PtrFromString("Fatal Error")
if err != nil {
log.Fatal(err)
}
text, err := syscall.UTF16PtrFromString("There has been a fatal error. Details:\n" + message)
if err != nil {
log.Fatal(err)
}
var flags uint32 = windows.MB_ICONERROR | windows.MB_OK
_, err = windows.MessageBox(0, text, title, flags|windows.MB_SYSTEMMODAL)
os.Exit(1)
return err
}

View File

@@ -142,7 +142,10 @@ func (m *Menu) processRadioGroups() error {
for _, win32MenuID := range m.initiallySelectedRadioItems {
menuItemDetails := getMenuCacheEntry(win32MenuID)
wailsMenuID := wailsMenuItemID(menuItemDetails.item.ID)
selectRadioItemFromWailsMenuID(wailsMenuID, win32MenuID)
err := selectRadioItemFromWailsMenuID(wailsMenuID, win32MenuID)
if err != nil {
return err
}
}
return nil
@@ -156,6 +159,8 @@ func (m *Menu) Destroy() error {
// Unload this menu's radio groups from the cache
globalRadioGroupCache.removeMenuFromRadioBoxCache(m.wailsMenu.Menu)
globalRadioGroupMap.removeMenuFromRadioGroupMapping(m.wailsMenu.Menu)
// Delete menu
return destroyWin32Menu(m.menu)
}

View File

@@ -3,7 +3,11 @@
package ffenestri
import (
"fmt"
"github.com/leaanthony/slicer"
"os"
"sync"
"text/tabwriter"
"github.com/wailsapp/wails/v2/internal/menumanager"
)
@@ -36,6 +40,26 @@ func NewRadioGroupCache() *RadioGroupCache {
}
}
func (c *RadioGroupCache) Dump() {
// Start a new tabwriter
w := new(tabwriter.Writer)
w.Init(os.Stdout, 8, 8, 0, '\t', 0)
println("---------------- RadioGroupCache", c, "Dump ----------------")
for menu, processedMenu := range c.cache {
println("Menu", menu)
_, _ = fmt.Fprintf(w, "Wails ID \tWindows ID Pairs\n")
for wailsMenuItemID, radioGroupStartEnd := range processedMenu {
menus := slicer.String()
for _, se := range radioGroupStartEnd {
menus.Add(fmt.Sprintf("[%d -> %d]", se.startID, se.endID))
}
_, _ = fmt.Fprintf(w, "%s\t%s\n", wailsMenuItemID, menus.Join(", "))
_ = w.Flush()
}
}
}
func (c *RadioGroupCache) addToRadioGroupCache(menu *menumanager.ProcessedMenu, item wailsMenuItemID, radioGroupMaps []*radioGroupStartEnd) {
c.mutex.Lock()
@@ -87,6 +111,25 @@ func NewRadioGroupMap() *RadioGroupMap {
}
}
func (c *RadioGroupMap) Dump() {
// Start a new tabwriter
w := new(tabwriter.Writer)
w.Init(os.Stdout, 8, 8, 0, '\t', 0)
println("---------------- RadioGroupMap", c, "Dump ----------------")
for _, processedMenu := range c.cache {
_, _ = fmt.Fprintf(w, "Menu\tWails ID \tWindows IDs\n")
for wailsMenuItemID, win32menus := range processedMenu {
menus := slicer.String()
for _, win32menu := range win32menus {
menus.Add(fmt.Sprintf("%v", win32menu))
}
_, _ = fmt.Fprintf(w, "%p\t%s\t%s\n", processedMenu, wailsMenuItemID, menus.Join(", "))
_ = w.Flush()
}
}
}
func (m *RadioGroupMap) addRadioGroupMapping(menu *menumanager.ProcessedMenu, item wailsMenuItemID, win32ID win32MenuItemID) {
m.mutex.Lock()
@@ -106,6 +149,12 @@ func (m *RadioGroupMap) addRadioGroupMapping(menu *menumanager.ProcessedMenu, it
m.mutex.Unlock()
}
func (m *RadioGroupMap) removeMenuFromRadioGroupMapping(menu *menumanager.ProcessedMenu) {
m.mutex.Lock()
delete(m.cache, menu)
m.mutex.Unlock()
}
func (m *RadioGroupMap) getRadioGroupMapping(wailsMenuID wailsMenuItemID) []win32MenuItemID {
m.mutex.Lock()
result := []win32MenuItemID{}
@@ -119,7 +168,7 @@ func (m *RadioGroupMap) getRadioGroupMapping(wailsMenuID wailsMenuItemID) []win3
return result
}
func selectRadioItemFromWailsMenuID(wailsMenuID wailsMenuItemID, win32MenuID win32MenuItemID) {
func selectRadioItemFromWailsMenuID(wailsMenuID wailsMenuItemID, win32MenuID win32MenuItemID) error {
radioItemGroups := globalRadioGroupCache.getRadioGroupMappings(wailsMenuID)
// Figure out offset into group
var offset win32MenuItemID = 0
@@ -132,6 +181,14 @@ func selectRadioItemFromWailsMenuID(wailsMenuID wailsMenuItemID, win32MenuID win
for _, radioItemGroup := range radioItemGroups {
selectedMenuID := radioItemGroup.startID + offset
menuItemDetails := getMenuCacheEntry(selectedMenuID)
selectRadioItem(selectedMenuID, radioItemGroup.startID, radioItemGroup.endID, menuItemDetails.parent)
if menuItemDetails != nil {
if menuItemDetails.parent != 0 {
err := selectRadioItem(selectedMenuID, radioItemGroup.startID, radioItemGroup.endID, menuItemDetails.parent)
if err != nil {
return err
}
}
}
}
return nil
}

View File

@@ -3,7 +3,6 @@
package ffenestri
import (
"log"
"unsafe"
"github.com/wailsapp/wails/v2/internal/menumanager"
@@ -45,15 +44,15 @@ const MF_BYPOSITION uint32 = 0x00000400
func createWin32Menu() (win32Menu, error) {
res, _, err := win32CreateMenu.Call()
if res == 0 {
return 0, err
return 0, wall(err)
}
return win32Menu(res), nil
}
func destroyWin32Menu(menu win32Menu) error {
res, _, err := win32CreateMenu.Call(uintptr(menu))
res, _, err := win32DestroyMenu.Call(uintptr(menu))
if res == 0 {
return err
return wall(err, "Menu:", menu)
}
return nil
}
@@ -61,7 +60,7 @@ func destroyWin32Menu(menu win32Menu) error {
func createWin32PopupMenu() (win32Menu, error) {
res, _, err := win32CreatePopupMenu.Call()
if res == 0 {
return 0, err
return 0, wall(err)
}
return win32Menu(res), nil
}
@@ -78,7 +77,7 @@ func appendWin32MenuItem(menu win32Menu, flags uintptr, submenuOrID uintptr, lab
uintptr(unsafe.Pointer(menuText)),
)
if res == 0 {
return err
return wall(err, "Menu", menu, "Flags", flags, "submenuOrID", submenuOrID, "label", label)
}
return nil
}
@@ -86,14 +85,15 @@ func appendWin32MenuItem(menu win32Menu, flags uintptr, submenuOrID uintptr, lab
func setWindowMenu(window win32Window, menu win32Menu) error {
res, _, err := win32SetMenu.Call(uintptr(window), uintptr(menu))
if res == 0 {
return err
return wall(err, "window", window, "menu", menu)
}
return nil
}
func selectRadioItem(selectedMenuID, startMenuItemID, endMenuItemID win32MenuItemID, parent win32Menu) {
func selectRadioItem(selectedMenuID, startMenuItemID, endMenuItemID win32MenuItemID, parent win32Menu) error {
res, _, err := win32CheckMenuRadioItem.Call(uintptr(parent), uintptr(startMenuItemID), uintptr(endMenuItemID), uintptr(selectedMenuID), uintptr(MF_BYCOMMAND))
if int(res) == 0 {
log.Fatal(err)
return wall(err, selectedMenuID, startMenuItemID, endMenuItemID, parent)
}
return nil
}