| @@ -1,223 +0,0 @@ | |||||
| /* | |||||
| * DISTRHO Plugin Framework (DPF) | |||||
| * Copyright (C) 2012-2020 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 | |||||
| * permission notice appear in all copies. | |||||
| * | |||||
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
| * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||||
| * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||||
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||||
| * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||||
| * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||||
| */ | |||||
| #include "../StandaloneWindow.hpp" | |||||
| // static int fib_filter_filename_filter(const char* const name) | |||||
| // { | |||||
| // return 1; | |||||
| // (void)name; | |||||
| // } | |||||
| // TODO use DGL_NAMESPACE for class names | |||||
| #ifdef DISTRHO_OS_MAC | |||||
| @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 | |||||
| @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 | |||||
| #endif | |||||
| START_NAMESPACE_DGL | |||||
| // ----------------------------------------------------------------------- | |||||
| bool Window::openFileBrowser(const FileBrowserOptions& options) | |||||
| { | |||||
| #if defined(DISTRHO_OS_WINDOWS) | |||||
| // the old and compatible dialog API | |||||
| OPENFILENAMEW ofn; | |||||
| memset(&ofn, 0, sizeof(ofn)); | |||||
| ofn.lStructSize = sizeof(ofn); | |||||
| ofn.hwndOwner = pData->hwnd; | |||||
| // set initial directory in UTF-16 coding | |||||
| std::vector<WCHAR> startDirW; | |||||
| if (options.startDir) | |||||
| { | |||||
| startDirW.resize(strlen(options.startDir) + 1); | |||||
| if (MultiByteToWideChar(CP_UTF8, 0, options.startDir, -1, startDirW.data(), startDirW.size())) | |||||
| ofn.lpstrInitialDir = startDirW.data(); | |||||
| } | |||||
| // set title in UTF-16 coding | |||||
| std::vector<WCHAR> titleW; | |||||
| if (options.title) | |||||
| { | |||||
| titleW.resize(strlen(options.title) + 1); | |||||
| if (MultiByteToWideChar(CP_UTF8, 0, options.title, -1, titleW.data(), titleW.size())) | |||||
| ofn.lpstrTitle = titleW.data(); | |||||
| } | |||||
| // prepare a buffer to receive the result | |||||
| std::vector<WCHAR> fileNameW(32768); // the Unicode maximum | |||||
| ofn.lpstrFile = fileNameW.data(); | |||||
| ofn.nMaxFile = (DWORD)fileNameW.size(); | |||||
| // TODO synchronous only, can't do better with WinAPI native dialogs. | |||||
| // threading might work, if someone is motivated to risk it. | |||||
| if (GetOpenFileNameW(&ofn)) | |||||
| { | |||||
| // back to UTF-8 | |||||
| std::vector<char> fileNameA(4 * 32768); | |||||
| if (WideCharToMultiByte(CP_UTF8, 0, fileNameW.data(), -1, fileNameA.data(), (int)fileNameA.size(), nullptr, nullptr)) | |||||
| { | |||||
| // handle it during the next idle cycle (fake async) | |||||
| pData->fSelectedFile = fileNameA.data(); | |||||
| } | |||||
| } | |||||
| 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; | |||||
| #elif defined(SOFD_HAVE_X11) | |||||
| using DISTRHO_NAMESPACE::String; | |||||
| // -------------------------------------------------------------------------- | |||||
| // configure start dir | |||||
| // TODO: get abspath if needed | |||||
| // TODO: cross-platform | |||||
| String startDir(options.startDir); | |||||
| # ifdef DISTRHO_OS_LINUX | |||||
| if (startDir.isEmpty()) | |||||
| { | |||||
| if (char* const dir_name = get_current_dir_name()) | |||||
| { | |||||
| startDir = dir_name; | |||||
| std::free(dir_name); | |||||
| } | |||||
| } | |||||
| # endif | |||||
| DISTRHO_SAFE_ASSERT_RETURN(startDir.isNotEmpty(), false); | |||||
| if (! startDir.endsWith('/')) | |||||
| startDir += "/"; | |||||
| DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(0, startDir) == 0, false); | |||||
| // -------------------------------------------------------------------------- | |||||
| // configure title | |||||
| String title(options.title); | |||||
| if (title.isEmpty()) | |||||
| { | |||||
| title = pData->getTitle(); | |||||
| if (title.isEmpty()) | |||||
| title = "FileBrowser"; | |||||
| } | |||||
| DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(1, title) == 0, false); | |||||
| // -------------------------------------------------------------------------- | |||||
| // configure filters | |||||
| x_fib_cfg_filter_callback(nullptr); //fib_filter_filename_filter); | |||||
| // -------------------------------------------------------------------------- | |||||
| // configure buttons | |||||
| x_fib_cfg_buttons(3, options.buttons.listAllFiles-1); | |||||
| x_fib_cfg_buttons(1, options.buttons.showHidden-1); | |||||
| x_fib_cfg_buttons(2, options.buttons.showPlaces-1); | |||||
| // -------------------------------------------------------------------------- | |||||
| // show | |||||
| return (x_fib_show(pData->xDisplay, pData->xWindow, /*options.width*/0, /*options.height*/0) == 0); | |||||
| #else | |||||
| // not implemented | |||||
| return false; | |||||
| // unused | |||||
| (void)options; | |||||
| #endif | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| END_NAMESPACE_DGL | |||||