[v3] send dialog results over channels

This commit is contained in:
Travis McLane 2023-09-29 23:54:57 -05:00
commit 757a4383e6
5 changed files with 88 additions and 58 deletions

View file

@ -1,6 +1,7 @@
package application
import (
"fmt"
"strings"
"sync"
)
@ -159,7 +160,7 @@ func (d *MessageDialog) SetMessage(message string) *MessageDialog {
}
type openFileDialogImpl interface {
show() ([]string, error)
show() (chan string, error)
}
type FileFilter struct {
@ -265,10 +266,11 @@ func (d *OpenFileDialogStruct) PromptForSingleSelection() (string, error) {
if d.impl == nil {
d.impl = newOpenFileDialogImpl(d)
}
selection, err := InvokeSyncWithResultAndError(d.impl.show)
var result string
if len(selection) > 0 {
result = selection[0]
selections, err := InvokeSyncWithResultAndError(d.impl.show)
if err == nil {
result = <-selections
}
return result, err
@ -289,7 +291,17 @@ func (d *OpenFileDialogStruct) PromptForMultipleSelection() ([]string, error) {
if d.impl == nil {
d.impl = newOpenFileDialogImpl(d)
}
return InvokeSyncWithResultAndError(d.impl.show)
selections, err := InvokeSyncWithResultAndError(d.impl.show)
var result []string
fmt.Println("Waiting for results:")
for filename := range selections {
fmt.Println(filename)
result = append(result, filename)
}
return result, err
}
func (d *OpenFileDialogStruct) SetMessage(message string) *OpenFileDialogStruct {
@ -385,7 +397,7 @@ type SaveFileDialogStruct struct {
}
type saveFileDialogImpl interface {
show() (string, error)
show() (chan string, error)
}
func (d *SaveFileDialogStruct) SetOptions(options *SaveFileDialogOptions) {
@ -448,7 +460,13 @@ func (d *SaveFileDialogStruct) PromptForSingleSelection() (string, error) {
if d.impl == nil {
d.impl = newSaveFileDialogImpl(d)
}
return InvokeSyncWithResultAndError(d.impl.show)
var result string
selections, err := InvokeSyncWithResultAndError(d.impl.show)
if err == nil {
result = <-selections
}
return result, err
}
func (d *SaveFileDialogStruct) SetButtonText(text string) *SaveFileDialogStruct {

View file

@ -18,7 +18,7 @@ extern void saveFileDialogCallback(uint id, char* path);
static void showAboutBox(char* title, char *message, void *icon, int length) {
// run on main thread
dispatch_async(dispatch_get_main_queue(), ^{
// dispatch_async(dispatch_get_main_queue(), ^{
NSAlert *alert = [[NSAlert alloc] init];
if (title != NULL) {
[alert setMessageText:[NSString stringWithUTF8String:title]];
@ -34,7 +34,7 @@ static void showAboutBox(char* title, char *message, void *icon, int length) {
}
[alert setAlertStyle:NSAlertStyleInformational];
[alert runModal];
});
// });
}
@ -163,7 +163,7 @@ static void showOpenFileDialog(unsigned int dialogID,
void *window) {
// run on main thread
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSOpenPanel *panel = [NSOpenPanel openPanel];
@ -229,7 +229,7 @@ static void showOpenFileDialog(unsigned int dialogID,
processOpenFileDialogResults(panel, result, dialogID);
}];
}
});
});
}
static void showSaveFileDialog(unsigned int dialogID,
@ -246,7 +246,7 @@ static void showSaveFileDialog(unsigned int dialogID,
void *window) {
// run on main thread
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSSavePanel *panel = [NSSavePanel savePanel];
if (message != NULL) {
@ -280,8 +280,8 @@ static void showSaveFileDialog(unsigned int dialogID,
[panel beginSheetModalForWindow:(__bridge NSWindow *)window completionHandler:^(NSInteger result) {
const char *path = NULL;
if (result == NSModalResponseOK) {
NSURL *url = [panel URL];
const char *path = [[url path] UTF8String];
NSURL *url = [panel URL];
path = [[url path] UTF8String];
}
saveFileDialogCallback(dialogID, (char *)path);
}];
@ -290,12 +290,12 @@ static void showSaveFileDialog(unsigned int dialogID,
const char *path = NULL;
if (result == NSModalResponseOK) {
NSURL *url = [panel URL];
const char *path = [[url path] UTF8String];
path = [[url path] UTF8String];
}
saveFileDialogCallback(dialogID, (char *)path);
}];
}
});
});
}
*/
@ -321,7 +321,9 @@ func (m *macosApp) showAboutDialog(title string, message string, icon []byte) {
if icon != nil {
iconData = unsafe.Pointer(&icon[0])
}
C.showAboutBox(C.CString(title), C.CString(message), iconData, C.int(len(icon)))
InvokeAsync(func() {
C.showAboutBox(C.CString(title), C.CString(message), iconData, C.int(len(icon)))
})
}
type macosDialog struct {
@ -331,7 +333,7 @@ type macosDialog struct {
}
func (m *macosDialog) show() {
globalApplication.dispatchOnMainThread(func() {
InvokeAsync(func() {
// Mac can only have 4 Buttons on a dialog
if len(m.dialog.Buttons) > 4 {
@ -419,7 +421,7 @@ func toCString(s string) *C.char {
return C.CString(s)
}
func (m *macosOpenFileDialog) show() ([]string, error) {
func (m *macosOpenFileDialog) show() (chan string, error) {
openFileResponses[m.dialog.id] = make(chan string)
nsWindow := unsafe.Pointer(nil)
if m.dialog.window != nil {
@ -445,7 +447,6 @@ func (m *macosOpenFileDialog) show() ([]string, error) {
}
filterPatterns = strings.Join(allPatterns, ";")
}
C.showOpenFileDialog(C.uint(m.dialog.id),
C.bool(m.dialog.canChooseFiles),
C.bool(m.dialog.canChooseDirectories),
@ -462,11 +463,8 @@ func (m *macosOpenFileDialog) show() ([]string, error) {
toCString(m.dialog.directory),
toCString(m.dialog.buttonText),
nsWindow)
var result []string
for filename := range openFileResponses[m.dialog.id] {
result = append(result, filename)
}
return result, nil
return openFileResponses[m.dialog.id], nil
}
//export openFileDialogCallback
@ -504,7 +502,7 @@ func newSaveFileDialogImpl(d *SaveFileDialogStruct) *macosSaveFileDialog {
}
}
func (m *macosSaveFileDialog) show() (string, error) {
func (m *macosSaveFileDialog) show() (chan string, error) {
saveFileResponses[m.dialog.id] = make(chan string)
nsWindow := unsafe.Pointer(nil)
if m.dialog.window != nil {
@ -524,7 +522,7 @@ func (m *macosSaveFileDialog) show() (string, error) {
toCString(m.dialog.buttonText),
toCString(m.dialog.filename),
nsWindow)
return <-saveFileResponses[m.dialog.id], nil
return saveFileResponses[m.dialog.id], nil
}
//export saveFileDialogCallback

View file

@ -53,7 +53,7 @@ func newOpenFileDialogImpl(d *OpenFileDialogStruct) *linuxOpenFileDialog {
}
}
func (m *linuxOpenFileDialog) show() ([]string, error) {
func (m *linuxOpenFileDialog) show() (chan string, error) {
return runOpenFileDialog(m.dialog)
}
@ -67,6 +67,6 @@ func newSaveFileDialogImpl(d *SaveFileDialogStruct) *linuxSaveFileDialog {
}
}
func (m *linuxSaveFileDialog) show() (string, error) {
func (m *linuxSaveFileDialog) show() (chan string, error) {
return runSaveFileDialog(m.dialog)
}

View file

@ -91,7 +91,7 @@ func getDefaultFolder(folder string) (string, error) {
return filepath.Abs(folder)
}
func (m *windowOpenFileDialog) show() ([]string, error) {
func (m *windowOpenFileDialog) show() (chan string, error) {
defaultFolder, err := getDefaultFolder(m.dialog.directory)
if err != nil {
@ -133,7 +133,14 @@ func (m *windowOpenFileDialog) show() ([]string, error) {
result = []string{temp.(string)}
}
return result, nil
files := make(chan string)
go func() {
for _, file := range result {
files <- file
}
close(files)
}()
return files, nil
}
type windowSaveFileDialog struct {
@ -146,10 +153,12 @@ func newSaveFileDialogImpl(d *SaveFileDialogStruct) *windowSaveFileDialog {
}
}
func (m *windowSaveFileDialog) show() (string, error) {
func (m *windowSaveFileDialog) show() (chan string, error) {
files := make(chan string)
defaultFolder, err := getDefaultFolder(m.dialog.directory)
if err != nil {
return "", err
close(files)
return files, err
}
config := cfd.DialogConfig{
@ -164,7 +173,11 @@ func (m *windowSaveFileDialog) show() (string, error) {
func() (cfd.Dialog, error) {
return cfd.NewSaveFileDialog(config)
}, false)
return result.(string), nil
go func() {
files <- result.(string)
close(files)
}()
return files, err
}
func calculateMessageDialogFlags(options MessageDialogOptions) uint32 {

View file

@ -973,7 +973,7 @@ func messageDialogCB(button C.int) {
}
func runChooserDialog(window pointer, allowMultiple, createFolders, showHidden bool, currentFolder, title string, action int, acceptLabel string, filters []FileFilter) ([]string, error) {
func runChooserDialog(window pointer, allowMultiple, createFolders, showHidden bool, currentFolder, title string, action int, acceptLabel string, filters []FileFilter) (chan string, error) {
titleStr := C.CString(title)
defer C.free(unsafe.Pointer(titleStr))
cancelStr := C.CString("_Cancel")
@ -1036,27 +1036,32 @@ func runChooserDialog(window pointer, allowMultiple, createFolders, showHidden b
return string(bytes)
}
response := C.gtk_dialog_run((*C.GtkDialog)(fc))
selections := []string{}
if response == C.GTK_RESPONSE_ACCEPT {
filenames := C.gtk_file_chooser_get_filenames((*C.GtkFileChooser)(fc))
iter := filenames
count := 0
for {
selections = append(selections, buildStringAndFree(C.gpointer(iter.data)))
iter = iter.next
if iter == nil || count == 1024 {
break
selections := make(chan string)
// run this on the gtk thread
InvokeAsync(func() {
go func() {
response := C.gtk_dialog_run((*C.GtkDialog)(fc))
if response == C.GTK_RESPONSE_ACCEPT {
filenames := C.gtk_file_chooser_get_filenames((*C.GtkFileChooser)(fc))
iter := filenames
count := 0
for {
selections <- buildStringAndFree(C.gpointer(iter.data))
iter = iter.next
if iter == nil || count == 1024 {
break
}
count++
}
close(selections)
C.gtk_widget_destroy((*C.GtkWidget)(unsafe.Pointer(fc)))
}
count++
}
}
defer C.gtk_widget_destroy((*C.GtkWidget)(unsafe.Pointer(fc)))
}()
})
return selections, nil
}
func runOpenFileDialog(dialog *OpenFileDialogStruct) ([]string, error) {
func runOpenFileDialog(dialog *OpenFileDialogStruct) (chan string, error) {
const GtkFileChooserActionOpen = C.GTK_FILE_CHOOSER_ACTION_OPEN
window := nilPointer
@ -1145,7 +1150,7 @@ func runQuestionDialog(parent pointer, options *MessageDialog) int {
return int(C.gtk_dialog_run((*C.GtkDialog)(unsafe.Pointer(dialog))))
}
func runSaveFileDialog(dialog *SaveFileDialogStruct) (string, error) {
func runSaveFileDialog(dialog *SaveFileDialogStruct) (chan string, error) {
window := nilPointer
buttonText := dialog.buttonText
if buttonText == "" {
@ -1162,11 +1167,7 @@ func runSaveFileDialog(dialog *SaveFileDialogStruct) (string, error) {
buttonText,
dialog.filters)
if err != nil || len(results) == 0 {
return "", err
}
return results[0], nil
return results, err
}
// systray