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.

324 lines
15KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. namespace juce
  20. {
  21. //==============================================================================
  22. /**
  23. Creates a dialog box to choose a file or directory to load or save.
  24. To use a FileChooser:
  25. - create one (as a local stack variable is the neatest way)
  26. - call one of its browseFor.. methods
  27. - if this returns true, the user has selected a file, so you can retrieve it
  28. with the getResult() method.
  29. e.g. @code
  30. void loadMooseFile()
  31. {
  32. FileChooser myChooser ("Please select the moose you want to load...",
  33. File::getSpecialLocation (File::userHomeDirectory),
  34. "*.moose");
  35. if (myChooser.browseForFileToOpen())
  36. {
  37. File mooseFile (myChooser.getResult());
  38. loadMoose (mooseFile);
  39. }
  40. }
  41. @endcode
  42. */
  43. class JUCE_API FileChooser
  44. {
  45. public:
  46. //==============================================================================
  47. /** Creates a FileChooser.
  48. After creating one of these, use one of the browseFor... methods to display it.
  49. @param dialogBoxTitle a text string to display in the dialog box to
  50. tell the user what's going on
  51. @param initialFileOrDirectory the file or directory that should be selected
  52. when the dialog box opens. If this parameter is
  53. set to File(), a sensible default directory will
  54. be used instead. This parameter is ignored for native
  55. iOS file choosers.
  56. @param filePatternsAllowed a set of file patterns to specify which files
  57. can be selected - each pattern should be
  58. separated by a comma or semi-colon, e.g. "*" or
  59. "*.jpg;*.gif". An empty string means that all
  60. files are allowed
  61. @param useOSNativeDialogBox if true, then a native dialog box will be used
  62. if possible; if false, then a Juce-based
  63. browser dialog box will always be used
  64. @param treatFilePackagesAsDirectories if true, then the file chooser will allow the
  65. selection of files inside packages when
  66. invoked on OS X and when using native dialog
  67. boxes.
  68. @see browseForFileToOpen, browseForFileToSave, browseForDirectory
  69. */
  70. FileChooser (const String& dialogBoxTitle,
  71. const File& initialFileOrDirectory = File(),
  72. const String& filePatternsAllowed = String(),
  73. bool useOSNativeDialogBox = true,
  74. bool treatFilePackagesAsDirectories = false);
  75. /** Destructor. */
  76. ~FileChooser();
  77. //==============================================================================
  78. /** Shows a dialog box to choose a file to open.
  79. This will display the dialog box modally, using an "open file" mode, so that
  80. it won't allow non-existent files or directories to be chosen.
  81. @param previewComponent an optional component to display inside the dialog
  82. box to show special info about the files that the user
  83. is browsing. The component will not be deleted by this
  84. object, so the caller must take care of it.
  85. @returns true if the user selected a file, in which case, use the getResult()
  86. method to find out what it was. Returns false if they cancelled instead.
  87. @see browseForFileToSave, browseForDirectory
  88. */
  89. bool browseForFileToOpen (FilePreviewComponent* previewComponent = nullptr);
  90. /** Same as browseForFileToOpen, but allows the user to select multiple files.
  91. The files that are returned can be obtained by calling getResults(). See
  92. browseForFileToOpen() for more info about the behaviour of this method.
  93. */
  94. bool browseForMultipleFilesToOpen (FilePreviewComponent* previewComponent = nullptr);
  95. /** Shows a dialog box to choose a file to save.
  96. This will display the dialog box modally, using an "save file" mode, so it
  97. will allow non-existent files to be chosen, but not directories.
  98. @param warnAboutOverwritingExistingFiles if true, the dialog box will ask
  99. the user if they're sure they want to overwrite a file that already
  100. exists
  101. @param fileWhichShouldBeSaved if this parameter is specified, then, if the the user
  102. selects a valid location to save the file, fileWhichShouldBeSaved will
  103. automaitcally be moved to the location selected by the user when the user
  104. clicks 'ok'. If you do not specify this parameter, then it is your
  105. responsibility to save your file at the location that is returned from this
  106. file chooser. Typically, when using this parameter, you already write the
  107. file you wish to save to a temporary location and then supply the path to
  108. this file to this parameter. This parameter is required on iOS when using
  109. native file save dialogs but can be used on all other platforms.
  110. @returns true if the user chose a file and pressed 'ok', in which case, use
  111. the getResult() method to find out what the file was. Returns false
  112. if they cancelled instead.
  113. @see browseForFileToOpen, browseForDirectory
  114. */
  115. bool browseForFileToSave (bool warnAboutOverwritingExistingFiles,
  116. const File& fileWhichShouldBeSaved = File());
  117. /** Shows a dialog box to choose a directory.
  118. This will display the dialog box modally, using an "open directory" mode, so it
  119. will only allow directories to be returned, not files.
  120. @returns true if the user chose a directory and pressed 'ok', in which case, use
  121. the getResult() method to find out what they chose. Returns false
  122. if they cancelled instead.
  123. @see browseForFileToOpen, browseForFileToSave
  124. */
  125. bool browseForDirectory();
  126. /** Same as browseForFileToOpen, but allows the user to select multiple files and directories.
  127. The files that are returned can be obtained by calling getResults(). See
  128. browseForFileToOpen() for more info about the behaviour of this method.
  129. */
  130. bool browseForMultipleFilesOrDirectories (FilePreviewComponent* previewComponent = nullptr);
  131. //==============================================================================
  132. /** Runs a dialog box for the given set of option flags.
  133. The flag values used are those in FileBrowserComponent::FileChooserFlags.
  134. @param fileWhichShouldBeSaved if this parameter is specified and saveMode is
  135. specified, then, if the the user selects a valid location to save the file,
  136. fileWhichShouldBeSaved will automaitcally be moved to the location selected
  137. by the user when the user clicks 'ok'. If you do not specify this parameter,
  138. then it is your responsibility to save your file at the location that is
  139. returned from this file chooser. Typically, when using this parameter,
  140. you already write the file you wish to save to a temporary location and
  141. then supply the path to this file to this parameter. This parameter is
  142. required on iOS when using native file save dialogs but can be used on all
  143. other platforms.
  144. @returns true if the user chose a directory and pressed 'ok', in which case, use
  145. the getResult() method to find out what they chose. Returns false
  146. if they cancelled instead.
  147. @see FileBrowserComponent::FileChooserFlags
  148. */
  149. bool showDialog (int flags, FilePreviewComponent* previewComponent,
  150. const File& fileWhichShouldBeSaved = File());
  151. /** Use this method to launch the file browser window asynchronously.
  152. This will create a file browser dialog based on the settings in this
  153. structure and will launch it modally, returning immediately.
  154. You must specify a callback which is called when the file browser is
  155. canceled or a file is selected. To abort the file selection, simply
  156. delete the FileChooser object.
  157. You can use the ModalCallbackFunction::create method to wrap a lambda
  158. into a modal Callback object.
  159. You must ensure that the lifetime of the callback object is longer than
  160. the lifetime of the file-chooser.
  161. @param fileWhichShouldBeSaved if this parameter is specified and saveMode is
  162. specified, then, if the the user selects a valid location to save the file,
  163. fileWhichShouldBeSaved will automaitcally be moved to the location selected
  164. by the user when the user clicks 'ok'. If you do not specify this parameter,
  165. then it is your responsibility to save your file at the location that is
  166. returned from this file chooser. Typically, when using this parameter,
  167. you already write the file you wish to save to a temporary location and
  168. then supply the path to this file to this parameter. This parameter is
  169. required on iOS when using native file save dialogs but can be used on all
  170. other platforms.
  171. */
  172. void launchAsync (int flags,
  173. std::function<void (const FileChooser&)>,
  174. FilePreviewComponent* previewComponent = nullptr,
  175. const File& fileWhichShouldBeSaved = File());
  176. //==============================================================================
  177. /** Returns the last file that was chosen by one of the browseFor methods.
  178. After calling the appropriate browseFor... method, this method lets you
  179. find out what file or directory they chose.
  180. Note that the file returned is only valid if the browse method returned true (i.e.
  181. if the user pressed 'ok' rather than cancelling).
  182. On mobile platforms, the file browser may return a URL instead of a local file.
  183. Therefore, om mobile platforms, you should call getURLResult() instead.
  184. If you're using a multiple-file select, then use the getResults() method instead,
  185. to obtain the list of all files chosen.
  186. @see getURLResult, getResults
  187. */
  188. File getResult() const;
  189. /** Returns a list of all the files that were chosen during the last call to a
  190. browse method.
  191. On mobile platforms, the file browser may return a URL instead of a local file.
  192. Therefore, om mobile platforms, you should call getURLResults() instead.
  193. This array may be empty if no files were chosen, or can contain multiple entries
  194. if multiple files were chosen.
  195. @see getURLResults, getResult
  196. */
  197. Array<File> getResults() const noexcept;
  198. //==============================================================================
  199. /** Returns the last document that was chosen by one of the browseFor methods.
  200. Use this method if you are using the FileChooser on a mobile platform which
  201. may return a URL to a remote document. If a local file is chosen then you can
  202. convert this file to a JUCE File class via the URL::getLocalFile method.
  203. @see getResult, URL::getLocalFile
  204. */
  205. URL getURLResult() const;
  206. /** Returns a list of all the files that were chosen during the last call to a
  207. browse method.
  208. Use this method if you are using the FileChooser on a mobile platform which
  209. may return a URL to a remote document. If a local file is chosen then you can
  210. convert this file to a JUCE File class via the URL::getLocalFile method.
  211. This array may be empty if no files were chosen, or can contain multiple entries
  212. if multiple files were chosen.
  213. @see getResults, URL::getLocalFile
  214. */
  215. const Array<URL>& getURLResults() const noexcept { return results; }
  216. //==============================================================================
  217. /** Returns if a native filechooser is currently available on this platform.
  218. Note: On iOS this will only return true if you have iCloud permissions
  219. and code-signing enabled in the Projucer and have added iCloud containers
  220. to your app in Apple's online developer portal. Additionally, the user must
  221. have installed the iCloud app on their device and used the app at leat once.
  222. */
  223. static bool isPlatformDialogAvailable();
  224. //==============================================================================
  225. #ifndef DOXYGEN
  226. class Native;
  227. #endif
  228. private:
  229. //==============================================================================
  230. String title, filters;
  231. File startingFile, fileToSave;
  232. Array<URL> results;
  233. const bool useNativeDialogBox;
  234. const bool treatFilePackagesAsDirs;
  235. std::function<void (const FileChooser&)> asyncCallback;
  236. //==============================================================================
  237. void finished (const Array<URL>&, bool);
  238. //==============================================================================
  239. struct Pimpl
  240. {
  241. virtual ~Pimpl() {}
  242. virtual void launch() = 0;
  243. virtual void runModally() = 0;
  244. };
  245. ScopedPointer<Pimpl> pimpl;
  246. //==============================================================================
  247. Pimpl* createPimpl (int, FilePreviewComponent*);
  248. static Pimpl* showPlatformDialog (FileChooser&, int,
  249. FilePreviewComponent*);
  250. class NonNative;
  251. friend class NonNative;
  252. friend class Native;
  253. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileChooser)
  254. };
  255. } // namespace juce