From b1e8f2f88716e2210be92ba459e215a9fe9fdf4a Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 18 Dec 2022 23:06:31 +1100 Subject: [PATCH] Start of file dialogs --- exp/examples/dialogs/main.go | 57 ++++++++++++++ exp/examples/kitchensink/icon.png | Bin 1622 -> 0 bytes exp/examples/kitchensink/macos_icon.png | Bin 1212 -> 0 bytes exp/examples/kitchensink/main.go | 14 +--- exp/pkg/application/application.go | 26 ++++--- exp/pkg/application/dialogs.go | 96 ++++++++++++++++++++---- exp/pkg/application/dialogs_darwin.go | 94 ++++++++++++++++++++++- 7 files changed, 252 insertions(+), 35 deletions(-) delete mode 100644 exp/examples/kitchensink/icon.png delete mode 100644 exp/examples/kitchensink/macos_icon.png diff --git a/exp/examples/dialogs/main.go b/exp/examples/dialogs/main.go index f976f014f..1f1a8361b 100644 --- a/exp/examples/dialogs/main.go +++ b/exp/examples/dialogs/main.go @@ -135,6 +135,63 @@ func main() { dialog.Show() }) + openMenu := menu.AddSubmenu("Open") + openMenu.Add("Open File").OnClick(func(ctx *application.Context) { + result, _ := app.NewOpenFileDialog(). + CanChooseFiles(true). + Show() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } else { + app.NewInfoDialog().SetMessage("No file selected").Show() + } + }) + openMenu.Add("Open File (Show Hidden Files)").OnClick(func(ctx *application.Context) { + result, _ := app.NewOpenFileDialog(). + CanChooseFiles(true). + CanCreateDirectories(true). + ShowHiddenFiles(true). + Show() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } else { + app.NewInfoDialog().SetMessage("No file selected").Show() + } + }) + //openMenu.Add("Open Multiple Files (Show Hidden Files)").OnClick(func(ctx *application.Context) { + // result, _ := app.NewOpenMultipleFilesDialog(). + // CanChooseFiles(true). + // CanCreateDirectories(true). + // ShowHiddenFiles(true). + // Show() + // if len(result) > 0 { + // app.NewInfoDialog().SetMessage(strings.Join(result, ",")).Show() + // } else { + // app.NewInfoDialog().SetMessage("No file selected").Show() + // } + //}) + openMenu.Add("Open Directory").OnClick(func(ctx *application.Context) { + result, _ := app.NewOpenFileDialog(). + CanChooseDirectories(true). + Show() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } else { + app.NewInfoDialog().SetMessage("No directory selected").Show() + } + }) + openMenu.Add("Open Directory (Create Directories)").OnClick(func(ctx *application.Context) { + result, _ := app.NewOpenFileDialog(). + CanChooseDirectories(true). + CanCreateDirectories(true). + Show() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } else { + app.NewInfoDialog().SetMessage("No directory selected").Show() + } + }) + app.SetMenu(menu) app.NewWindow() diff --git a/exp/examples/kitchensink/icon.png b/exp/examples/kitchensink/icon.png deleted file mode 100644 index fc492c9167cce9c272f98bf99207d0efff1d1c1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1622 zcmV-c2C4apP)?9E5by_tm=H)BK!2&G8Wn%g z1REfMKm>jvR4h%YDEwl01TgZle?-$?nBFt(Ztk8lvpYj`ldheUe8TR%=j?p%mzjHK z?ykvXgb_v$>U*@FR5X( zImyGEK7E?h0m2M;^5luMy}j*{j*bpeS6Nv}@_1nR#x?iv-zRyPuC6Xp2M9CZ`+N6@ z2uyQxGpXzE?#axiS!mW{$10bvHTwY3o;n2L%Dr<#I-0+NHt&vQ25`t|E12Xp)O zZKBVPFavJgxrl#^2vxT3J~kIXpj2PO_&R<Ak5LDN9Ejvgap#3 zMpo9}2EZNT=H@2p=fSIt62c5Pd-g05go%oZl5<;ITS=c9Sy@?fjXQ(a*ViSR%|>)# zgc*>Uno2}rEEbEL`)cYH=~Ls}xpQ*O-Me>5AI}T6JYr2s2s0olDT#>UfeFgj*H69- za37#HCuC-3%6D}$Gc%-*r?9Y)Xi`F$0mqLYC!%=P*4E_7k9`*D1JqW9GiT07M~)mJ z?L6?=X0w@SQbL#khYuen!gv-I7UaC);bGGE?%g}7w6v7818~1^<;oS(&hzNeBcewQ zVFpA-MiOB>v$M1EB(<@zLHgi9>hk5wq#ek}$dH~seM;JS>=UIHgc-1J-##LYXKHFn zD!Futv;(J3rK_F+a0x6fE|PXTaAv`6HP)ksFazKkgozFdv@<$7Dm{DljI=K;ElGZU zeo|Rk8R-LV-n>cLcwlwFT3jK_0QfJsdbS4xV6wvP4(y?hhlYko8xK4mU@fi? zW&kWztE;O-pdB@H>^nYc6P;Qe@b>Ln$;ZcsXmN!w1AzDM-xHCp`0(L_6ciLB*IvDP zmGrvT0ICg zz!NYG*o^^fg8Bwtehvig=68aVlapVv>+er^>*=t$WQL8&Y|;~~U~fc3#IWg~pPPCp zvi9WU$x zvFrgX?%%(EA}uYgijBbnmoy%m=73^`A6!EWDJj4;9oBmQUc7aDot UG_K_hc>n+a07*qoM6N<$g0pSuE&u=k diff --git a/exp/examples/kitchensink/macos_icon.png b/exp/examples/kitchensink/macos_icon.png deleted file mode 100644 index 659d860e141b3bbf9139c9290f0fe57a78fbe3e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1212 zcmV;t1Vj6YP)#O?|gIZHH`tSTp#>6n{nBD>~F8L_Fi+YDN}m&>eZ`P zuU0EUm5EN^OOb3Qf0O>72n%PS(CCznS;45 zDZPie7#}IA4*7)`@1pd5T&m2#c%xF&G>msq>0e?t#HC1xdG3RHo99PThg|RbYDu60FOngUozP>yDE}aJo_nEZ z6{$hKk<2eX2{hmk83fr3Jr9x^WCQeUBQ?l#zQ;=f4cJcxK^}#kH%JYF1{@_d$ZFr? zC4mO)CW9cu!&x8CRDLEk$UUy-Lgg1y-}dC$0VMP1J%fd)KG212e*wYIkK1IaV)bg%I_$$LKe zXCf{MG++Z62w9P8uO+!0ccdQs#dwzFJrllVm?Y4ETggDk;Cb}#L6XZ+8!*b?Kb1uj zr#69-ht=20g(10t+V4jny?qibsUU{6vjrGct zB<^_~=gCO|4Om77^L#7Ss_Yq(vkR%mNZhztd7H#NgA-*NNuU9?XMlrw?8LW`#Elyz ze+1aSz$p^1IjPLVd2*6K18fIooD5j=sqzkqpH?nVHj$jMm&80raF!-XpaFJq({ycb z2H438tu;hvvF8DP@7pU99+ z{4Qy$O8-7Z@}oF}GmMf18(^OZ4%x(eu6HxZk796fRU!#C-~<`6iA}C|3&}U}l|tA3 znk2ynd_e}yaaLL4dY>jWP3-Zn-BuE8z%eptj$_cfmDJ=ISC;$!wvu22J|x5Dz$NlF ztGzX!`Q8#qumSIqVRNj6-Vy`0`rZ;rumNqBxsBtbx6PueVb>DFb4RHp*nl>BcE&-{ z`wXdLypO#ll3)W~CId6BBfV`6cm#V(B*6wePXyqrK9jUF;4SPcl>{5Giwuq2gncHB? +extern void openFileDialogCallback(uint id, char* path); +extern void openFileDialogCallbackEnd(uint id); + static void showAboutBox(char* title, char *message, void *icon, int length) { // run on main thread @@ -99,9 +102,46 @@ static void alertAddButton(void *dialog, char *label, bool isDefault, bool isCan } } +static void showOpenFileDialog(unsigned int dialogID, bool canChooseFiles, bool canChooseDirectories, bool canCreateDirectories, bool showHiddenFiles, bool allowsMultipleSelection) { + + // run on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + NSOpenPanel *panel = [NSOpenPanel openPanel]; + + [panel setCanChooseFiles:canChooseFiles]; + [panel setCanChooseDirectories:canChooseDirectories]; + [panel setCanCreateDirectories:canCreateDirectories]; + [panel setShowsHiddenFiles:showHiddenFiles]; + [panel setAllowsMultipleSelection:allowsMultipleSelection]; + + + // Show panel + [panel beginWithCompletionHandler:^(NSInteger result) { + const char *path = NULL; + if (result == NSModalResponseOK) { + if (allowsMultipleSelection) { + NSArray *urls = [panel URLs]; + for (NSURL *url in urls) { + path = [[url path] UTF8String]; + openFileDialogCallback(dialogID, (char *)path); + } + + } else { + NSURL *url = [panel URL]; + path = [[url path] UTF8String]; + openFileDialogCallback(dialogID, (char *)path); + } + } + openFileDialogCallbackEnd(dialogID); + }]; + }); +} + */ import "C" -import "unsafe" +import ( + "unsafe" +) const NSAlertStyleWarning = C.int(0) const NSAlertStyleInformational = C.int(1) @@ -123,7 +163,7 @@ func (m *macosApp) showAboutDialog(title string, message string, icon []byte) { } type macosDialog struct { - dialog *Dialog + dialog *MessageDialog nsDialog unsafe.Pointer } @@ -188,8 +228,56 @@ func (m *macosDialog) show() { } -func newDialogImpl(d *Dialog) *macosDialog { +func newDialogImpl(d *MessageDialog) *macosDialog { return &macosDialog{ dialog: d, } } + +type macosOpenFileDialog struct { + dialog *OpenFileDialog +} + +func newOpenFileDialogImpl(d *OpenFileDialog) *macosOpenFileDialog { + return &macosOpenFileDialog{ + dialog: d, + } +} + +func (m *macosOpenFileDialog) show() ([]string, error) { + openFileResponses[dialogID] = make(chan string) + C.showOpenFileDialog(C.uint(m.dialog.id), + C.bool(m.dialog.canChooseFiles), + C.bool(m.dialog.canChooseDirectories), + C.bool(m.dialog.canCreateDirectories), + C.bool(m.dialog.showHiddenFiles), + C.bool(m.dialog.allowsMultipleSelection)) + var result []string + for filename := range openFileResponses[m.dialog.id] { + result = append(result, filename) + } + return result, nil +} + +//export openFileDialogCallback +func openFileDialogCallback(id C.uint, path *C.char) { + // Covert the path to a string + filePath := C.GoString(path) + // put response on channel + channel, ok := openFileResponses[uint(id)] + if ok { + channel <- filePath + } else { + panic("No channel found for open file dialog") + } +} + +//export openFileDialogCallbackEnd +func openFileDialogCallbackEnd(id C.uint) { + channel, ok := openFileResponses[uint(id)] + if ok { + close(channel) + } else { + panic("No channel found for open file dialog") + } +}