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.

274 lines
7.9KB

  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. FileSearchPathListComponent::FileSearchPathListComponent()
  22. : addButton ("+"),
  23. removeButton ("-"),
  24. changeButton (TRANS ("change...")),
  25. upButton (String(), DrawableButton::ImageOnButtonBackground),
  26. downButton (String(), DrawableButton::ImageOnButtonBackground)
  27. {
  28. listBox.setModel (this);
  29. addAndMakeVisible (listBox);
  30. listBox.setColour (ListBox::backgroundColourId, Colours::black.withAlpha (0.02f));
  31. listBox.setColour (ListBox::outlineColourId, Colours::black.withAlpha (0.1f));
  32. listBox.setOutlineThickness (1);
  33. addAndMakeVisible (addButton);
  34. addButton.addListener (this);
  35. addButton.setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight | Button::ConnectedOnBottom | Button::ConnectedOnTop);
  36. addAndMakeVisible (removeButton);
  37. removeButton.addListener (this);
  38. removeButton.setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight | Button::ConnectedOnBottom | Button::ConnectedOnTop);
  39. addAndMakeVisible (changeButton);
  40. changeButton.addListener (this);
  41. addAndMakeVisible (upButton);
  42. upButton.addListener (this);
  43. {
  44. Path arrowPath;
  45. arrowPath.addArrow (Line<float> (50.0f, 100.0f, 50.0f, 0.0f), 40.0f, 100.0f, 50.0f);
  46. DrawablePath arrowImage;
  47. arrowImage.setFill (Colours::black.withAlpha (0.4f));
  48. arrowImage.setPath (arrowPath);
  49. upButton.setImages (&arrowImage);
  50. }
  51. addAndMakeVisible (downButton);
  52. downButton.addListener (this);
  53. {
  54. Path arrowPath;
  55. arrowPath.addArrow (Line<float> (50.0f, 0.0f, 50.0f, 100.0f), 40.0f, 100.0f, 50.0f);
  56. DrawablePath arrowImage;
  57. arrowImage.setFill (Colours::black.withAlpha (0.4f));
  58. arrowImage.setPath (arrowPath);
  59. downButton.setImages (&arrowImage);
  60. }
  61. updateButtons();
  62. }
  63. FileSearchPathListComponent::~FileSearchPathListComponent()
  64. {
  65. }
  66. void FileSearchPathListComponent::updateButtons()
  67. {
  68. const bool anythingSelected = listBox.getNumSelectedRows() > 0;
  69. removeButton.setEnabled (anythingSelected);
  70. changeButton.setEnabled (anythingSelected);
  71. upButton.setEnabled (anythingSelected);
  72. downButton.setEnabled (anythingSelected);
  73. }
  74. void FileSearchPathListComponent::changed()
  75. {
  76. listBox.updateContent();
  77. listBox.repaint();
  78. updateButtons();
  79. }
  80. //==============================================================================
  81. void FileSearchPathListComponent::setPath (const FileSearchPath& newPath)
  82. {
  83. if (newPath.toString() != path.toString())
  84. {
  85. path = newPath;
  86. changed();
  87. }
  88. }
  89. void FileSearchPathListComponent::setDefaultBrowseTarget (const File& newDefaultDirectory)
  90. {
  91. defaultBrowseTarget = newDefaultDirectory;
  92. }
  93. //==============================================================================
  94. int FileSearchPathListComponent::getNumRows()
  95. {
  96. return path.getNumPaths();
  97. }
  98. void FileSearchPathListComponent::paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected)
  99. {
  100. if (rowIsSelected)
  101. g.fillAll (findColour (TextEditor::highlightColourId));
  102. g.setColour (findColour (ListBox::textColourId));
  103. Font f (height * 0.7f);
  104. f.setHorizontalScale (0.9f);
  105. g.setFont (f);
  106. g.drawText (path [rowNumber].getFullPathName(),
  107. 4, 0, width - 6, height,
  108. Justification::centredLeft, true);
  109. }
  110. void FileSearchPathListComponent::deleteKeyPressed (int row)
  111. {
  112. if (isPositiveAndBelow (row, path.getNumPaths()))
  113. {
  114. path.remove (row);
  115. changed();
  116. }
  117. }
  118. void FileSearchPathListComponent::returnKeyPressed (int row)
  119. {
  120. #if JUCE_MODAL_LOOPS_PERMITTED
  121. FileChooser chooser (TRANS("Change folder..."), path [row], "*");
  122. if (chooser.browseForDirectory())
  123. {
  124. path.remove (row);
  125. path.add (chooser.getResult(), row);
  126. changed();
  127. }
  128. #else
  129. ignoreUnused (row);
  130. #endif
  131. }
  132. void FileSearchPathListComponent::listBoxItemDoubleClicked (int row, const MouseEvent&)
  133. {
  134. returnKeyPressed (row);
  135. }
  136. void FileSearchPathListComponent::selectedRowsChanged (int)
  137. {
  138. updateButtons();
  139. }
  140. void FileSearchPathListComponent::paint (Graphics& g)
  141. {
  142. g.fillAll (findColour (backgroundColourId));
  143. }
  144. void FileSearchPathListComponent::resized()
  145. {
  146. const int buttonH = 22;
  147. const int buttonY = getHeight() - buttonH - 4;
  148. listBox.setBounds (2, 2, getWidth() - 4, buttonY - 5);
  149. addButton.setBounds (2, buttonY, buttonH, buttonH);
  150. removeButton.setBounds (addButton.getRight(), buttonY, buttonH, buttonH);
  151. changeButton.changeWidthToFitText (buttonH);
  152. downButton.setSize (buttonH * 2, buttonH);
  153. upButton.setSize (buttonH * 2, buttonH);
  154. downButton.setTopRightPosition (getWidth() - 2, buttonY);
  155. upButton.setTopRightPosition (downButton.getX() - 4, buttonY);
  156. changeButton.setTopRightPosition (upButton.getX() - 8, buttonY);
  157. }
  158. bool FileSearchPathListComponent::isInterestedInFileDrag (const StringArray&)
  159. {
  160. return true;
  161. }
  162. void FileSearchPathListComponent::filesDropped (const StringArray& filenames, int, int mouseY)
  163. {
  164. for (int i = filenames.size(); --i >= 0;)
  165. {
  166. const File f (filenames[i]);
  167. if (f.isDirectory())
  168. {
  169. const int row = listBox.getRowContainingPosition (0, mouseY - listBox.getY());
  170. path.add (f, row);
  171. changed();
  172. }
  173. }
  174. }
  175. void FileSearchPathListComponent::buttonClicked (Button* button)
  176. {
  177. const int currentRow = listBox.getSelectedRow();
  178. if (button == &removeButton)
  179. {
  180. deleteKeyPressed (currentRow);
  181. }
  182. else if (button == &addButton)
  183. {
  184. File start (defaultBrowseTarget);
  185. if (start == File())
  186. start = path [0];
  187. if (start == File())
  188. start = File::getCurrentWorkingDirectory();
  189. #if JUCE_MODAL_LOOPS_PERMITTED
  190. FileChooser chooser (TRANS("Add a folder..."), start, "*");
  191. if (chooser.browseForDirectory())
  192. path.add (chooser.getResult(), currentRow);
  193. #else
  194. jassertfalse; // needs rewriting to deal with non-modal environments
  195. #endif
  196. }
  197. else if (button == &changeButton)
  198. {
  199. returnKeyPressed (currentRow);
  200. }
  201. else if (button == &upButton)
  202. {
  203. if (currentRow > 0 && currentRow < path.getNumPaths())
  204. {
  205. const File f (path[currentRow]);
  206. path.remove (currentRow);
  207. path.add (f, currentRow - 1);
  208. listBox.selectRow (currentRow - 1);
  209. }
  210. }
  211. else if (button == &downButton)
  212. {
  213. if (currentRow >= 0 && currentRow < path.getNumPaths() - 1)
  214. {
  215. const File f (path[currentRow]);
  216. path.remove (currentRow);
  217. path.add (f, currentRow + 1);
  218. listBox.selectRow (currentRow + 1);
  219. }
  220. }
  221. changed();
  222. }
  223. } // namespace juce