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.

281 lines
9.5KB

  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 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&, int) override {}
  91. void valueTreeChildOrderChanged (ValueTree&, int, int) 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 isRoot() const override { return true; }
  139. bool isProjectSettings() const override { return true; }
  140. String getRenamingName() const override { return getDisplayName(); }
  141. String getDisplayName() const override { return project.getTitle(); }
  142. void setName (const String&) override {}
  143. bool isMissing() override { return false; }
  144. Icon getIcon() const override { return project.getMainGroup().getIcon().withContrastingColourTo (getBackgroundColour()); }
  145. void showDocument() override { showSettingsPage (new SettingsComp (project)); }
  146. bool canBeSelected() const override { return true; }
  147. bool mightContainSubItems() override { return project.getNumExporters() > 0; }
  148. String getUniqueName() const override { return "config_root"; }
  149. void addSubItems() override
  150. {
  151. addSubItem (new EnabledModulesItem (project));
  152. IntrojucerApp::getApp().addExtraConfigItems (project, *this);
  153. int i = 0;
  154. for (Project::ExporterIterator exporter (project); exporter.next(); ++i)
  155. addSubItem (new ExporterItem (project, exporter.exporter.release(), i));
  156. }
  157. void showPopupMenu() override
  158. {
  159. if (ProjectContentComponent* pcc = getProjectContentComponent())
  160. pcc->showNewExporterMenu();
  161. }
  162. bool isInterestedInDragSource (const DragAndDropTarget::SourceDetails& dragSourceDetails) override
  163. {
  164. return dragSourceDetails.description.toString().startsWith (getUniqueName());
  165. }
  166. void itemDropped (const DragAndDropTarget::SourceDetails& dragSourceDetails, int insertIndex) override
  167. {
  168. int oldIndex = dragSourceDetails.description.toString().getTrailingIntValue();
  169. exportersTree.moveChild (oldIndex, jmax (0, insertIndex - 1), project.getUndoManagerFor (exportersTree));
  170. }
  171. //==============================================================================
  172. void valueTreeChildAdded (ValueTree& parentTree, ValueTree&) override { refreshIfNeeded (parentTree); }
  173. void valueTreeChildRemoved (ValueTree& parentTree, ValueTree&, int) override { refreshIfNeeded (parentTree); }
  174. void valueTreeChildOrderChanged (ValueTree& parentTree, int, int) override { refreshIfNeeded (parentTree); }
  175. void refreshIfNeeded (ValueTree& changedTree)
  176. {
  177. if (changedTree == exportersTree)
  178. refreshSubItems();
  179. }
  180. private:
  181. Project& project;
  182. ValueTree exportersTree;
  183. //==============================================================================
  184. class SettingsComp : public Component,
  185. private ChangeListener
  186. {
  187. public:
  188. SettingsComp (Project& p) : project (p)
  189. {
  190. addAndMakeVisible (group);
  191. updatePropertyList();
  192. project.addChangeListener (this);
  193. }
  194. ~SettingsComp()
  195. {
  196. project.removeChangeListener (this);
  197. }
  198. void parentSizeChanged() override
  199. {
  200. updateSize (*this, group);
  201. }
  202. void updatePropertyList()
  203. {
  204. PropertyListBuilder props;
  205. project.createPropertyEditors (props);
  206. group.setProperties (props);
  207. group.setName ("Project Settings");
  208. lastProjectType = project.getProjectTypeValue().getValue();
  209. parentSizeChanged();
  210. }
  211. void changeListenerCallback (ChangeBroadcaster*) override
  212. {
  213. if (lastProjectType != project.getProjectTypeValue().getValue())
  214. updatePropertyList();
  215. }
  216. private:
  217. Project& project;
  218. var lastProjectType;
  219. PropertyGroupComponent group;
  220. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SettingsComp)
  221. };
  222. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RootItem)
  223. };