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.

296 lines
9.3KB

  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. #pragma once
  20. //==========================================================================
  21. struct ProjectSettingsComponent : public Component,
  22. private ChangeListener
  23. {
  24. ProjectSettingsComponent (Project& p)
  25. : project (p),
  26. group (project.getProjectFilenameRoot(),
  27. Icon (getIcons().settings, Colours::transparentBlack))
  28. {
  29. addAndMakeVisible (group);
  30. updatePropertyList();
  31. project.addChangeListener (this);
  32. }
  33. ~ProjectSettingsComponent()
  34. {
  35. project.removeChangeListener (this);
  36. }
  37. void resized() override
  38. {
  39. group.updateSize (12, 0, getWidth() - 24);
  40. group.setBounds (getLocalBounds().reduced (12, 0));
  41. }
  42. void updatePropertyList()
  43. {
  44. PropertyListBuilder props;
  45. project.createPropertyEditors (props);
  46. group.setProperties (props);
  47. group.setName ("Project Settings");
  48. lastProjectType = project.getProjectTypeValue().getValue();
  49. parentSizeChanged();
  50. }
  51. void changeListenerCallback (ChangeBroadcaster*) override
  52. {
  53. if (lastProjectType != project.getProjectTypeValue().getValue())
  54. updatePropertyList();
  55. }
  56. void parentSizeChanged() override
  57. {
  58. const auto width = jmax (550, getParentWidth());
  59. auto y = group.updateSize (12, 0, width - 12);
  60. y = jmax (getParentHeight(), y);
  61. setSize (width, y);
  62. }
  63. Project& project;
  64. var lastProjectType;
  65. PropertyGroupComponent group;
  66. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectSettingsComponent)
  67. };
  68. //==============================================================================
  69. struct FileTreePanel : public TreePanelBase
  70. {
  71. FileTreePanel (Project& p)
  72. : TreePanelBase (&p, "fileTreeState")
  73. {
  74. tree.setMultiSelectEnabled (true);
  75. setRoot (new TreeItemTypes::GroupItem (p.getMainGroup()));
  76. tree.setRootItemVisible (false);
  77. }
  78. void updateMissingFileStatuses()
  79. {
  80. if (auto* p = dynamic_cast<TreeItemTypes::FileTreeItemBase*> (rootItem.get()))
  81. p->checkFileStatus();
  82. }
  83. };
  84. struct ModuleTreePanel : public TreePanelBase
  85. {
  86. ModuleTreePanel (Project& p)
  87. : TreePanelBase (&p, "moduleTreeState")
  88. {
  89. tree.setMultiSelectEnabled (false);
  90. setRoot (new TreeItemTypes::EnabledModulesItem (p));
  91. tree.setRootItemVisible (false);
  92. }
  93. };
  94. struct ExportersTreePanel : public TreePanelBase
  95. {
  96. ExportersTreePanel (Project& p)
  97. : TreePanelBase (&p, "exportersTreeState")
  98. {
  99. tree.setMultiSelectEnabled (false);
  100. setRoot (new TreeItemTypes::ExportersTreeRoot (p));
  101. tree.setRootItemVisible (false);
  102. }
  103. void deleteSelectedItems() override
  104. {
  105. for (int i = rootItem->getNumSubItems() - 1; i >= 0; --i)
  106. if (rootItem->getSubItem (i)->isSelected())
  107. if (auto* root = dynamic_cast<TreeItemTypes::ExportersTreeRoot*> (rootItem.get()))
  108. root->removeExporter (i);
  109. }
  110. };
  111. //==============================================================================
  112. class ProjectTab : public Component,
  113. private ChangeListener
  114. {
  115. public:
  116. ProjectTab (Project* p)
  117. : project (p)
  118. {
  119. addAndMakeVisible (concertinaPanel);
  120. buildConcertina();
  121. }
  122. ~ProjectTab()
  123. {
  124. getFileTreePanel()->saveOpenness();
  125. getModuleTreePanel()->saveOpenness();
  126. getExportersTreePanel()->saveOpenness();
  127. }
  128. void paint (Graphics& g) override
  129. {
  130. g.fillAll (findColour (secondaryBackgroundColourId));
  131. }
  132. void resized() override
  133. {
  134. concertinaPanel.setBounds (getLocalBounds().withTrimmedBottom (3));
  135. }
  136. TreePanelBase* getTreeWithSelectedItems()
  137. {
  138. for (int i = concertinaPanel.getNumPanels() - 1; i >= 0; --i)
  139. {
  140. if (auto* treeComponent = dynamic_cast<ConcertinaTreeComponent*> (concertinaPanel.getPanel (i)))
  141. {
  142. if (auto* base = treeComponent->getTree())
  143. if (base->tree.getNumSelectedItems() != 0)
  144. return base;
  145. }
  146. }
  147. return nullptr;
  148. }
  149. FileTreePanel* getFileTreePanel()
  150. {
  151. if (auto* panel = dynamic_cast<ConcertinaTreeComponent*> (concertinaPanel.getPanel (0)))
  152. return dynamic_cast<FileTreePanel*> (panel->getTree());
  153. return nullptr;
  154. }
  155. ModuleTreePanel* getModuleTreePanel()
  156. {
  157. if (auto* panel = dynamic_cast<ConcertinaTreeComponent*> (concertinaPanel.getPanel (1)))
  158. return dynamic_cast<ModuleTreePanel*> (panel->getTree());
  159. return nullptr;
  160. }
  161. ExportersTreePanel* getExportersTreePanel()
  162. {
  163. if (auto* panel = dynamic_cast<ConcertinaTreeComponent*> (concertinaPanel.getPanel (2)))
  164. return dynamic_cast<ExportersTreePanel*> (panel->getTree());
  165. return nullptr;
  166. }
  167. void showPanel (int panelIndex)
  168. {
  169. jassert (isPositiveAndBelow (panelIndex, concertinaPanel.getNumPanels()));
  170. concertinaPanel.expandPanelFully (concertinaPanel.getPanel (panelIndex), true);
  171. }
  172. void setPanelHeightProportion (int panelIndex, float prop)
  173. {
  174. jassert (isPositiveAndBelow (panelIndex, concertinaPanel.getNumPanels()));
  175. concertinaPanel.setPanelSize (concertinaPanel.getPanel (panelIndex),
  176. roundToInt (prop * (concertinaPanel.getHeight() - 90)), false);
  177. }
  178. float getPanelHeightProportion (int panelIndex)
  179. {
  180. jassert (isPositiveAndBelow (panelIndex, concertinaPanel.getNumPanels()));
  181. return ((float) (concertinaPanel.getPanel (panelIndex)->getHeight()) / (concertinaPanel.getHeight() - 90));
  182. }
  183. private:
  184. ConcertinaPanel concertinaPanel;
  185. OwnedArray<ConcertinaHeader> headers;
  186. Project* project = nullptr;
  187. //==============================================================================
  188. void changeListenerCallback (ChangeBroadcaster* source) override
  189. {
  190. if (auto* header = dynamic_cast<ConcertinaHeader*> (source))
  191. {
  192. auto index = headers.indexOf (header);
  193. concertinaPanel.expandPanelFully (concertinaPanel.getPanel (index), true);
  194. }
  195. }
  196. void buildConcertina()
  197. {
  198. for (int i = concertinaPanel.getNumPanels() - 1; i >= 0 ; --i)
  199. concertinaPanel.removePanel (concertinaPanel.getPanel (i));
  200. headers.clear();
  201. if (project != nullptr)
  202. {
  203. concertinaPanel.addPanel (0, new ConcertinaTreeComponent (new FileTreePanel (*project), true, false, true), true);
  204. concertinaPanel.addPanel (1, new ConcertinaTreeComponent (new ModuleTreePanel (*project), true, true), true);
  205. concertinaPanel.addPanel (2, new ConcertinaTreeComponent (new ExportersTreePanel (*project), true), true);
  206. }
  207. headers.add (new ConcertinaHeader ("File explorer", getIcons().fileExplorer));
  208. headers.add (new ConcertinaHeader ("Modules", getIcons().modules));
  209. headers.add (new ConcertinaHeader ("Exporters", getIcons().exporter));
  210. for (int i = 0; i < concertinaPanel.getNumPanels(); ++i)
  211. {
  212. auto* p = concertinaPanel.getPanel (i);
  213. auto* h = headers.getUnchecked (i);
  214. p->addMouseListener (this, true);
  215. h->addChangeListener (this);
  216. h->yPosition = i * 30;
  217. concertinaPanel.setCustomPanelHeader (p, h, false);
  218. concertinaPanel.setPanelHeaderSize (p, 30);
  219. }
  220. }
  221. void mouseDown (const MouseEvent& e) override
  222. {
  223. for (int i = concertinaPanel.getNumPanels() - 1; i >= 0; --i)
  224. {
  225. auto* p = concertinaPanel.getPanel (i);
  226. if (! (p->isParentOf (e.eventComponent)))
  227. {
  228. auto* base = dynamic_cast<TreePanelBase*> (p);
  229. if (base == nullptr)
  230. base = dynamic_cast<ConcertinaTreeComponent*> (p)->getTree();
  231. if (base != nullptr)
  232. base->tree.clearSelectedItems();
  233. }
  234. }
  235. }
  236. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectTab)
  237. };