mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 00:09:56 +08:00
194 lines
5.8 KiB
Go
194 lines
5.8 KiB
Go
//go:build darwin
|
|
// +build darwin
|
|
|
|
package darwin
|
|
|
|
/*
|
|
#cgo CFLAGS: -x objective-c
|
|
#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit
|
|
#import <Foundation/Foundation.h>
|
|
#import "Application.h"
|
|
#import "WailsContext.h"
|
|
*/
|
|
import "C"
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
"unsafe"
|
|
|
|
"github.com/leaanthony/slicer"
|
|
"github.com/wailsapp/wails/v2/internal/frontend"
|
|
)
|
|
|
|
// Obj-C dialog methods send the response to this channel
|
|
var messageDialogResponse = make(chan int)
|
|
var openFileDialogResponse = make(chan string)
|
|
var saveFileDialogResponse = make(chan string)
|
|
var dialogLock sync.Mutex
|
|
|
|
// OpenDirectoryDialog prompts the user to select a directory
|
|
func (f *Frontend) OpenDirectoryDialog(options frontend.OpenDialogOptions) (string, error) {
|
|
results, err := f.openDialog(&options, false, false, true)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var selected string
|
|
if len(results) > 0 {
|
|
selected = results[0]
|
|
}
|
|
return selected, nil
|
|
}
|
|
|
|
func (f *Frontend) openDialog(options *frontend.OpenDialogOptions, multiple bool, allowfiles bool, allowdirectories bool) ([]string, error) {
|
|
dialogLock.Lock()
|
|
defer dialogLock.Unlock()
|
|
|
|
c := NewCalloc()
|
|
defer c.Free()
|
|
title := c.String(options.Title)
|
|
defaultFilename := c.String(options.DefaultFilename)
|
|
defaultDirectory := c.String(options.DefaultDirectory)
|
|
allowDirectories := bool2Cint(allowdirectories)
|
|
allowFiles := bool2Cint(allowfiles)
|
|
canCreateDirectories := bool2Cint(options.CanCreateDirectories)
|
|
treatPackagesAsDirectories := bool2Cint(options.TreatPackagesAsDirectories)
|
|
resolveAliases := bool2Cint(options.ResolvesAliases)
|
|
showHiddenFiles := bool2Cint(options.ShowHiddenFiles)
|
|
allowMultipleFileSelection := bool2Cint(multiple)
|
|
|
|
var filterStrings slicer.StringSlicer
|
|
if options.Filters != nil {
|
|
for _, filter := range options.Filters {
|
|
thesePatterns := strings.Split(filter.Pattern, ";")
|
|
for _, pattern := range thesePatterns {
|
|
pattern = strings.TrimSpace(pattern)
|
|
if pattern != "" {
|
|
filterStrings.Add(pattern)
|
|
}
|
|
}
|
|
}
|
|
filterStrings.Deduplicate()
|
|
}
|
|
filters := filterStrings.Join(";")
|
|
C.OpenFileDialog(f.mainWindow.context, title, defaultFilename, defaultDirectory, allowDirectories, allowFiles, canCreateDirectories, treatPackagesAsDirectories, resolveAliases, showHiddenFiles, allowMultipleFileSelection, c.String(filters))
|
|
|
|
var result = <-openFileDialogResponse
|
|
|
|
var parsedResults []string
|
|
err := json.Unmarshal([]byte(result), &parsedResults)
|
|
|
|
return parsedResults, err
|
|
}
|
|
|
|
// OpenFileDialog prompts the user to select a file
|
|
func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, error) {
|
|
results, err := f.openDialog(&options, false, true, false)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var selected string
|
|
if len(results) > 0 {
|
|
selected = results[0]
|
|
}
|
|
return selected, nil
|
|
}
|
|
|
|
// OpenMultipleFilesDialog prompts the user to select a file
|
|
func (f *Frontend) OpenMultipleFilesDialog(options frontend.OpenDialogOptions) ([]string, error) {
|
|
return f.openDialog(&options, true, true, false)
|
|
}
|
|
|
|
// SaveFileDialog prompts the user to select a file
|
|
func (f *Frontend) SaveFileDialog(options frontend.SaveDialogOptions) (string, error) {
|
|
dialogLock.Lock()
|
|
defer dialogLock.Unlock()
|
|
|
|
c := NewCalloc()
|
|
defer c.Free()
|
|
title := c.String(options.Title)
|
|
defaultFilename := c.String(options.DefaultFilename)
|
|
defaultDirectory := c.String(options.DefaultDirectory)
|
|
canCreateDirectories := bool2Cint(options.CanCreateDirectories)
|
|
treatPackagesAsDirectories := bool2Cint(options.TreatPackagesAsDirectories)
|
|
showHiddenFiles := bool2Cint(options.ShowHiddenFiles)
|
|
|
|
var filterStrings slicer.StringSlicer
|
|
if options.Filters != nil {
|
|
for _, filter := range options.Filters {
|
|
thesePatterns := strings.Split(filter.Pattern, ";")
|
|
for _, pattern := range thesePatterns {
|
|
pattern = strings.TrimSpace(pattern)
|
|
if pattern != "" {
|
|
filterStrings.Add(pattern)
|
|
}
|
|
}
|
|
}
|
|
filterStrings.Deduplicate()
|
|
}
|
|
filters := filterStrings.Join(";")
|
|
C.SaveFileDialog(f.mainWindow.context, title, defaultFilename, defaultDirectory, canCreateDirectories, treatPackagesAsDirectories, showHiddenFiles, c.String(filters))
|
|
|
|
var result = <-saveFileDialogResponse
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// MessageDialog show a message dialog to the user
|
|
func (f *Frontend) MessageDialog(options frontend.MessageDialogOptions) (string, error) {
|
|
dialogLock.Lock()
|
|
defer dialogLock.Unlock()
|
|
|
|
c := NewCalloc()
|
|
defer c.Free()
|
|
dialogType := c.String(string(options.Type))
|
|
title := c.String(options.Title)
|
|
message := c.String(options.Message)
|
|
defaultButton := c.String(options.DefaultButton)
|
|
cancelButton := c.String(options.CancelButton)
|
|
const MaxButtons = 4
|
|
var buttons [MaxButtons]*C.char
|
|
for index, buttonText := range options.Buttons {
|
|
if index == MaxButtons {
|
|
return "", fmt.Errorf("max %d buttons supported (%d given)", MaxButtons, len(options.Buttons))
|
|
}
|
|
buttons[index] = c.String(buttonText)
|
|
}
|
|
|
|
var iconData unsafe.Pointer
|
|
var iconDataLength C.int
|
|
if options.Icon != nil {
|
|
iconData = unsafe.Pointer(&options.Icon[0])
|
|
iconDataLength = C.int(len(options.Icon))
|
|
}
|
|
|
|
C.MessageDialog(f.mainWindow.context, dialogType, title, message, buttons[0], buttons[1], buttons[2], buttons[3], defaultButton, cancelButton, iconData, iconDataLength)
|
|
|
|
var result = <-messageDialogResponse
|
|
|
|
selectedC := buttons[result]
|
|
var selected string
|
|
if selectedC != nil {
|
|
selected = options.Buttons[result]
|
|
}
|
|
return selected, nil
|
|
}
|
|
|
|
//export processMessageDialogResponse
|
|
func processMessageDialogResponse(selection int) {
|
|
messageDialogResponse <- selection
|
|
}
|
|
|
|
//export processOpenFileDialogResponse
|
|
func processOpenFileDialogResponse(cselection *C.char) {
|
|
selection := C.GoString(cselection)
|
|
openFileDialogResponse <- selection
|
|
}
|
|
|
|
//export processSaveFileDialogResponse
|
|
func processSaveFileDialogResponse(cselection *C.char) {
|
|
selection := C.GoString(cselection)
|
|
saveFileDialogResponse <- selection
|
|
}
|