Audio plugin host https://kx.studio/carla
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.

270 lines
9.2KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. class FileChooserDialogBox::ContentComponent : public Component
  18. {
  19. public:
  20. ContentComponent (const String& name, const String& desc, FileBrowserComponent& chooser)
  21. : Component (name),
  22. chooserComponent (chooser),
  23. okButton (chooser.getActionVerb()),
  24. cancelButton (TRANS ("Cancel")),
  25. newFolderButton (TRANS ("New Folder")),
  26. instructions (desc)
  27. {
  28. addAndMakeVisible (&chooserComponent);
  29. addAndMakeVisible (&okButton);
  30. okButton.addShortcut (KeyPress (KeyPress::returnKey));
  31. addAndMakeVisible (&cancelButton);
  32. cancelButton.addShortcut (KeyPress (KeyPress::escapeKey));
  33. addChildComponent (&newFolderButton);
  34. setInterceptsMouseClicks (false, true);
  35. }
  36. void paint (Graphics& g) override
  37. {
  38. text.draw (g, getLocalBounds().reduced (6)
  39. .removeFromTop ((int) text.getHeight()).toFloat());
  40. }
  41. void resized() override
  42. {
  43. const int buttonHeight = 26;
  44. Rectangle<int> area (getLocalBounds());
  45. text.createLayout (getLookAndFeel().createFileChooserHeaderText (getName(), instructions),
  46. getWidth() - 12.0f);
  47. area.removeFromTop (roundToInt (text.getHeight()) + 10);
  48. chooserComponent.setBounds (area.removeFromTop (area.getHeight() - buttonHeight - 20));
  49. Rectangle<int> buttonArea (area.reduced (16, 10));
  50. okButton.changeWidthToFitText (buttonHeight);
  51. okButton.setBounds (buttonArea.removeFromRight (okButton.getWidth() + 16));
  52. buttonArea.removeFromRight (16);
  53. cancelButton.changeWidthToFitText (buttonHeight);
  54. cancelButton.setBounds (buttonArea.removeFromRight (cancelButton.getWidth()));
  55. newFolderButton.changeWidthToFitText (buttonHeight);
  56. newFolderButton.setBounds (buttonArea.removeFromLeft (newFolderButton.getWidth()));
  57. }
  58. FileBrowserComponent& chooserComponent;
  59. TextButton okButton, cancelButton, newFolderButton;
  60. private:
  61. String instructions;
  62. TextLayout text;
  63. };
  64. //==============================================================================
  65. FileChooserDialogBox::FileChooserDialogBox (const String& name,
  66. const String& instructions,
  67. FileBrowserComponent& chooserComponent,
  68. const bool warnAboutOverwritingExistingFiles_,
  69. Colour backgroundColour)
  70. : ResizableWindow (name, backgroundColour, true),
  71. warnAboutOverwritingExistingFiles (warnAboutOverwritingExistingFiles_)
  72. {
  73. content = new ContentComponent (name, instructions, chooserComponent);
  74. setContentOwned (content, false);
  75. setResizable (true, true);
  76. setResizeLimits (300, 300, 1200, 1000);
  77. content->okButton.addListener (this);
  78. content->cancelButton.addListener (this);
  79. content->newFolderButton.addListener (this);
  80. content->chooserComponent.addListener (this);
  81. FileChooserDialogBox::selectionChanged();
  82. }
  83. FileChooserDialogBox::~FileChooserDialogBox()
  84. {
  85. content->chooserComponent.removeListener (this);
  86. }
  87. //==============================================================================
  88. #if JUCE_MODAL_LOOPS_PERMITTED
  89. bool FileChooserDialogBox::show (int w, int h)
  90. {
  91. return showAt (-1, -1, w, h);
  92. }
  93. bool FileChooserDialogBox::showAt (int x, int y, int w, int h)
  94. {
  95. if (w <= 0) w = getDefaultWidth();
  96. if (h <= 0) h = 500;
  97. if (x < 0 || y < 0)
  98. centreWithSize (w, h);
  99. else
  100. setBounds (x, y, w, h);
  101. const bool ok = (runModalLoop() != 0);
  102. setVisible (false);
  103. return ok;
  104. }
  105. #endif
  106. void FileChooserDialogBox::centreWithDefaultSize (Component* componentToCentreAround)
  107. {
  108. centreAroundComponent (componentToCentreAround, getDefaultWidth(), 500);
  109. }
  110. int FileChooserDialogBox::getDefaultWidth() const
  111. {
  112. if (Component* const previewComp = content->chooserComponent.getPreviewComponent())
  113. return 400 + previewComp->getWidth();
  114. return 600;
  115. }
  116. //==============================================================================
  117. void FileChooserDialogBox::buttonClicked (Button* button)
  118. {
  119. if (button == &(content->okButton))
  120. {
  121. okButtonPressed();
  122. }
  123. else if (button == &(content->cancelButton))
  124. {
  125. closeButtonPressed();
  126. }
  127. else if (button == &(content->newFolderButton))
  128. {
  129. createNewFolder();
  130. }
  131. }
  132. void FileChooserDialogBox::closeButtonPressed()
  133. {
  134. setVisible (false);
  135. }
  136. void FileChooserDialogBox::selectionChanged()
  137. {
  138. content->okButton.setEnabled (content->chooserComponent.currentFileIsValid());
  139. content->newFolderButton.setVisible (content->chooserComponent.isSaveMode()
  140. && content->chooserComponent.getRoot().isDirectory());
  141. }
  142. void FileChooserDialogBox::fileDoubleClicked (const File&)
  143. {
  144. selectionChanged();
  145. content->okButton.triggerClick();
  146. }
  147. void FileChooserDialogBox::fileClicked (const File&, const MouseEvent&) {}
  148. void FileChooserDialogBox::browserRootChanged (const File&) {}
  149. void FileChooserDialogBox::okToOverwriteFileCallback (int result, FileChooserDialogBox* box)
  150. {
  151. if (result != 0 && box != nullptr)
  152. box->exitModalState (1);
  153. }
  154. void FileChooserDialogBox::okButtonPressed()
  155. {
  156. if (warnAboutOverwritingExistingFiles
  157. && content->chooserComponent.isSaveMode()
  158. && content->chooserComponent.getSelectedFile(0).exists())
  159. {
  160. AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
  161. TRANS("File already exists"),
  162. TRANS("There's already a file called: FLMN")
  163. .replace ("FLNM", content->chooserComponent.getSelectedFile(0).getFullPathName())
  164. + "\n\n"
  165. + TRANS("Are you sure you want to overwrite it?"),
  166. TRANS("Overwrite"),
  167. TRANS("Cancel"),
  168. this,
  169. ModalCallbackFunction::forComponent (okToOverwriteFileCallback, this));
  170. }
  171. else
  172. {
  173. exitModalState (1);
  174. }
  175. }
  176. void FileChooserDialogBox::createNewFolderCallback (int result, FileChooserDialogBox* box,
  177. Component::SafePointer<AlertWindow> alert)
  178. {
  179. if (result != 0 && alert != nullptr && box != nullptr)
  180. {
  181. alert->setVisible (false);
  182. box->createNewFolderConfirmed (alert->getTextEditorContents ("Folder Name"));
  183. }
  184. }
  185. void FileChooserDialogBox::createNewFolder()
  186. {
  187. File parent (content->chooserComponent.getRoot());
  188. if (parent.isDirectory())
  189. {
  190. AlertWindow* aw = new AlertWindow (TRANS("New Folder"),
  191. TRANS("Please enter the name for the folder"),
  192. AlertWindow::NoIcon, this);
  193. aw->addTextEditor ("Folder Name", String::empty, String::empty, false);
  194. aw->addButton (TRANS("Create Folder"), 1, KeyPress (KeyPress::returnKey));
  195. aw->addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey));
  196. aw->enterModalState (true,
  197. ModalCallbackFunction::forComponent (createNewFolderCallback, this,
  198. Component::SafePointer<AlertWindow> (aw)),
  199. true);
  200. }
  201. }
  202. void FileChooserDialogBox::createNewFolderConfirmed (const String& nameFromDialog)
  203. {
  204. const String name (File::createLegalFileName (nameFromDialog));
  205. if (! name.isEmpty())
  206. {
  207. const File parent (content->chooserComponent.getRoot());
  208. if (! parent.getChildFile (name).createDirectory())
  209. {
  210. AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
  211. TRANS ("New Folder"),
  212. TRANS ("Couldn't create the folder!"));
  213. }
  214. content->chooserComponent.refresh();
  215. }
  216. }