commit 5dff90ad277abb857db274fff5fbe84dd6489b6a
parent 1ae79e9a5303ec6873ecc26a0834d5a1017ecee6
Author: JP Cimalando <jp-dev@inbox.ru>
Date: Thu, 1 Aug 2019 02:59:50 +0200
add file dialog for macOS (#161)
* add file dialog for macOS
* mac: use the 10.6 setDirectory API
* mac: rewrite file dialog without a for-each loop
* some minor style changes
* mac: use file dialog compatibility API, not using blocks
* add some copyright notices
Diffstat:
M | dgl/src/Window.cpp | | | 141 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 141 insertions(+), 0 deletions(-)
diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp
@@ -1,6 +1,8 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
+ * Copyright (C) 2019 Jean Pierre Cimalando <jp-dev@inbox.ru>
+ * Copyright (C) 2019 Robin Gareus <robin@gareus.org>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -105,6 +107,10 @@ struct Window::PrivateData {
mView(nullptr),
mWindow(nullptr),
mParentWindow(nullptr)
+# ifndef DGL_FILE_BROWSER_DISABLED
+ , fOpenFilePanel(nullptr),
+ fFilePanelDelegate(nullptr)
+# endif
#else
xDisplay(nullptr),
xWindow(0)
@@ -137,6 +143,10 @@ struct Window::PrivateData {
mView(nullptr),
mWindow(nullptr),
mParentWindow(nullptr)
+# ifndef DGL_FILE_BROWSER_DISABLED
+ , fOpenFilePanel(nullptr),
+ fFilePanelDelegate(nullptr)
+# endif
#else
xDisplay(nullptr),
xWindow(0)
@@ -181,6 +191,10 @@ struct Window::PrivateData {
mView(nullptr),
mWindow(nullptr),
mParentWindow(nullptr)
+# ifndef DGL_FILE_BROWSER_DISABLED
+ , fOpenFilePanel(nullptr),
+ fFilePanelDelegate(nullptr)
+# endif
#else
xDisplay(nullptr),
xWindow(0)
@@ -323,6 +337,19 @@ struct Window::PrivateData {
xWindow = 0;
#endif
+#if defined(DISTRHO_OS_MAC) && !defined(DGL_FILE_BROWSER_DISABLED)
+ if (fOpenFilePanel)
+ {
+ [fOpenFilePanel release];
+ fOpenFilePanel = nullptr;
+ }
+ if (fFilePanelDelegate)
+ {
+ [fFilePanelDelegate release];
+ fFilePanelDelegate = nullptr;
+ }
+#endif
+
DBG("Success!\n");
}
@@ -1062,6 +1089,39 @@ struct Window::PrivateData {
return false;
}
+#if defined(DISTRHO_OS_MAC) && !defined(DGL_FILE_BROWSER_DISABLED)
+ static void openPanelDidEnd(NSOpenPanel* panel, int returnCode, void *userData)
+ {
+ PrivateData* pData = (PrivateData*)userData;
+
+ if (returnCode == NSOKButton)
+ {
+ NSArray* urls = [panel URLs];
+ NSURL* fileUrl = nullptr;
+
+ for (NSUInteger i = 0, n = [urls count]; i < n && !fileUrl; ++i)
+ {
+ NSURL* url = (NSURL*)[urls objectAtIndex:i];
+ if ([url isFileURL])
+ fileUrl = url;
+ }
+
+ if (fileUrl)
+ {
+ PuglView* view = pData->fView;
+ if (view->fileSelectedFunc)
+ {
+ const char* fileName = [fileUrl.path UTF8String];
+ view->fileSelectedFunc(view, fileName);
+ }
+ }
+ }
+
+ [pData->fOpenFilePanel release];
+ pData->fOpenFilePanel = nullptr;
+ }
+#endif
+
// -------------------------------------------------------------------
Application& fApp;
@@ -1115,6 +1175,10 @@ struct Window::PrivateData {
NSView<PuglGenericView>* mView;
id mWindow;
id mParentWindow;
+# ifndef DGL_FILE_BROWSER_DISABLED
+ NSOpenPanel* fOpenFilePanel;
+ id fFilePanelDelegate;
+# endif
#else
Display* xDisplay;
::Window xWindow;
@@ -1231,6 +1295,20 @@ void Window::repaint() noexcept
// }
#ifndef DGL_FILE_BROWSER_DISABLED
+
+#ifdef DISTRHO_OS_MAC
+END_NAMESPACE_DGL
+@interface FilePanelDelegate : NSObject
+{
+ void (*fCallback)(NSOpenPanel*, int, void*);
+ void* fUserData;
+}
+-(id)initWithCallback:(void(*)(NSOpenPanel*, int, void*))callback userData:(void*)userData;
+-(void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
+@end
+START_NAMESPACE_DGL
+#endif
+
bool Window::openFileBrowser(const FileBrowserOptions& options)
{
# ifdef SOFD_HAVE_X11
@@ -1338,6 +1416,48 @@ bool Window::openFileBrowser(const FileBrowserOptions& options)
}
return true;
+# elif defined(DISTRHO_OS_MAC)
+ if (pData->fOpenFilePanel) // permit one dialog at most
+ {
+ [pData->fOpenFilePanel makeKeyAndOrderFront:nil];
+ return false;
+ }
+
+ NSOpenPanel* panel = [NSOpenPanel openPanel];
+ pData->fOpenFilePanel = [panel retain];
+
+ [panel setCanChooseFiles:YES];
+ [panel setCanChooseDirectories:NO];
+ [panel setAllowsMultipleSelection:NO];
+
+ if (options.startDir)
+ [panel setDirectory:[NSString stringWithUTF8String:options.startDir]];
+
+ if (options.title)
+ {
+ NSString* titleString = [[NSString alloc]
+ initWithBytes:options.title
+ length:strlen(options.title)
+ encoding:NSUTF8StringEncoding];
+ [panel setTitle:titleString];
+ }
+
+ id delegate = pData->fFilePanelDelegate;
+ if (!delegate)
+ {
+ delegate = [[FilePanelDelegate alloc] initWithCallback:&PrivateData::openPanelDidEnd
+ userData:pData];
+ pData->fFilePanelDelegate = [delegate retain];
+ }
+
+ [panel beginSheetForDirectory:nullptr
+ file:nullptr
+ modalForWindow:nullptr
+ modalDelegate:delegate
+ didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
+ contextInfo:nullptr];
+
+ return true;
# else
// not implemented
return false;
@@ -1346,8 +1466,29 @@ bool Window::openFileBrowser(const FileBrowserOptions& options)
(void)options;
# endif
}
+
+#ifdef DISTRHO_OS_MAC
+END_NAMESPACE_DGL
+@implementation FilePanelDelegate
+-(id)initWithCallback:(void(*)(NSOpenPanel*, int, void*))callback userData:(void *)userData
+{
+ [super init];
+ self->fCallback = callback;
+ self->fUserData = userData;
+ return self;
+}
+
+-(void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
+{
+ self->fCallback(sheet, returnCode, self->fUserData);
+ (void)contextInfo;
+}
+@end
+START_NAMESPACE_DGL
#endif
+#endif // !defined(DGL_FILE_BROWSER_DISABLED)
+
bool Window::isEmbed() const noexcept
{
return pData->fUsingEmbed;