DISTRHO Plugin Framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

224 lines
6.7KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com>
  4. * Copyright (C) 2019 Jean Pierre Cimalando <jp-dev@inbox.ru>
  5. * Copyright (C) 2019 Robin Gareus <robin@gareus.org>
  6. *
  7. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  8. * or without fee is hereby granted, provided that the above copyright notice and this
  9. * permission notice appear in all copies.
  10. *
  11. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  12. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  13. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  14. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  15. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  16. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include "../StandaloneWindow.hpp"
  19. // static int fib_filter_filename_filter(const char* const name)
  20. // {
  21. // return 1;
  22. // (void)name;
  23. // }
  24. // TODO use DGL_NAMESPACE for class names
  25. #ifdef DISTRHO_OS_MAC
  26. @interface FilePanelDelegate : NSObject
  27. {
  28. void (*fCallback)(NSOpenPanel*, int, void*);
  29. void* fUserData;
  30. }
  31. -(id)initWithCallback:(void(*)(NSOpenPanel*, int, void*))callback userData:(void*)userData;
  32. -(void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
  33. @end
  34. @implementation FilePanelDelegate
  35. -(id)initWithCallback:(void(*)(NSOpenPanel*, int, void*))callback userData:(void *)userData
  36. {
  37. [super init];
  38. self->fCallback = callback;
  39. self->fUserData = userData;
  40. return self;
  41. }
  42. -(void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
  43. {
  44. self->fCallback(sheet, returnCode, self->fUserData);
  45. (void)contextInfo;
  46. }
  47. @end
  48. #endif
  49. START_NAMESPACE_DGL
  50. // -----------------------------------------------------------------------
  51. bool Window::openFileBrowser(const FileBrowserOptions& options)
  52. {
  53. #if defined(DISTRHO_OS_WINDOWS)
  54. // the old and compatible dialog API
  55. OPENFILENAMEW ofn;
  56. memset(&ofn, 0, sizeof(ofn));
  57. ofn.lStructSize = sizeof(ofn);
  58. ofn.hwndOwner = pData->hwnd;
  59. // set initial directory in UTF-16 coding
  60. std::vector<WCHAR> startDirW;
  61. if (options.startDir)
  62. {
  63. startDirW.resize(strlen(options.startDir) + 1);
  64. if (MultiByteToWideChar(CP_UTF8, 0, options.startDir, -1, startDirW.data(), startDirW.size()))
  65. ofn.lpstrInitialDir = startDirW.data();
  66. }
  67. // set title in UTF-16 coding
  68. std::vector<WCHAR> titleW;
  69. if (options.title)
  70. {
  71. titleW.resize(strlen(options.title) + 1);
  72. if (MultiByteToWideChar(CP_UTF8, 0, options.title, -1, titleW.data(), titleW.size()))
  73. ofn.lpstrTitle = titleW.data();
  74. }
  75. // prepare a buffer to receive the result
  76. std::vector<WCHAR> fileNameW(32768); // the Unicode maximum
  77. ofn.lpstrFile = fileNameW.data();
  78. ofn.nMaxFile = (DWORD)fileNameW.size();
  79. // TODO synchronous only, can't do better with WinAPI native dialogs.
  80. // threading might work, if someone is motivated to risk it.
  81. if (GetOpenFileNameW(&ofn))
  82. {
  83. // back to UTF-8
  84. std::vector<char> fileNameA(4 * 32768);
  85. if (WideCharToMultiByte(CP_UTF8, 0, fileNameW.data(), -1, fileNameA.data(), (int)fileNameA.size(), nullptr, nullptr))
  86. {
  87. // handle it during the next idle cycle (fake async)
  88. pData->fSelectedFile = fileNameA.data();
  89. }
  90. }
  91. return true;
  92. #elif defined(DISTRHO_OS_MAC)
  93. if (pData->fOpenFilePanel) // permit one dialog at most
  94. {
  95. [pData->fOpenFilePanel makeKeyAndOrderFront:nil];
  96. return false;
  97. }
  98. NSOpenPanel* panel = [NSOpenPanel openPanel];
  99. pData->fOpenFilePanel = [panel retain];
  100. [panel setCanChooseFiles:YES];
  101. [panel setCanChooseDirectories:NO];
  102. [panel setAllowsMultipleSelection:NO];
  103. if (options.startDir)
  104. [panel setDirectory:[NSString stringWithUTF8String:options.startDir]];
  105. if (options.title)
  106. {
  107. NSString* titleString = [[NSString alloc]
  108. initWithBytes:options.title
  109. length:strlen(options.title)
  110. encoding:NSUTF8StringEncoding];
  111. [panel setTitle:titleString];
  112. }
  113. id delegate = pData->fFilePanelDelegate;
  114. if (!delegate)
  115. {
  116. delegate = [[FilePanelDelegate alloc] initWithCallback:&PrivateData::openPanelDidEnd
  117. userData:pData];
  118. pData->fFilePanelDelegate = [delegate retain];
  119. }
  120. [panel beginSheetForDirectory:nullptr
  121. file:nullptr
  122. modalForWindow:nullptr
  123. modalDelegate:delegate
  124. didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
  125. contextInfo:nullptr];
  126. return true;
  127. #elif defined(SOFD_HAVE_X11)
  128. using DISTRHO_NAMESPACE::String;
  129. // --------------------------------------------------------------------------
  130. // configure start dir
  131. // TODO: get abspath if needed
  132. // TODO: cross-platform
  133. String startDir(options.startDir);
  134. # ifdef DISTRHO_OS_LINUX
  135. if (startDir.isEmpty())
  136. {
  137. if (char* const dir_name = get_current_dir_name())
  138. {
  139. startDir = dir_name;
  140. std::free(dir_name);
  141. }
  142. }
  143. # endif
  144. DISTRHO_SAFE_ASSERT_RETURN(startDir.isNotEmpty(), false);
  145. if (! startDir.endsWith('/'))
  146. startDir += "/";
  147. DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(0, startDir) == 0, false);
  148. // --------------------------------------------------------------------------
  149. // configure title
  150. String title(options.title);
  151. if (title.isEmpty())
  152. {
  153. title = pData->getTitle();
  154. if (title.isEmpty())
  155. title = "FileBrowser";
  156. }
  157. DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(1, title) == 0, false);
  158. // --------------------------------------------------------------------------
  159. // configure filters
  160. x_fib_cfg_filter_callback(nullptr); //fib_filter_filename_filter);
  161. // --------------------------------------------------------------------------
  162. // configure buttons
  163. x_fib_cfg_buttons(3, options.buttons.listAllFiles-1);
  164. x_fib_cfg_buttons(1, options.buttons.showHidden-1);
  165. x_fib_cfg_buttons(2, options.buttons.showPlaces-1);
  166. // --------------------------------------------------------------------------
  167. // show
  168. return (x_fib_show(pData->xDisplay, pData->xWindow, /*options.width*/0, /*options.height*/0) == 0);
  169. #else
  170. // not implemented
  171. return false;
  172. // unused
  173. (void)options;
  174. #endif
  175. }
  176. // -----------------------------------------------------------------------
  177. END_NAMESPACE_DGL