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.

275 lines
7.8KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  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 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. FileSearchPathListComponent::FileSearchPathListComponent()
  21. : addButton ("+"),
  22. removeButton ("-"),
  23. changeButton (TRANS ("change...")),
  24. upButton ({}, DrawableButton::ImageOnButtonBackground),
  25. downButton ({}, DrawableButton::ImageOnButtonBackground)
  26. {
  27. listBox.setModel (this);
  28. addAndMakeVisible (listBox);
  29. listBox.setColour (ListBox::backgroundColourId, Colours::black.withAlpha (0.02f));
  30. listBox.setColour (ListBox::outlineColourId, Colours::black.withAlpha (0.1f));
  31. listBox.setOutlineThickness (1);
  32. addAndMakeVisible (addButton);
  33. addButton.onClick = [this] { addPath(); };
  34. addButton.setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight | Button::ConnectedOnBottom | Button::ConnectedOnTop);
  35. addAndMakeVisible (removeButton);
  36. removeButton.onClick = [this] { deleteSelected(); };
  37. removeButton.setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight | Button::ConnectedOnBottom | Button::ConnectedOnTop);
  38. addAndMakeVisible (changeButton);
  39. changeButton.onClick = [this] { editSelected(); };
  40. addAndMakeVisible (upButton);
  41. upButton.onClick = [this] { moveSelection (-1); };
  42. auto arrowColour = findColour (ListBox::textColourId);
  43. {
  44. Path arrowPath;
  45. arrowPath.addArrow ({ 50.0f, 100.0f, 50.0f, 0.0f }, 40.0f, 100.0f, 50.0f);
  46. DrawablePath arrowImage;
  47. arrowImage.setFill (arrowColour);
  48. arrowImage.setPath (arrowPath);
  49. upButton.setImages (&arrowImage);
  50. }
  51. addAndMakeVisible (downButton);
  52. downButton.onClick = [this] { moveSelection (1); };
  53. {
  54. Path arrowPath;
  55. arrowPath.addArrow ({ 50.0f, 0.0f, 50.0f, 100.0f }, 40.0f, 100.0f, 50.0f);
  56. DrawablePath arrowImage;
  57. arrowImage.setFill (arrowColour);
  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 ((float) 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. auto row = listBox.getRowContainingPosition (0, mouseY - listBox.getY());
  170. path.add (f, row);
  171. changed();
  172. }
  173. }
  174. }
  175. void FileSearchPathListComponent::addPath()
  176. {
  177. auto start = defaultBrowseTarget;
  178. if (start == File())
  179. start = path[0];
  180. if (start == File())
  181. start = File::getCurrentWorkingDirectory();
  182. #if JUCE_MODAL_LOOPS_PERMITTED
  183. FileChooser chooser (TRANS("Add a folder..."), start, "*");
  184. if (chooser.browseForDirectory())
  185. path.add (chooser.getResult(), listBox.getSelectedRow());
  186. changed();
  187. #else
  188. jassertfalse; // needs rewriting to deal with non-modal environments
  189. #endif
  190. }
  191. void FileSearchPathListComponent::deleteSelected()
  192. {
  193. deleteKeyPressed (listBox.getSelectedRow());
  194. changed();
  195. }
  196. void FileSearchPathListComponent::editSelected()
  197. {
  198. returnKeyPressed (listBox.getSelectedRow());
  199. changed();
  200. }
  201. void FileSearchPathListComponent::moveSelection (int delta)
  202. {
  203. jassert (delta == -1 || delta == 1);
  204. auto currentRow = listBox.getSelectedRow();
  205. if (isPositiveAndBelow (currentRow, path.getNumPaths()))
  206. {
  207. auto newRow = jlimit (0, path.getNumPaths() - 1, currentRow + delta);
  208. if (currentRow != newRow)
  209. {
  210. auto f = path[currentRow];
  211. path.remove (currentRow);
  212. path.add (f, newRow);
  213. listBox.selectRow (newRow);
  214. changed();
  215. }
  216. }
  217. }
  218. } // namespace juce