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.

269 lines
7.8KB

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