The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

344 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. // (This file gets included by juce_win32_NativeCode.cpp, rather than being
  24. // compiled on its own).
  25. #if JUCE_INCLUDED_FILE
  26. //==============================================================================
  27. static const void* defaultDirPath = 0;
  28. static String returnedString; // need this to get non-existent pathnames from the directory chooser
  29. static Component* currentExtraFileWin = 0;
  30. static bool areThereAnyAlwaysOnTopWindows()
  31. {
  32. for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;)
  33. {
  34. Component* c = Desktop::getInstance().getComponent (i);
  35. if (c != 0 && c->isAlwaysOnTop() && c->isShowing())
  36. return true;
  37. }
  38. return false;
  39. }
  40. static int CALLBACK browseCallbackProc (HWND hWnd, UINT msg, LPARAM lParam, LPARAM /*lpData*/)
  41. {
  42. if (msg == BFFM_INITIALIZED)
  43. {
  44. SendMessage (hWnd, BFFM_SETSELECTIONW, TRUE, (LPARAM) defaultDirPath);
  45. }
  46. else if (msg == BFFM_VALIDATEFAILEDW)
  47. {
  48. returnedString = (LPCWSTR) lParam;
  49. }
  50. else if (msg == BFFM_VALIDATEFAILEDA)
  51. {
  52. returnedString = (const char*) lParam;
  53. }
  54. return 0;
  55. }
  56. void juce_setWindowStyleBit (HWND h, int styleType, int feature, bool bitIsSet);
  57. static UINT_PTR CALLBACK openCallback (HWND hdlg, UINT uiMsg, WPARAM /*wParam*/, LPARAM lParam)
  58. {
  59. if (currentExtraFileWin != 0)
  60. {
  61. if (uiMsg == WM_INITDIALOG)
  62. {
  63. HWND dialogH = GetParent (hdlg);
  64. jassert (dialogH != 0);
  65. if (dialogH == 0)
  66. dialogH = hdlg;
  67. RECT r, cr;
  68. GetWindowRect (dialogH, &r);
  69. GetClientRect (dialogH, &cr);
  70. SetWindowPos (dialogH, 0,
  71. r.left, r.top,
  72. currentExtraFileWin->getWidth() + jmax (150, r.right - r.left),
  73. jmax (150, r.bottom - r.top),
  74. SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
  75. currentExtraFileWin->setBounds (cr.right, cr.top, currentExtraFileWin->getWidth(), cr.bottom - cr.top);
  76. currentExtraFileWin->getChildComponent(0)->setBounds (0, 0, currentExtraFileWin->getWidth(), currentExtraFileWin->getHeight());
  77. SetParent ((HWND) currentExtraFileWin->getWindowHandle(), (HWND) dialogH);
  78. juce_setWindowStyleBit ((HWND)currentExtraFileWin->getWindowHandle(), GWL_STYLE, WS_CHILD, (dialogH != 0));
  79. juce_setWindowStyleBit ((HWND)currentExtraFileWin->getWindowHandle(), GWL_STYLE, WS_POPUP, (dialogH == 0));
  80. }
  81. else if (uiMsg == WM_NOTIFY)
  82. {
  83. LPOFNOTIFY ofn = (LPOFNOTIFY) lParam;
  84. if (ofn->hdr.code == CDN_SELCHANGE)
  85. {
  86. FilePreviewComponent* comp = (FilePreviewComponent*) currentExtraFileWin->getChildComponent(0);
  87. if (comp != 0)
  88. {
  89. TCHAR path [MAX_PATH * 2];
  90. path[0] = 0;
  91. CommDlg_OpenSave_GetFilePath (GetParent (hdlg), (LPARAM) &path, MAX_PATH);
  92. const String fn ((const WCHAR*) path);
  93. comp->selectedFileChanged (File (fn));
  94. }
  95. }
  96. }
  97. }
  98. return 0;
  99. }
  100. class FPComponentHolder : public Component
  101. {
  102. public:
  103. FPComponentHolder()
  104. {
  105. setVisible (true);
  106. setOpaque (true);
  107. }
  108. ~FPComponentHolder()
  109. {
  110. }
  111. void paint (Graphics& g)
  112. {
  113. g.fillAll (Colours::lightgrey);
  114. }
  115. private:
  116. FPComponentHolder (const FPComponentHolder&);
  117. const FPComponentHolder& operator= (const FPComponentHolder&);
  118. };
  119. //==============================================================================
  120. void FileChooser::showPlatformDialog (OwnedArray<File>& results,
  121. const String& title,
  122. const File& currentFileOrDirectory,
  123. const String& filter,
  124. bool selectsDirectory,
  125. bool isSaveDialogue,
  126. bool warnAboutOverwritingExistingFiles,
  127. bool selectMultipleFiles,
  128. FilePreviewComponent* extraInfoComponent)
  129. {
  130. const int numCharsAvailable = 32768;
  131. MemoryBlock filenameSpace ((numCharsAvailable + 1) * sizeof (WCHAR), true);
  132. WCHAR* const fname = (WCHAR*) filenameSpace.getData();
  133. int fnameIdx = 0;
  134. JUCE_TRY
  135. {
  136. // use a modal window as the parent for this dialog box
  137. // to block input from other app windows
  138. const Rectangle mainMon (Desktop::getInstance().getMainMonitorArea());
  139. Component w (String::empty);
  140. w.setBounds (mainMon.getX() + mainMon.getWidth() / 4,
  141. mainMon.getY() + mainMon.getHeight() / 4,
  142. 0, 0);
  143. w.setOpaque (true);
  144. w.setAlwaysOnTop (areThereAnyAlwaysOnTopWindows());
  145. w.addToDesktop (0);
  146. if (extraInfoComponent == 0)
  147. w.enterModalState();
  148. String initialDir;
  149. if (currentFileOrDirectory.isDirectory())
  150. {
  151. initialDir = currentFileOrDirectory.getFullPathName();
  152. }
  153. else
  154. {
  155. currentFileOrDirectory.getFileName().copyToBuffer (fname, numCharsAvailable);
  156. initialDir = currentFileOrDirectory.getParentDirectory().getFullPathName();
  157. }
  158. if (currentExtraFileWin->isValidComponent())
  159. {
  160. jassertfalse
  161. return;
  162. }
  163. if (selectsDirectory)
  164. {
  165. LPITEMIDLIST list = 0;
  166. filenameSpace.fillWith (0);
  167. {
  168. BROWSEINFO bi;
  169. zerostruct (bi);
  170. bi.hwndOwner = (HWND) w.getWindowHandle();
  171. bi.pszDisplayName = fname;
  172. bi.lpszTitle = title;
  173. bi.lpfn = browseCallbackProc;
  174. #ifdef BIF_USENEWUI
  175. bi.ulFlags = BIF_USENEWUI | BIF_VALIDATE;
  176. #else
  177. bi.ulFlags = 0x50;
  178. #endif
  179. defaultDirPath = (const WCHAR*) initialDir;
  180. list = SHBrowseForFolder (&bi);
  181. if (! SHGetPathFromIDListW (list, fname))
  182. {
  183. fname[0] = 0;
  184. returnedString = String::empty;
  185. }
  186. }
  187. LPMALLOC al;
  188. if (list != 0 && SUCCEEDED (SHGetMalloc (&al)))
  189. al->Free (list);
  190. defaultDirPath = 0;
  191. if (returnedString.isNotEmpty())
  192. {
  193. const String stringFName (fname);
  194. results.add (new File (File (stringFName).getSiblingFile (returnedString)));
  195. returnedString = String::empty;
  196. return;
  197. }
  198. }
  199. else
  200. {
  201. DWORD flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
  202. if (warnAboutOverwritingExistingFiles)
  203. flags |= OFN_OVERWRITEPROMPT;
  204. if (selectMultipleFiles)
  205. flags |= OFN_ALLOWMULTISELECT;
  206. if (extraInfoComponent != 0)
  207. {
  208. flags |= OFN_ENABLEHOOK;
  209. currentExtraFileWin = new FPComponentHolder();
  210. currentExtraFileWin->addAndMakeVisible (extraInfoComponent);
  211. currentExtraFileWin->setSize (jlimit (20, 800, extraInfoComponent->getWidth()),
  212. extraInfoComponent->getHeight());
  213. currentExtraFileWin->addToDesktop (0);
  214. currentExtraFileWin->enterModalState();
  215. }
  216. {
  217. WCHAR filters [1024];
  218. zeromem (filters, sizeof (filters));
  219. filter.copyToBuffer (filters, 1024);
  220. filter.copyToBuffer (filters + filter.length() + 1,
  221. 1022 - filter.length());
  222. OPENFILENAMEW of;
  223. zerostruct (of);
  224. #ifdef OPENFILENAME_SIZE_VERSION_400W
  225. of.lStructSize = OPENFILENAME_SIZE_VERSION_400W;
  226. #else
  227. of.lStructSize = sizeof (of);
  228. #endif
  229. of.hwndOwner = (HWND) w.getWindowHandle();
  230. of.lpstrFilter = filters;
  231. of.nFilterIndex = 1;
  232. of.lpstrFile = fname;
  233. of.nMaxFile = numCharsAvailable;
  234. of.lpstrInitialDir = initialDir;
  235. of.lpstrTitle = title;
  236. of.Flags = flags;
  237. if (extraInfoComponent != 0)
  238. of.lpfnHook = &openCallback;
  239. if (isSaveDialogue)
  240. {
  241. if (! GetSaveFileName (&of))
  242. fname[0] = 0;
  243. else
  244. fnameIdx = of.nFileOffset;
  245. }
  246. else
  247. {
  248. if (! GetOpenFileName (&of))
  249. fname[0] = 0;
  250. else
  251. fnameIdx = of.nFileOffset;
  252. }
  253. }
  254. }
  255. }
  256. #if JUCE_CATCH_UNHANDLED_EXCEPTIONS
  257. catch (...)
  258. {
  259. fname[0] = 0;
  260. }
  261. #endif
  262. deleteAndZero (currentExtraFileWin);
  263. const WCHAR* const files = fname;
  264. if (selectMultipleFiles && fnameIdx > 0 && files [fnameIdx - 1] == 0)
  265. {
  266. const WCHAR* filename = files + fnameIdx;
  267. while (*filename != 0)
  268. {
  269. const String filepath (String (files) + T("\\") + String (filename));
  270. results.add (new File (filepath));
  271. filename += CharacterFunctions::length (filename) + 1;
  272. }
  273. }
  274. else if (files[0] != 0)
  275. {
  276. results.add (new File (files));
  277. }
  278. }
  279. #endif