5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-03 06:20:48 +08:00

[windows-x] Runtime ported. Menu shortcuts.

This commit is contained in:
Lea Anthony 2021-07-25 20:21:21 +10:00
parent 72b1e58218
commit 5b10ee4b40
13 changed files with 574 additions and 44 deletions

View File

@ -131,7 +131,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
bindingExemptions := []interface{}{appoptions.Startup, appoptions.Shutdown} bindingExemptions := []interface{}{appoptions.Startup, appoptions.Shutdown}
appBindings := binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions) appBindings := binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions)
appFrontend := frontend.NewFrontend(appoptions, myLogger, appBindings) appFrontend := NewFrontend(appoptions, myLogger, appBindings)
result := &App{ result := &App{
frontend: appFrontend, frontend: appFrontend,

View File

@ -1,12 +1,13 @@
package frontend package appng
import ( import (
"github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/windows" "github.com/wailsapp/wails/v2/internal/frontend/windows"
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options"
) )
func NewFrontend(appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings) *windows.Frontend { func NewFrontend(appoptions *options.App, myLogger *logger.Logger, bindings *binding.Bindings) frontend.Frontend {
return windows.NewFrontend(appoptions, myLogger, appBindings) return windows.NewFrontend(appoptions, myLogger, bindings)
} }

View File

@ -1,5 +1,58 @@
package frontend package frontend
import "github.com/wailsapp/wails/v2/pkg/menu"
// FileFilter defines a filter for dialog boxes
type FileFilter struct {
DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)"
Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png"
}
// OpenDialogOptions contains the options for the OpenDialogOptions runtime method
type OpenDialogOptions struct {
DefaultDirectory string
DefaultFilename string
Title string
Filters []FileFilter
AllowFiles bool
AllowDirectories bool
ShowHiddenFiles bool
CanCreateDirectories bool
ResolvesAliases bool
TreatPackagesAsDirectories bool
}
// SaveDialogOptions contains the options for the SaveDialog runtime method
type SaveDialogOptions struct {
DefaultDirectory string
DefaultFilename string
Title string
Filters []FileFilter
ShowHiddenFiles bool
CanCreateDirectories bool
TreatPackagesAsDirectories bool
}
type DialogType string
const (
InfoDialog DialogType = "info"
WarningDialog DialogType = "warning"
ErrorDialog DialogType = "error"
QuestionDialog DialogType = "question"
)
// MessageDialogOptions contains the options for the Message dialogs, EG Info, Warning, etc runtime methods
type MessageDialogOptions struct {
Type DialogType
Title string
Message string
Buttons []string
DefaultButton string
CancelButton string
Icon string
}
type Frontend interface { type Frontend interface {
// Main methods // Main methods
@ -10,12 +63,12 @@ type Frontend interface {
//NotifyEvent(message string) //NotifyEvent(message string)
//CallResult(message string) //CallResult(message string)
// //
//// Dialog // Dialog
//OpenFileDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) OpenFileDialog(dialogOptions OpenDialogOptions) (string, error)
//OpenMultipleFilesDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) OpenMultipleFilesDialog(dialogOptions OpenDialogOptions) ([]string, error)
//OpenDirectoryDialog(dialogOptions dialog.OpenDialogOptions, callbackID string) OpenDirectoryDialog(dialogOptions OpenDialogOptions) (string, error)
//SaveDialog(dialogOptions dialog.SaveDialogOptions, callbackID string) SaveFileDialog(dialogOptions SaveDialogOptions) (string, error)
//MessageDialog(dialogOptions dialog.MessageDialogOptions, callbackID string) MessageDialog(dialogOptions MessageDialogOptions) (string, error)
// Window // Window
WindowSetTitle(title string) WindowSetTitle(title string)
@ -35,9 +88,10 @@ type Frontend interface {
WindowFullscreen() WindowFullscreen()
WindowUnFullscreen() WindowUnFullscreen()
WindowSetColour(colour int) WindowSetColour(colour int)
//
//// Menus // Menus
//SetApplicationMenu(menu *menu.Menu) SetApplicationMenu(menu *menu.Menu)
UpdateApplicationMenu()
//SetTrayMenu(menu *menu.TrayMenu) //SetTrayMenu(menu *menu.TrayMenu)
//UpdateTrayMenuLabel(menu *menu.TrayMenu) //UpdateTrayMenuLabel(menu *menu.TrayMenu)
//UpdateContextMenu(contextMenu *menu.ContextMenu) //UpdateContextMenu(contextMenu *menu.ContextMenu)

View File

@ -0,0 +1,151 @@
package windows
import "C"
import (
"github.com/leaanthony/go-common-file-dialog/cfd"
"github.com/wailsapp/wails/v2/internal/frontend"
"golang.org/x/sys/windows"
"syscall"
)
// OpenDirectoryDialog prompts the user to select a directory
func (f *Frontend) OpenDirectoryDialog(options frontend.OpenDialogOptions) (string, error) {
config := cfd.DialogConfig{
Title: options.Title,
Role: "PickFolder",
Folder: options.DefaultDirectory,
}
thisDialog, err := cfd.NewSelectFolderDialog(config)
if err != nil {
return "", err
}
thisDialog.SetParentWindowHandle(f.mainWindow.Handle())
defer func(thisDialog cfd.SelectFolderDialog) {
err := thisDialog.Release()
if err != nil {
println("ERROR: Unable to release dialog:", err.Error())
}
}(thisDialog)
result, err := thisDialog.ShowAndGetResult()
if err != nil && err != cfd.ErrorCancelled {
return "", err
}
return result, nil
}
// OpenFileDialog prompts the user to select a file
func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, error) {
config := cfd.DialogConfig{
Folder: options.DefaultDirectory,
FileFilters: convertFilters(options.Filters),
FileName: options.DefaultFilename,
}
thisdialog, err := cfd.NewOpenFileDialog(config)
if err != nil {
return "", err
}
thisdialog.SetParentWindowHandle(f.mainWindow.Handle())
defer func(thisdialog cfd.OpenFileDialog) {
err := thisdialog.Release()
if err != nil {
println("ERROR: Unable to release dialog:", err.Error())
}
}(thisdialog)
result, err := thisdialog.ShowAndGetResult()
if err != nil && err != cfd.ErrorCancelled {
return "", err
}
return result, nil
}
// OpenMultipleFilesDialog prompts the user to select a file
func (f *Frontend) OpenMultipleFilesDialog(dialogOptions frontend.OpenDialogOptions) ([]string, error) {
config := cfd.DialogConfig{
Title: dialogOptions.Title,
Role: "OpenMultipleFiles",
FileFilters: convertFilters(dialogOptions.Filters),
FileName: dialogOptions.DefaultFilename,
Folder: dialogOptions.DefaultDirectory,
}
thisdialog, err := cfd.NewOpenMultipleFilesDialog(config)
if err != nil {
return nil, err
}
thisdialog.SetParentWindowHandle(f.mainWindow.Handle())
defer func(thisdialog cfd.OpenMultipleFilesDialog) {
err := thisdialog.Release()
if err != nil {
println("ERROR: Unable to release dialog:", err.Error())
}
}(thisdialog)
result, err := thisdialog.ShowAndGetResults()
if err != nil && err != cfd.ErrorCancelled {
return nil, err
}
return result, nil
}
// SaveFileDialog prompts the user to select a file
func (f *Frontend) SaveFileDialog(dialogOptions frontend.SaveDialogOptions) (string, error) {
saveDialog, err := cfd.NewSaveFileDialog(cfd.DialogConfig{
Title: dialogOptions.Title,
Role: "SaveFile",
FileFilters: convertFilters(dialogOptions.Filters),
FileName: dialogOptions.DefaultFilename,
Folder: dialogOptions.DefaultDirectory,
})
if err != nil {
return "", err
}
saveDialog.SetParentWindowHandle(f.mainWindow.Handle())
err = saveDialog.Show()
if err != nil {
return "", err
}
result, err := saveDialog.GetResult()
if err != nil && err != cfd.ErrorCancelled {
return "", err
}
return result, nil
}
// MessageDialog show a message dialog to the user
func (f *Frontend) MessageDialog(options frontend.MessageDialogOptions) (string, error) {
title, err := syscall.UTF16PtrFromString(options.Title)
if err != nil {
return "", err
}
message, err := syscall.UTF16PtrFromString(options.Message)
if err != nil {
return "", err
}
var flags uint32
switch options.Type {
case frontend.InfoDialog:
flags = windows.MB_OK | windows.MB_ICONINFORMATION
case frontend.ErrorDialog:
flags = windows.MB_ICONERROR | windows.MB_OK
case frontend.QuestionDialog:
flags = windows.MB_YESNO
case frontend.WarningDialog:
flags = windows.MB_OK | windows.MB_ICONWARNING
}
button, _ := windows.MessageBox(windows.HWND(f.mainWindow.Handle()), message, title, flags|windows.MB_SYSTEMMODAL)
// This maps MessageBox return values to strings
responses := []string{"", "Ok", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No", "", "", "Try Again", "Continue"}
result := "Error"
if int(button) < len(responses) {
result = responses[button]
}
return result, nil
}
func convertFilters(filters []frontend.FileFilter) []cfd.FileFilter {
var result []cfd.FileFilter
for _, filter := range filters {
result = append(result, cfd.FileFilter(filter))
}
return result
}

View File

@ -1,6 +1,7 @@
package windows package windows
import ( import (
"context"
"github.com/tadvi/winc" "github.com/tadvi/winc"
"github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
@ -37,6 +38,12 @@ func (f *Frontend) Run() error {
} }
}) })
// TODO: Move this into a callback from frontend
go func() {
ctx := context.WithValue(context.Background(), "frontend", f)
f.frontendOptions.Startup(ctx)
}()
winc.RunMainLoop() winc.RunMainLoop()
return nil return nil
} }

View File

@ -0,0 +1,200 @@
package windows
import (
"github.com/tadvi/winc"
"github.com/wailsapp/wails/v2/pkg/menu/keys"
"strings"
)
var ModifierMap = map[keys.Modifier]winc.Modifiers{
keys.ShiftKey: winc.ModShift,
keys.ControlKey: winc.ModControl,
keys.OptionOrAltKey: winc.ModAlt,
keys.CmdOrCtrlKey: winc.ModControl,
}
func acceleratorToWincShortcut(accelerator *keys.Accelerator) winc.Shortcut {
if accelerator == nil {
return winc.NoShortcut
}
inKey := strings.ToUpper(accelerator.Key)
key, exists := keyMap[inKey]
if !exists {
return winc.NoShortcut
}
var modifiers winc.Modifiers
if _, exists := shiftMap[inKey]; exists {
modifiers = winc.ModShift
}
for _, mod := range accelerator.Modifiers {
modifiers |= ModifierMap[mod]
}
return winc.Shortcut{
Modifiers: modifiers,
Key: key,
}
}
var shiftMap = map[string]struct{}{
"~": {},
")": {},
"!": {},
"@": {},
"#": {},
"$": {},
"%": {},
"^": {},
"&": {},
"*": {},
"(": {},
"_": {},
"PLUS": {},
"<": {},
">": {},
"?": {},
":": {},
`"`: {},
"{": {},
"}": {},
"|": {},
}
var keyMap = map[string]winc.Key{
"0": winc.Key0,
"1": winc.Key1,
"2": winc.Key2,
"3": winc.Key3,
"4": winc.Key4,
"5": winc.Key5,
"6": winc.Key6,
"7": winc.Key7,
"8": winc.Key8,
"9": winc.Key9,
"A": winc.KeyA,
"B": winc.KeyB,
"C": winc.KeyC,
"D": winc.KeyD,
"E": winc.KeyE,
"F": winc.KeyF,
"G": winc.KeyG,
"H": winc.KeyH,
"I": winc.KeyI,
"J": winc.KeyJ,
"K": winc.KeyK,
"L": winc.KeyL,
"M": winc.KeyM,
"N": winc.KeyN,
"O": winc.KeyO,
"P": winc.KeyP,
"Q": winc.KeyQ,
"R": winc.KeyR,
"S": winc.KeyS,
"T": winc.KeyT,
"U": winc.KeyU,
"V": winc.KeyV,
"W": winc.KeyW,
"X": winc.KeyX,
"Y": winc.KeyY,
"Z": winc.KeyZ,
"F1": winc.KeyF1,
"F2": winc.KeyF2,
"F3": winc.KeyF3,
"F4": winc.KeyF4,
"F5": winc.KeyF5,
"F6": winc.KeyF6,
"F7": winc.KeyF7,
"F8": winc.KeyF8,
"F9": winc.KeyF9,
"F10": winc.KeyF10,
"F11": winc.KeyF11,
"F12": winc.KeyF12,
"F13": winc.KeyF13,
"F14": winc.KeyF14,
"F15": winc.KeyF15,
"F16": winc.KeyF16,
"F17": winc.KeyF17,
"F18": winc.KeyF18,
"F19": winc.KeyF19,
"F20": winc.KeyF20,
"F21": winc.KeyF21,
"F22": winc.KeyF22,
"F23": winc.KeyF23,
"F24": winc.KeyF24,
"`": winc.KeyOEM3,
",": winc.KeyOEMComma,
".": winc.KeyOEMPeriod,
"/": winc.KeyOEM2,
";": winc.KeyOEM1,
"'": winc.KeyOEM7,
"[": winc.KeyOEM4,
"]": winc.KeyOEM6,
`\`: winc.KeyOEM5,
"~": winc.KeyOEM3, //
")": winc.Key0,
"!": winc.Key1,
"@": winc.Key2,
"#": winc.Key3,
"$": winc.Key4,
"%": winc.Key5,
"^": winc.Key6,
"&": winc.Key7,
"*": winc.Key8,
"(": winc.Key9,
"_": winc.KeyOEMMinus,
"PLUS": winc.KeyOEMPlus,
"<": winc.KeyOEMComma,
">": winc.KeyOEMPeriod,
"?": winc.KeyOEM2,
":": winc.KeyOEM1,
`"`: winc.KeyOEM7,
"{": winc.KeyOEM4,
"}": winc.KeyOEM6,
"|": winc.KeyOEM5,
"SPACE": winc.KeySpace,
"TAB": winc.KeyTab,
"CAPSLOCK": winc.KeyCapital,
"NUMLOCK": winc.KeyNumlock,
"SCROLLLOCK": winc.KeyScroll,
"BACKSPACE": winc.KeyBack,
"DELETE": winc.KeyDelete,
"INSERT": winc.KeyInsert,
"RETURN": winc.KeyReturn,
"ENTER": winc.KeyReturn,
"UP": winc.KeyUp,
"DOWN": winc.KeyDown,
"LEFT": winc.KeyLeft,
"RIGHT": winc.KeyRight,
"HOME": winc.KeyHome,
"END": winc.KeyEnd,
"PAGEUP": winc.KeyPrior,
"PAGEDOWN": winc.KeyNext,
"ESCAPE": winc.KeyEscape,
"ESC": winc.KeyEscape,
"VOLUMEUP": winc.KeyVolumeUp,
"VOLUMEDOWN": winc.KeyVolumeDown,
"VOLUMEMUTE": winc.KeyVolumeMute,
"MEDIANEXTTRACK": winc.KeyMediaNextTrack,
"MEDIAPREVIOUSTRACK": winc.KeyMediaPrevTrack,
"MEDIASTOP": winc.KeyMediaStop,
"MEDIAPLAYPAUSE": winc.KeyMediaPlayPause,
"PRINTSCREEN": winc.KeyPrint,
"NUM0": winc.KeyNumpad0,
"NUM1": winc.KeyNumpad1,
"NUM2": winc.KeyNumpad2,
"NUM3": winc.KeyNumpad3,
"NUM4": winc.KeyNumpad4,
"NUM5": winc.KeyNumpad5,
"NUM6": winc.KeyNumpad6,
"NUM7": winc.KeyNumpad7,
"NUM8": winc.KeyNumpad8,
"NUM9": winc.KeyNumpad9,
"nummult": winc.KeyMultiply,
"numadd": winc.KeyAdd,
"numsub": winc.KeySubtract,
"numdec": winc.KeyDecimal,
"numdiv": winc.KeyDivide,
}

View File

@ -36,9 +36,14 @@ func addRadioItemToMap(menuItem *menu.MenuItem, wincMenuItem *winc.MenuItem) {
radioGroupMap[menuItem] = append(radioGroupMap[menuItem], wincMenuItem) radioGroupMap[menuItem] = append(radioGroupMap[menuItem], wincMenuItem)
} }
func processApplicationMenu(window *Window, menuToProcess *menu.Menu) { func (w *Window) SetApplicationMenu(menu *menu.Menu) {
w.applicationMenu = menu
processMenu(w, menu)
}
func processMenu(window *Window, menu *menu.Menu) {
mainMenu := window.NewMenu() mainMenu := window.NewMenu()
for _, menuItem := range menuToProcess.Items { for _, menuItem := range menu.Items {
submenu := mainMenu.AddSubMenu(menuItem.Label) submenu := mainMenu.AddSubMenu(menuItem.Label)
for _, menuItem := range menuItem.SubMenu.Items { for _, menuItem := range menuItem.SubMenu.Items {
processMenuItem(submenu, menuItem) processMenuItem(submenu, menuItem)
@ -55,7 +60,8 @@ func processMenuItem(parent *winc.MenuItem, menuItem *menu.MenuItem) {
case menu.SeparatorType: case menu.SeparatorType:
parent.AddSeparator() parent.AddSeparator()
case menu.TextType: case menu.TextType:
newItem := parent.AddItem(menuItem.Label, winc.NoShortcut) shortcut := acceleratorToWincShortcut(menuItem.Accelerator)
newItem := parent.AddItem(menuItem.Label, shortcut)
if menuItem.Tooltip != "" { if menuItem.Tooltip != "" {
newItem.SetToolTip(menuItem.Tooltip) newItem.SetToolTip(menuItem.Tooltip)
} }
@ -69,7 +75,8 @@ func processMenuItem(parent *winc.MenuItem, menuItem *menu.MenuItem) {
newItem.SetEnabled(!menuItem.Disabled) newItem.SetEnabled(!menuItem.Disabled)
case menu.CheckboxType: case menu.CheckboxType:
newItem := parent.AddItem(menuItem.Label, winc.NoShortcut) shortcut := acceleratorToWincShortcut(menuItem.Accelerator)
newItem := parent.AddItem(menuItem.Label, shortcut)
newItem.SetCheckable(true) newItem.SetCheckable(true)
newItem.SetChecked(menuItem.Checked) newItem.SetChecked(menuItem.Checked)
if menuItem.Tooltip != "" { if menuItem.Tooltip != "" {
@ -86,7 +93,8 @@ func processMenuItem(parent *winc.MenuItem, menuItem *menu.MenuItem) {
newItem.SetEnabled(!menuItem.Disabled) newItem.SetEnabled(!menuItem.Disabled)
addCheckBoxToMap(menuItem, newItem) addCheckBoxToMap(menuItem, newItem)
case menu.RadioType: case menu.RadioType:
newItem := parent.AddItemRadio(menuItem.Label, winc.NoShortcut) shortcut := acceleratorToWincShortcut(menuItem.Accelerator)
newItem := parent.AddItemRadio(menuItem.Label, shortcut)
newItem.SetCheckable(true) newItem.SetCheckable(true)
newItem.SetChecked(menuItem.Checked) newItem.SetChecked(menuItem.Checked)
if menuItem.Tooltip != "" { if menuItem.Tooltip != "" {
@ -109,3 +117,11 @@ func processMenuItem(parent *winc.MenuItem, menuItem *menu.MenuItem) {
} }
} }
} }
func (f *Frontend) SetApplicationMenu(menu *menu.Menu) {
f.mainWindow.SetApplicationMenu(menu)
}
func (f *Frontend) UpdateApplicationMenu() {
processMenu(f.mainWindow, f.mainWindow.applicationMenu)
}

View File

@ -3,12 +3,14 @@ package windows
import ( import (
"github.com/tadvi/winc" "github.com/tadvi/winc"
"github.com/tadvi/winc/w32" "github.com/tadvi/winc/w32"
"github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options"
) )
type Window struct { type Window struct {
winc.Form winc.Form
frontendOptions *options.App frontendOptions *options.App
applicationMenu *menu.Menu
} }
func NewWindow(parent winc.Controller, options *options.App) *Window { func NewWindow(parent winc.Controller, options *options.App) *Window {
@ -61,7 +63,7 @@ func NewWindow(parent winc.Controller, options *options.App) *Window {
} }
if options.Windows.Menu != nil { if options.Windows.Menu != nil {
processApplicationMenu(result, options.Windows.Menu) result.SetApplicationMenu(options.Windows.Menu)
} }
return result return result

View File

@ -187,10 +187,10 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
verbose := options.Verbosity == VERBOSE verbose := options.Verbosity == VERBOSE
// Run go mod tidy first // Run go mod tidy first
cmd := exec.Command(options.Compiler, "mod", "tidy") cmd := exec.Command(options.Compiler, "mod", "tidy")
cmd.Stderr = os.Stderr
if verbose { if verbose {
println("") println("")
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
} }
err := cmd.Run() err := cmd.Run()
if err != nil { if err != nil {
@ -271,10 +271,10 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
// Create the command // Create the command
cmd = exec.Command(options.Compiler, commands.AsSlice()...) cmd = exec.Command(options.Compiler, commands.AsSlice()...)
cmd.Stderr = os.Stderr
if verbose { if verbose {
println(" Build command:", commands.Join(" ")) println(" Build command:", commands.Join(" "))
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
} }
// Set the directory // Set the directory
cmd.Dir = b.projectData.Path cmd.Dir = b.projectData.Path
@ -321,17 +321,13 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
println(" Environment:", strings.Join(cmd.Env, " ")) println(" Environment:", strings.Join(cmd.Env, " "))
} }
// Setup buffers
var stdo, stde bytes.Buffer
cmd.Stdout = &stdo
cmd.Stderr = &stde
// Run command // Run command
err = cmd.Run() err = cmd.Run()
cmd.Stderr = os.Stderr
// Format error if we have one // Format error if we have one
if err != nil { if err != nil {
return fmt.Errorf("%s\n%s", err, string(stde.Bytes())) return err
} }
println("Done.") println("Done.")

View File

@ -0,0 +1,59 @@
//+build experimental
package runtime
import (
"context"
"github.com/wailsapp/wails/v2/internal/frontend"
)
// FileFilter defines a filter for dialog boxes
type FileFilter = frontend.FileFilter
// OpenDialogOptions contains the options for the OpenDialogOptions runtime method
type OpenDialogOptions = frontend.OpenDialogOptions
// SaveDialogOptions contains the options for the SaveDialog runtime method
type SaveDialogOptions = frontend.SaveDialogOptions
type DialogType = frontend.DialogType
const (
InfoDialog = frontend.InfoDialog
WarningDialog = frontend.WarningDialog
ErrorDialog = frontend.ErrorDialog
QuestionDialog = frontend.QuestionDialog
)
// MessageDialogOptions contains the options for the Message dialogs, EG Info, Warning, etc runtime methods
type MessageDialogOptions = frontend.MessageDialogOptions
// OpenDirectoryDialog prompts the user to select a directory
func OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error) {
frontend := getFrontend(ctx)
return frontend.OpenDirectoryDialog(dialogOptions)
}
// OpenFileDialog prompts the user to select a file
func OpenFileDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error) {
frontend := getFrontend(ctx)
return frontend.OpenFileDialog(dialogOptions)
}
// OpenMultipleFilesDialog prompts the user to select a file
func OpenMultipleFilesDialog(ctx context.Context, dialogOptions OpenDialogOptions) ([]string, error) {
frontend := getFrontend(ctx)
return frontend.OpenMultipleFilesDialog(dialogOptions)
}
// SaveFileDialog prompts the user to select a file
func SaveFileDialog(ctx context.Context, dialogOptions SaveDialogOptions) (string, error) {
frontend := getFrontend(ctx)
return frontend.SaveFileDialog(dialogOptions)
}
// MessageDialog show a message dialog to the user
func MessageDialog(ctx context.Context, dialogOptions MessageDialogOptions) (string, error) {
frontend := getFrontend(ctx)
return frontend.MessageDialog(dialogOptions)
}

View File

@ -60,23 +60,6 @@ type MessageDialogOptions struct {
Icon string Icon string
} }
// processTitleAndFilter return the title and filter from the given params.
// title is the first string, filter is the second
func processTitleAndFilter(params ...string) (string, string) {
var title, filter string
if len(params) > 0 {
title = params[0]
}
if len(params) > 1 {
filter = params[1]
}
return title, filter
}
// OpenDirectoryDialog prompts the user to select a directory // OpenDirectoryDialog prompts the user to select a directory
func OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error) { func OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error) {

34
v2/pkg/runtime/menu-x.go Normal file
View File

@ -0,0 +1,34 @@
//+build experimental
package runtime
import (
"context"
)
func UpdateApplicationMenu(ctx context.Context) {
frontend := getFrontend(ctx)
frontend.UpdateApplicationMenu()
}
/*
func UpdateContextMenu(ctx context.Context, contextMenu *menu.ContextMenu) {
frontend := getFrontend(ctx)
bus.Publish("menu:updatecontextmenu", contextMenu)
}
func SetTrayMenu(ctx context.Context, trayMenu *menu.TrayMenu) {
frontend := getFrontend(ctx)
bus.Publish("menu:settraymenu", trayMenu)
}
func UpdateTrayMenuLabel(ctx context.Context, trayMenu *menu.TrayMenu) {
frontend := getFrontend(ctx)
bus.Publish("menu:updatetraymenulabel", trayMenu)
}
func DeleteTrayMenu(ctx context.Context, trayMenu *menu.TrayMenu) {
frontend := getFrontend(ctx)
bus.Publish("menu:deletetraymenu", trayMenu)
}
*/

View File

@ -0,0 +1,27 @@
//+build experimental
package runtime
import (
"context"
"github.com/wailsapp/wails/v2/internal/frontend"
"log"
goruntime "runtime"
)
func getFrontend(ctx context.Context) frontend.Frontend {
result := ctx.Value("frontend")
if result != nil {
return result.(frontend.Frontend)
}
pc, _, _, _ := goruntime.Caller(1)
funcName := goruntime.FuncForPC(pc).Name()
log.Fatalf("cannot call '%s': Application not initialised", funcName)
return nil
}
// Quit the application
func Quit(ctx context.Context) {
frontend := getFrontend(ctx)
frontend.Quit()
}