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.

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