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.

277 lines
9.2KB

  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. class FileChooserDialogBox::ContentComponent : public Component
  22. {
  23. public:
  24. ContentComponent (const String& name, const String& desc, FileBrowserComponent& chooser)
  25. : Component (name),
  26. chooserComponent (chooser),
  27. okButton (chooser.getActionVerb()),
  28. cancelButton (TRANS ("Cancel")),
  29. newFolderButton (TRANS ("New Folder")),
  30. instructions (desc)
  31. {
  32. addAndMakeVisible (chooserComponent);
  33. addAndMakeVisible (okButton);
  34. okButton.addShortcut (KeyPress (KeyPress::returnKey));
  35. addAndMakeVisible (cancelButton);
  36. cancelButton.addShortcut (KeyPress (KeyPress::escapeKey));
  37. addChildComponent (newFolderButton);
  38. setInterceptsMouseClicks (false, true);
  39. }
  40. void paint (Graphics& g) override
  41. {
  42. text.draw (g, getLocalBounds().reduced (6)
  43. .removeFromTop ((int) text.getHeight()).toFloat());
  44. }
  45. void resized() override
  46. {
  47. const int buttonHeight = 26;
  48. Rectangle<int> area (getLocalBounds());
  49. text.createLayout (getLookAndFeel().createFileChooserHeaderText (getName(), instructions),
  50. getWidth() - 12.0f);
  51. area.removeFromTop (roundToInt (text.getHeight()) + 10);
  52. chooserComponent.setBounds (area.removeFromTop (area.getHeight() - buttonHeight - 20));
  53. Rectangle<int> buttonArea (area.reduced (16, 10));
  54. okButton.changeWidthToFitText (buttonHeight);
  55. okButton.setBounds (buttonArea.removeFromRight (okButton.getWidth() + 16));
  56. buttonArea.removeFromRight (16);
  57. cancelButton.changeWidthToFitText (buttonHeight);
  58. cancelButton.setBounds (buttonArea.removeFromRight (cancelButton.getWidth()));
  59. newFolderButton.changeWidthToFitText (buttonHeight);
  60. newFolderButton.setBounds (buttonArea.removeFromLeft (newFolderButton.getWidth()));
  61. }
  62. FileBrowserComponent& chooserComponent;
  63. TextButton okButton, cancelButton, newFolderButton;
  64. private:
  65. String instructions;
  66. TextLayout text;
  67. };
  68. //==============================================================================
  69. FileChooserDialogBox::FileChooserDialogBox (const String& name,
  70. const String& instructions,
  71. FileBrowserComponent& chooserComponent,
  72. const bool warnAboutOverwritingExistingFiles_,
  73. Colour backgroundColour)
  74. : ResizableWindow (name, backgroundColour, true),
  75. warnAboutOverwritingExistingFiles (warnAboutOverwritingExistingFiles_)
  76. {
  77. content = new ContentComponent (name, instructions, chooserComponent);
  78. setContentOwned (content, false);
  79. setResizable (true, true);
  80. setResizeLimits (300, 300, 1200, 1000);
  81. content->okButton.addListener (this);
  82. content->cancelButton.addListener (this);
  83. content->newFolderButton.addListener (this);
  84. content->chooserComponent.addListener (this);
  85. FileChooserDialogBox::selectionChanged();
  86. }
  87. FileChooserDialogBox::~FileChooserDialogBox()
  88. {
  89. content->chooserComponent.removeListener (this);
  90. }
  91. //==============================================================================
  92. #if JUCE_MODAL_LOOPS_PERMITTED
  93. bool FileChooserDialogBox::show (int w, int h)
  94. {
  95. return showAt (-1, -1, w, h);
  96. }
  97. bool FileChooserDialogBox::showAt (int x, int y, int w, int h)
  98. {
  99. if (w <= 0) w = getDefaultWidth();
  100. if (h <= 0) h = 500;
  101. if (x < 0 || y < 0)
  102. centreWithSize (w, h);
  103. else
  104. setBounds (x, y, w, h);
  105. const bool ok = (runModalLoop() != 0);
  106. setVisible (false);
  107. return ok;
  108. }
  109. #endif
  110. void FileChooserDialogBox::centreWithDefaultSize (Component* componentToCentreAround)
  111. {
  112. centreAroundComponent (componentToCentreAround, getDefaultWidth(), 500);
  113. }
  114. int FileChooserDialogBox::getDefaultWidth() const
  115. {
  116. if (Component* const previewComp = content->chooserComponent.getPreviewComponent())
  117. return 400 + previewComp->getWidth();
  118. return 600;
  119. }
  120. //==============================================================================
  121. void FileChooserDialogBox::buttonClicked (Button* button)
  122. {
  123. if (button == &(content->okButton))
  124. {
  125. okButtonPressed();
  126. }
  127. else if (button == &(content->cancelButton))
  128. {
  129. closeButtonPressed();
  130. }
  131. else if (button == &(content->newFolderButton))
  132. {
  133. createNewFolder();
  134. }
  135. }
  136. void FileChooserDialogBox::closeButtonPressed()
  137. {
  138. setVisible (false);
  139. }
  140. void FileChooserDialogBox::selectionChanged()
  141. {
  142. content->okButton.setEnabled (content->chooserComponent.currentFileIsValid());
  143. content->newFolderButton.setVisible (content->chooserComponent.isSaveMode()
  144. && content->chooserComponent.getRoot().isDirectory());
  145. }
  146. void FileChooserDialogBox::fileDoubleClicked (const File&)
  147. {
  148. selectionChanged();
  149. content->okButton.triggerClick();
  150. }
  151. void FileChooserDialogBox::fileClicked (const File&, const MouseEvent&) {}
  152. void FileChooserDialogBox::browserRootChanged (const File&) {}
  153. void FileChooserDialogBox::okToOverwriteFileCallback (int result, FileChooserDialogBox* box)
  154. {
  155. if (result != 0 && box != nullptr)
  156. box->exitModalState (1);
  157. }
  158. void FileChooserDialogBox::okButtonPressed()
  159. {
  160. if (warnAboutOverwritingExistingFiles
  161. && content->chooserComponent.isSaveMode()
  162. && content->chooserComponent.getSelectedFile(0).exists())
  163. {
  164. AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
  165. TRANS("File already exists"),
  166. TRANS("There's already a file called: FLNM")
  167. .replace ("FLNM", content->chooserComponent.getSelectedFile(0).getFullPathName())
  168. + "\n\n"
  169. + TRANS("Are you sure you want to overwrite it?"),
  170. TRANS("Overwrite"),
  171. TRANS("Cancel"),
  172. this,
  173. ModalCallbackFunction::forComponent (okToOverwriteFileCallback, this));
  174. }
  175. else
  176. {
  177. exitModalState (1);
  178. }
  179. }
  180. void FileChooserDialogBox::createNewFolderCallback (int result, FileChooserDialogBox* box,
  181. Component::SafePointer<AlertWindow> alert)
  182. {
  183. if (result != 0 && alert != nullptr && box != nullptr)
  184. {
  185. alert->setVisible (false);
  186. box->createNewFolderConfirmed (alert->getTextEditorContents ("Folder Name"));
  187. }
  188. }
  189. void FileChooserDialogBox::createNewFolder()
  190. {
  191. File parent (content->chooserComponent.getRoot());
  192. if (parent.isDirectory())
  193. {
  194. AlertWindow* aw = new AlertWindow (TRANS("New Folder"),
  195. TRANS("Please enter the name for the folder"),
  196. AlertWindow::NoIcon, this);
  197. aw->addTextEditor ("Folder Name", String(), String(), false);
  198. aw->addButton (TRANS("Create Folder"), 1, KeyPress (KeyPress::returnKey));
  199. aw->addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey));
  200. aw->enterModalState (true,
  201. ModalCallbackFunction::forComponent (createNewFolderCallback, this,
  202. Component::SafePointer<AlertWindow> (aw)),
  203. true);
  204. }
  205. }
  206. void FileChooserDialogBox::createNewFolderConfirmed (const String& nameFromDialog)
  207. {
  208. const String name (File::createLegalFileName (nameFromDialog));
  209. if (! name.isEmpty())
  210. {
  211. const File parent (content->chooserComponent.getRoot());
  212. if (! parent.getChildFile (name).createDirectory())
  213. {
  214. AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
  215. TRANS ("New Folder"),
  216. TRANS ("Couldn't create the folder!"));
  217. }
  218. content->chooserComponent.refresh();
  219. }
  220. }
  221. } // namespace juce