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.

297 lines
9.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software 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 PropertyGroupComponent : public Component
  18. {
  19. public:
  20. PropertyGroupComponent() {}
  21. void setProperties (const PropertyListBuilder& newProps)
  22. {
  23. properties.clear();
  24. properties.addArray (newProps.components);
  25. for (int i = properties.size(); --i >= 0;)
  26. addAndMakeVisible (properties.getUnchecked(i));
  27. }
  28. int updateSize (int x, int y, int width)
  29. {
  30. int height = 38;
  31. for (int i = 0; i < properties.size(); ++i)
  32. {
  33. PropertyComponent* pp = properties.getUnchecked(i);
  34. pp->setBounds (10, height, width - 20, pp->getPreferredHeight());
  35. height += pp->getHeight();
  36. }
  37. height += 16;
  38. setBounds (x, y, width, height);
  39. return height;
  40. }
  41. void paint (Graphics& g) override
  42. {
  43. const Colour bkg (findColour (mainBackgroundColourId));
  44. g.setColour (Colours::white.withAlpha (0.35f));
  45. g.fillRect (0, 30, getWidth(), getHeight() - 38);
  46. g.setFont (Font (15.0f, Font::bold));
  47. g.setColour (bkg.contrasting (0.7f));
  48. g.drawFittedText (getName(), 12, 0, getWidth() - 16, 25, Justification::bottomLeft, 1);
  49. }
  50. OwnedArray<PropertyComponent> properties;
  51. private:
  52. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyGroupComponent)
  53. };
  54. //==============================================================================
  55. class ConfigTreeItemBase : public JucerTreeViewBase,
  56. public ValueTree::Listener
  57. {
  58. public:
  59. ConfigTreeItemBase() {}
  60. void showSettingsPage (Component* content)
  61. {
  62. content->setComponentID (getUniqueName());
  63. ScopedPointer<Component> comp (content);
  64. if (ProjectContentComponent* pcc = getProjectContentComponent())
  65. pcc->setEditorComponent (new PropertyPanelViewport (comp.release()), nullptr);
  66. }
  67. void closeSettingsPage()
  68. {
  69. if (ProjectContentComponent* pcc = getProjectContentComponent())
  70. {
  71. if (PropertyPanelViewport* ppv = dynamic_cast<PropertyPanelViewport*> (pcc->getEditorComponent()))
  72. if (ppv->viewport.getViewedComponent()->getComponentID() == getUniqueName())
  73. pcc->hideEditor();
  74. }
  75. }
  76. void deleteAllSelectedItems() override
  77. {
  78. TreeView* const tree = getOwnerView();
  79. jassert (tree->getNumSelectedItems() <= 1); // multi-select should be disabled
  80. if (ConfigTreeItemBase* s = dynamic_cast<ConfigTreeItemBase*> (tree->getSelectedItem (0)))
  81. s->deleteItem();
  82. }
  83. void itemOpennessChanged (bool isNowOpen) override
  84. {
  85. if (isNowOpen)
  86. refreshSubItems();
  87. }
  88. void valueTreePropertyChanged (ValueTree&, const Identifier&) override {}
  89. void valueTreeChildAdded (ValueTree&, ValueTree&) override {}
  90. void valueTreeChildRemoved (ValueTree&, ValueTree&) override {}
  91. void valueTreeChildOrderChanged (ValueTree&) override {}
  92. void valueTreeParentChanged (ValueTree&) override {}
  93. virtual bool isProjectSettings() const { return false; }
  94. virtual bool isModulesList() const { return false; }
  95. static void updateSize (Component& comp, PropertyGroupComponent& group)
  96. {
  97. const int width = jmax (550, comp.getParentWidth() - 20);
  98. int y = 0;
  99. y += group.updateSize (12, y, width - 12);
  100. comp.setSize (width, y);
  101. }
  102. private:
  103. //==============================================================================
  104. class PropertyPanelViewport : public Component
  105. {
  106. public:
  107. PropertyPanelViewport (Component* content)
  108. {
  109. addAndMakeVisible (viewport);
  110. addAndMakeVisible (rolloverHelp);
  111. viewport.setViewedComponent (content, true);
  112. }
  113. void paint (Graphics& g) override
  114. {
  115. IntrojucerLookAndFeel::fillWithBackgroundTexture (*this, g);
  116. }
  117. void resized() override
  118. {
  119. Rectangle<int> r (getLocalBounds());
  120. rolloverHelp.setBounds (r.removeFromBottom (70).reduced (10, 0));
  121. viewport.setBounds (r);
  122. }
  123. Viewport viewport;
  124. RolloverHelpComp rolloverHelp;
  125. private:
  126. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyPanelViewport)
  127. };
  128. };
  129. //==============================================================================
  130. class RootItem : public ConfigTreeItemBase
  131. {
  132. public:
  133. RootItem (Project& p)
  134. : project (p), exportersTree (p.getExporters())
  135. {
  136. exportersTree.addListener (this);
  137. }
  138. bool isProjectSettings() const override { return true; }
  139. String getRenamingName() const override { return getDisplayName(); }
  140. String getDisplayName() const override { return project.getTitle(); }
  141. void setName (const String&) override {}
  142. bool isMissing() override { return false; }
  143. Icon getIcon() const override { return project.getMainGroup().getIcon().withContrastingColourTo (getBackgroundColour()); }
  144. void showDocument() override { showSettingsPage (new SettingsComp (project)); }
  145. bool canBeSelected() const override { return true; }
  146. bool mightContainSubItems() override { return project.getNumExporters() > 0; }
  147. String getUniqueName() const override { return "config_root"; }
  148. void addSubItems() override
  149. {
  150. addSubItem (new EnabledModulesItem (project));
  151. IntrojucerApp::getApp().addExtraConfigItems (project, *this);
  152. int i = 0;
  153. for (Project::ExporterIterator exporter (project); exporter.next(); ++i)
  154. addSubItem (new ExporterItem (project, exporter.exporter.release(), i));
  155. }
  156. void showPopupMenu() override
  157. {
  158. PopupMenu menu;
  159. const StringArray exporters (ProjectExporter::getExporterNames());
  160. for (int i = 0; i < exporters.size(); ++i)
  161. menu.addItem (i + 1, "Create a new " + exporters[i] + " target");
  162. launchPopupMenu (menu);
  163. }
  164. void handlePopupMenuResult (int resultCode) override
  165. {
  166. if (resultCode > 0)
  167. {
  168. String exporterName (ProjectExporter::getExporterNames() [resultCode - 1]);
  169. if (exporterName.isNotEmpty())
  170. project.addNewExporter (exporterName);
  171. }
  172. }
  173. bool isInterestedInDragSource (const DragAndDropTarget::SourceDetails& dragSourceDetails) override
  174. {
  175. return dragSourceDetails.description.toString().startsWith (getUniqueName());
  176. }
  177. void itemDropped (const DragAndDropTarget::SourceDetails& dragSourceDetails, int insertIndex) override
  178. {
  179. int oldIndex = dragSourceDetails.description.toString().getTrailingIntValue();
  180. exportersTree.moveChild (oldIndex, jmax (0, insertIndex - 1), project.getUndoManagerFor (exportersTree));
  181. }
  182. //==============================================================================
  183. void valueTreeChildAdded (ValueTree& parentTree, ValueTree&) override { refreshIfNeeded (parentTree); }
  184. void valueTreeChildRemoved (ValueTree& parentTree, ValueTree&) override { refreshIfNeeded (parentTree); }
  185. void valueTreeChildOrderChanged (ValueTree& parentTree) override { refreshIfNeeded (parentTree); }
  186. void refreshIfNeeded (ValueTree& changedTree)
  187. {
  188. if (changedTree == exportersTree)
  189. refreshSubItems();
  190. }
  191. private:
  192. Project& project;
  193. ValueTree exportersTree;
  194. //==============================================================================
  195. class SettingsComp : public Component,
  196. private ChangeListener
  197. {
  198. public:
  199. SettingsComp (Project& p) : project (p)
  200. {
  201. addAndMakeVisible (group);
  202. updatePropertyList();
  203. project.addChangeListener (this);
  204. }
  205. ~SettingsComp()
  206. {
  207. project.removeChangeListener (this);
  208. }
  209. void parentSizeChanged() override
  210. {
  211. updateSize (*this, group);
  212. }
  213. void updatePropertyList()
  214. {
  215. PropertyListBuilder props;
  216. project.createPropertyEditors (props);
  217. group.setProperties (props);
  218. group.setName ("Project Settings");
  219. lastProjectType = project.getProjectTypeValue().getValue();
  220. parentSizeChanged();
  221. }
  222. void changeListenerCallback (ChangeBroadcaster*) override
  223. {
  224. if (lastProjectType != project.getProjectTypeValue().getValue())
  225. updatePropertyList();
  226. }
  227. private:
  228. Project& project;
  229. var lastProjectType;
  230. PropertyGroupComponent group;
  231. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SettingsComp)
  232. };
  233. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RootItem)
  234. };