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.

283 lines
9.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. BEGIN_JUCE_NAMESPACE
  19. //==============================================================================
  20. class FileChooserDialogBox::ContentComponent : public Component
  21. {
  22. public:
  23. //==============================================================================
  24. ContentComponent (const String& name, const String& instructions_, FileBrowserComponent& chooserComponent_)
  25. : Component (name),
  26. chooserComponent (chooserComponent_),
  27. okButton (chooserComponent_.getActionVerb()),
  28. cancelButton (TRANS ("Cancel")),
  29. newFolderButton (TRANS ("New Folder")),
  30. instructions (instructions_)
  31. {
  32. addAndMakeVisible (&chooserComponent);
  33. addAndMakeVisible (&okButton);
  34. okButton.addShortcut (KeyPress::returnKey);
  35. addAndMakeVisible (&cancelButton);
  36. cancelButton.addShortcut (KeyPress::escapeKey);
  37. addChildComponent (&newFolderButton);
  38. setInterceptsMouseClicks (false, true);
  39. }
  40. void paint (Graphics& g)
  41. {
  42. g.setColour (getLookAndFeel().findColour (FileChooserDialogBox::titleTextColourId));
  43. text.draw (g);
  44. }
  45. void resized()
  46. {
  47. const int buttonHeight = 26;
  48. Rectangle<int> area (getLocalBounds());
  49. getLookAndFeel().createFileChooserHeaderText (getName(), instructions, text, getWidth());
  50. const Rectangle<float> bb (text.getBoundingBox (0, text.getNumGlyphs(), false));
  51. area.removeFromTop (roundToInt (bb.getBottom()) + 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. GlyphArrangement text;
  67. };
  68. //==============================================================================
  69. FileChooserDialogBox::FileChooserDialogBox (const String& name,
  70. const String& instructions,
  71. FileBrowserComponent& chooserComponent,
  72. const bool warnAboutOverwritingExistingFiles_,
  73. const 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)
  100. {
  101. Component* const previewComp = content->chooserComponent.getPreviewComponent();
  102. if (previewComp != nullptr)
  103. w = 400 + previewComp->getWidth();
  104. else
  105. w = 600;
  106. }
  107. if (h <= 0)
  108. h = 500;
  109. if (x < 0 || y < 0)
  110. centreWithSize (w, h);
  111. else
  112. setBounds (x, y, w, h);
  113. const bool ok = (runModalLoop() != 0);
  114. setVisible (false);
  115. return ok;
  116. }
  117. #endif
  118. void FileChooserDialogBox::centreWithDefaultSize (Component* componentToCentreAround)
  119. {
  120. Component* const previewComp = content->chooserComponent.getPreviewComponent();
  121. centreAroundComponent (componentToCentreAround,
  122. previewComp != nullptr ? 400 + previewComp->getWidth() : 600,
  123. 500);
  124. }
  125. //==============================================================================
  126. void FileChooserDialogBox::buttonClicked (Button* button)
  127. {
  128. if (button == &(content->okButton))
  129. {
  130. okButtonPressed();
  131. }
  132. else if (button == &(content->cancelButton))
  133. {
  134. closeButtonPressed();
  135. }
  136. else if (button == &(content->newFolderButton))
  137. {
  138. createNewFolder();
  139. }
  140. }
  141. void FileChooserDialogBox::closeButtonPressed()
  142. {
  143. setVisible (false);
  144. }
  145. void FileChooserDialogBox::selectionChanged()
  146. {
  147. content->okButton.setEnabled (content->chooserComponent.currentFileIsValid());
  148. content->newFolderButton.setVisible (content->chooserComponent.isSaveMode()
  149. && content->chooserComponent.getRoot().isDirectory());
  150. }
  151. void FileChooserDialogBox::fileClicked (const File&, const MouseEvent&)
  152. {
  153. }
  154. void FileChooserDialogBox::fileDoubleClicked (const File&)
  155. {
  156. selectionChanged();
  157. content->okButton.triggerClick();
  158. }
  159. void FileChooserDialogBox::okToOverwriteFileCallback (int result, FileChooserDialogBox* box)
  160. {
  161. if (result != 0 && box != nullptr)
  162. box->exitModalState (1);
  163. }
  164. void FileChooserDialogBox::okButtonPressed()
  165. {
  166. if (warnAboutOverwritingExistingFiles
  167. && content->chooserComponent.isSaveMode()
  168. && content->chooserComponent.getSelectedFile(0).exists())
  169. {
  170. AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
  171. TRANS("File already exists"),
  172. TRANS("There's already a file called:")
  173. + "\n\n" + content->chooserComponent.getSelectedFile(0).getFullPathName()
  174. + "\n\n" + TRANS("Are you sure you want to overwrite it?"),
  175. TRANS("overwrite"),
  176. TRANS("cancel"),
  177. this,
  178. ModalCallbackFunction::forComponent (okToOverwriteFileCallback, this));
  179. }
  180. else
  181. {
  182. exitModalState (1);
  183. }
  184. }
  185. void FileChooserDialogBox::createNewFolderCallback (int result, FileChooserDialogBox* box,
  186. Component::SafePointer<AlertWindow> alert)
  187. {
  188. if (result != 0 && alert != nullptr && box != nullptr)
  189. {
  190. alert->setVisible (false);
  191. box->createNewFolderConfirmed (alert->getTextEditorContents ("name"));
  192. }
  193. }
  194. void FileChooserDialogBox::createNewFolder()
  195. {
  196. File parent (content->chooserComponent.getRoot());
  197. if (parent.isDirectory())
  198. {
  199. AlertWindow* aw = new AlertWindow (TRANS("New Folder"),
  200. TRANS("Please enter the name for the folder"),
  201. AlertWindow::NoIcon, this);
  202. aw->addTextEditor ("name", String::empty, String::empty, false);
  203. aw->addButton (TRANS("ok"), 1, KeyPress::returnKey);
  204. aw->addButton (TRANS("cancel"), KeyPress::escapeKey);
  205. aw->enterModalState (true,
  206. ModalCallbackFunction::forComponent (createNewFolderCallback, this,
  207. Component::SafePointer<AlertWindow> (aw)),
  208. true);
  209. }
  210. }
  211. void FileChooserDialogBox::createNewFolderConfirmed (const String& nameFromDialog)
  212. {
  213. const String name (File::createLegalFileName (nameFromDialog));
  214. if (! name.isEmpty())
  215. {
  216. const File parent (content->chooserComponent.getRoot());
  217. if (! parent.getChildFile (name).createDirectory())
  218. {
  219. AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
  220. TRANS ("New Folder"),
  221. TRANS ("Couldn't create the folder!"));
  222. }
  223. content->chooserComponent.refresh();
  224. }
  225. }
  226. END_JUCE_NAMESPACE