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.

251 lines
9.1KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. class ModulesPanel : public Component,
  18. private TableListBoxModel,
  19. private ValueTree::Listener,
  20. private Button::Listener
  21. {
  22. public:
  23. ModulesPanel (Project& p)
  24. : project (p),
  25. modulesValueTree (p.getModules().state),
  26. setCopyModeButton ("Set copy-mode for all modules..."),
  27. copyPathButton ("Set paths for all modules...")
  28. {
  29. table.getHeader().addColumn ("Module", nameCol, 180, 100, 400, TableHeaderComponent::notSortable);
  30. table.getHeader().addColumn ("Version", versionCol, 100, 100, 100, TableHeaderComponent::notSortable);
  31. table.getHeader().addColumn ("Make Local Copy", copyCol, 100, 100, 100, TableHeaderComponent::notSortable);
  32. table.getHeader().addColumn ("Paths", pathCol, 250, 100, 600, TableHeaderComponent::notSortable);
  33. table.setModel (this);
  34. table.setColour (TableListBox::backgroundColourId, Colours::transparentBlack);
  35. addAndMakeVisible (table);
  36. table.updateContent();
  37. table.setRowHeight (20);
  38. table.setMultipleSelectionEnabled (true);
  39. addAndMakeVisible (setCopyModeButton);
  40. addAndMakeVisible (copyPathButton);
  41. setCopyModeButton.addListener (this);
  42. setCopyModeButton.setTriggeredOnMouseDown (true);
  43. copyPathButton.addListener (this);
  44. copyPathButton.setTriggeredOnMouseDown (true);
  45. modulesValueTree.addListener (this);
  46. lookAndFeelChanged();
  47. }
  48. void paint (Graphics& g) override
  49. {
  50. ProjucerLookAndFeel::fillWithBackgroundTexture (*this, g);
  51. }
  52. void resized() override
  53. {
  54. Rectangle<int> r (getLocalBounds().reduced (5, 4));
  55. table.setBounds (r.removeFromTop (table.getRowPosition (getNumRows() - 1, true).getBottom() + 20));
  56. Rectangle<int> buttonRow (r.removeFromTop (32).removeFromBottom (28));
  57. setCopyModeButton.setBounds (buttonRow.removeFromLeft (jmin (260, r.getWidth() / 3)));
  58. buttonRow.removeFromLeft (8);
  59. copyPathButton.setBounds (buttonRow.removeFromLeft (jmin (260, r.getWidth() / 3)));
  60. }
  61. int getNumRows() override
  62. {
  63. return project.getModules().getNumModules();
  64. }
  65. void paintRowBackground (Graphics& g, int /*rowNumber*/, int width, int height, bool rowIsSelected) override
  66. {
  67. g.setColour (rowIsSelected ? Colours::lightblue.withAlpha (0.4f)
  68. : Colours::white.withAlpha (0.4f));
  69. g.fillRect (0, 0, width, height - 1);
  70. }
  71. void paintCell (Graphics& g, int rowNumber, int columnId, int width, int height, bool /*rowIsSelected*/) override
  72. {
  73. String text;
  74. const String moduleID (project.getModules().getModuleID (rowNumber));
  75. if (columnId == nameCol)
  76. {
  77. text = moduleID;
  78. }
  79. else if (columnId == versionCol)
  80. {
  81. text = project.getModules().getModuleInfo (moduleID).getVersion();
  82. if (text.isEmpty())
  83. text = "?";
  84. }
  85. else if (columnId == copyCol)
  86. {
  87. text = project.getModules().shouldCopyModuleFilesLocally (moduleID).getValue()
  88. ? "Yes" : "No";
  89. }
  90. else if (columnId == pathCol)
  91. {
  92. StringArray paths;
  93. for (Project::ExporterIterator exporter (project); exporter.next();)
  94. paths.addIfNotAlreadyThere (exporter->getPathForModuleString (moduleID).trim());
  95. text = paths.joinIntoString (", ");
  96. }
  97. g.setColour (Colours::black);
  98. g.setFont (height * 0.65f);
  99. g.drawText (text, Rectangle<int> (width, height).reduced (4, 0), Justification::centredLeft, true);
  100. }
  101. void cellDoubleClicked (int rowNumber, int, const MouseEvent&) override
  102. {
  103. const String moduleID (project.getModules().getModuleID (rowNumber));
  104. if (moduleID.isNotEmpty())
  105. if (ProjectContentComponent* pcc = findParentComponentOfClass<ProjectContentComponent>())
  106. pcc->showModule (moduleID);
  107. }
  108. void deleteKeyPressed (int row) override
  109. {
  110. project.getModules().removeModule (project.getModules().getModuleID (row));
  111. }
  112. void buttonClicked (Button* b) override
  113. {
  114. if (b == &setCopyModeButton) showCopyModeMenu();
  115. if (b == &copyPathButton) showSetPathsMenu();
  116. }
  117. private:
  118. enum
  119. {
  120. nameCol = 1,
  121. versionCol,
  122. copyCol,
  123. pathCol
  124. };
  125. Project& project;
  126. ValueTree modulesValueTree;
  127. TableListBox table;
  128. TextButton setCopyModeButton, copyPathButton;
  129. std::map<String, var> modulePathClipboard;
  130. void valueTreePropertyChanged (ValueTree&, const Identifier&) override { itemChanged(); }
  131. void valueTreeChildAdded (ValueTree&, ValueTree&) override { itemChanged(); }
  132. void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override { itemChanged(); }
  133. void valueTreeChildOrderChanged (ValueTree&, int, int) override { itemChanged(); }
  134. void valueTreeParentChanged (ValueTree&) override { itemChanged(); }
  135. void itemChanged()
  136. {
  137. table.updateContent();
  138. resized();
  139. repaint();
  140. }
  141. void showCopyModeMenu()
  142. {
  143. PopupMenu m;
  144. m.addItem (1, "Set all modules to copy locally");
  145. m.addItem (2, "Set all modules to not copy locally");
  146. int res = m.showAt (&setCopyModeButton);
  147. if (res != 0)
  148. project.getModules().setLocalCopyModeForAllModules (res == 1);
  149. }
  150. void showSetPathsMenu()
  151. {
  152. enum
  153. {
  154. copyPathsToAllModulesID = 1,
  155. copyPathsID,
  156. pastePathsID
  157. };
  158. auto& moduleList = project.getModules();
  159. auto moduleToCopy = moduleList.getModuleID (table.getSelectedRow());
  160. if (moduleToCopy.isNotEmpty())
  161. {
  162. PopupMenu m;
  163. m.addItem (copyPathsToAllModulesID, "Copy the paths from the module '" + moduleToCopy + "' to all other modules");
  164. m.addItem (copyPathsID, "Copy paths from selected module", table.getNumSelectedRows() == 1);
  165. m.addItem (pastePathsID, "Paste paths to selected modules", ! modulePathClipboard.empty());
  166. int res = m.showAt (&copyPathButton);
  167. if (res == copyPathsToAllModulesID)
  168. {
  169. for (Project::ExporterIterator exporter (project); exporter.next();)
  170. {
  171. for (int i = 0; i < moduleList.getNumModules(); ++i)
  172. {
  173. auto modID = moduleList.getModuleID (i);
  174. if (modID != moduleToCopy)
  175. exporter->getPathForModuleValue (modID) = exporter->getPathForModuleValue (moduleToCopy).getValue();
  176. }
  177. }
  178. }
  179. else if (res == copyPathsID)
  180. {
  181. modulePathClipboard.clear();
  182. for (Project::ExporterIterator exporter (project); exporter.next();)
  183. modulePathClipboard[exporter->getName()] = exporter->getPathForModuleValue (moduleToCopy).getValue();
  184. }
  185. else if (res == pastePathsID)
  186. {
  187. for (int selectionId = 0; selectionId < table.getNumSelectedRows(); ++selectionId)
  188. {
  189. auto rowNumber = table.getSelectedRow (selectionId);
  190. auto modID = moduleList.getModuleID (rowNumber);
  191. for (Project::ExporterIterator exporter (project); exporter.next();)
  192. exporter->getPathForModuleValue (modID) = modulePathClipboard[exporter->getName()];
  193. }
  194. }
  195. table.repaint();
  196. }
  197. else
  198. {
  199. PopupMenu m;
  200. m.addItem (1, "(Select a module in the list above to use this option)", false);
  201. m.showAt (&copyPathButton);
  202. }
  203. }
  204. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ModulesPanel)
  205. };