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.

415 lines
13KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../../jucer_Headers.h"
  19. #include "jucer_ComponentEditor.h"
  20. #include "jucer_ComponentEditorTreeView.h"
  21. #include "jucer_ComponentEditorCodeView.h"
  22. #include "jucer_ComponentEditorToolbar.h"
  23. //==============================================================================
  24. class ComponentEditor::ClassInfoHolder : public Component
  25. {
  26. public:
  27. ClassInfoHolder (ComponentEditor& editor_)
  28. : editor (editor_)
  29. {
  30. addAndMakeVisible (panel = new PropertyPanelWithTooltips());
  31. Array <PropertyComponent*> props;
  32. editor.getDocument().createClassProperties (props);
  33. panel->getPanel()->addSection ("Component Properties", props, true);
  34. }
  35. ~ClassInfoHolder()
  36. {
  37. deleteAllChildren();
  38. }
  39. void resized()
  40. {
  41. panel->setBounds (getLocalBounds());
  42. }
  43. private:
  44. ComponentEditor& editor;
  45. PropertyPanelWithTooltips* panel;
  46. };
  47. //==============================================================================
  48. class ComponentEditor::LayoutEditorHolder : public Component
  49. {
  50. public:
  51. LayoutEditorHolder (ComponentEditor& editor_)
  52. : toolbarFactory (editor_), editor (editor_), infoPanel (0), tree (0)
  53. {
  54. addAndMakeVisible (toolbar = new Toolbar());
  55. toolbar->addDefaultItems (toolbarFactory);
  56. toolbar->setStyle (Toolbar::textOnly);
  57. addAndMakeVisible (viewport = new Viewport());
  58. addChildComponent (tree = new TreeView());
  59. tree->setRootItemVisible (true);
  60. tree->setMultiSelectEnabled (true);
  61. tree->setDefaultOpenness (true);
  62. tree->setColour (TreeView::backgroundColourId, Colours::white);
  63. tree->setIndentSize (15);
  64. }
  65. ~LayoutEditorHolder()
  66. {
  67. tree->deleteRootItem();
  68. deleteAndZero (infoPanel);
  69. deleteAllChildren();
  70. }
  71. void createCanvas()
  72. {
  73. viewport->setViewedComponent (new ComponentEditorCanvas (editor));
  74. addAndMakeVisible (infoPanel = new InfoPanel (editor));
  75. tree->setRootItem (new ComponentEditorTreeView::Root (editor));
  76. resized();
  77. }
  78. void resized()
  79. {
  80. const int toolbarHeight = 22;
  81. toolbar->setBounds (0, 0, getWidth(), toolbarHeight);
  82. int infoPanelWidth = 200;
  83. if (infoPanel != 0 && infoPanel->isVisible())
  84. infoPanel->setBounds (getWidth() - infoPanelWidth, toolbar->getBottom(), infoPanelWidth, getHeight() - toolbar->getBottom());
  85. else
  86. infoPanelWidth = 0;
  87. if (tree->isVisible())
  88. {
  89. tree->setBounds (0, toolbar->getBottom(), infoPanelWidth, getHeight() - toolbar->getBottom());
  90. viewport->setBounds (infoPanelWidth, toolbar->getBottom(), getWidth() - infoPanelWidth * 2, getHeight() - toolbar->getBottom());
  91. }
  92. else
  93. {
  94. viewport->setBounds (0, toolbar->getBottom(), getWidth() - infoPanelWidth, getHeight() - toolbar->getBottom());
  95. }
  96. }
  97. void showOrHideProperties()
  98. {
  99. infoPanel->setVisible (! infoPanel->isVisible());
  100. resized();
  101. }
  102. void showOrHideTree()
  103. {
  104. tree->setVisible (! tree->isVisible());
  105. resized();
  106. }
  107. Viewport* getViewport() const { return viewport; }
  108. private:
  109. //==============================================================================
  110. class InfoPanel : public Component,
  111. public ChangeListener
  112. {
  113. public:
  114. InfoPanel (ComponentEditor& editor_)
  115. : editor (editor_)
  116. {
  117. setOpaque (true);
  118. addAndMakeVisible (props = new PropertyPanel());
  119. editor.getCanvas()->getSelection().addChangeListener (this);
  120. }
  121. ~InfoPanel()
  122. {
  123. editor.getCanvas()->getSelection().removeChangeListener (this);
  124. props->clear();
  125. deleteAllChildren();
  126. }
  127. void changeListenerCallback (void*)
  128. {
  129. Array <PropertyComponent*> newComps;
  130. editor.getCanvas()->getSelectedItemProperties (newComps);
  131. props->clear();
  132. props->addProperties (newComps);
  133. }
  134. void paint (Graphics& g)
  135. {
  136. g.fillAll (Colour::greyLevel (0.92f));
  137. }
  138. void resized()
  139. {
  140. props->setSize (getWidth(), getHeight());
  141. }
  142. private:
  143. ComponentEditor& editor;
  144. PropertyPanel* props;
  145. };
  146. Toolbar* toolbar;
  147. ComponentEditorToolbarFactory toolbarFactory;
  148. ComponentEditor& editor;
  149. Viewport* viewport;
  150. InfoPanel* infoPanel;
  151. TreeView* tree;
  152. };
  153. //==============================================================================
  154. class ComponentEditor::BackgroundEditorHolder : public Component
  155. {
  156. public:
  157. BackgroundEditorHolder (ComponentEditor& editor_)
  158. : editor (editor_)
  159. {
  160. }
  161. ~BackgroundEditorHolder()
  162. {
  163. }
  164. private:
  165. ComponentEditor& editor;
  166. };
  167. //==============================================================================
  168. ComponentEditor::ComponentEditor (OpenDocumentManager::Document* document,
  169. Project* project_, ComponentDocument* componentDocument_)
  170. : DocumentEditorComponent (document),
  171. project (project_),
  172. componentDocument (componentDocument_),
  173. classInfoHolder (0),
  174. layoutEditorHolder (0),
  175. backgroundEditorHolder (0),
  176. codeEditorHolder (0)
  177. {
  178. setOpaque (true);
  179. if (componentDocument != 0)
  180. {
  181. classInfoHolder = new ClassInfoHolder (*this);
  182. layoutEditorHolder = new LayoutEditorHolder (*this);
  183. backgroundEditorHolder = new BackgroundEditorHolder (*this);
  184. codeEditorHolder = new CodeEditorHolder (*this);
  185. layoutEditorHolder->createCanvas();
  186. }
  187. addAndMakeVisible (tabs = new TabbedComponent (TabbedButtonBar::TabsAtRight));
  188. tabs->setTabBarDepth (22);
  189. tabs->addTab ("Class Settings", Colour::greyLevel (0.88f), classInfoHolder, true);
  190. tabs->addTab ("Components", Colours::white, layoutEditorHolder, true);
  191. tabs->addTab ("Background", Colours::white, backgroundEditorHolder, true);
  192. tabs->addTab ("Source Code", Colours::white, codeEditorHolder, true);
  193. tabs->setCurrentTabIndex (1);
  194. }
  195. ComponentEditor::~ComponentEditor()
  196. {
  197. deleteAllChildren();
  198. }
  199. void ComponentEditor::paint (Graphics& g)
  200. {
  201. g.fillAll (Colours::white);
  202. }
  203. void ComponentEditor::resized()
  204. {
  205. tabs->setBounds (getLocalBounds());
  206. }
  207. ComponentEditorCanvas* ComponentEditor::getCanvas() const
  208. {
  209. return dynamic_cast <ComponentEditorCanvas*> (getViewport()->getViewedComponent());
  210. }
  211. Viewport* ComponentEditor::getViewport() const
  212. {
  213. return layoutEditorHolder->getViewport();
  214. }
  215. //==============================================================================
  216. class TestComponent : public ComponentEditorCanvas::ComponentHolder
  217. {
  218. public:
  219. TestComponent (ComponentDocument& document_)
  220. : document (document_)
  221. {
  222. setSize (document.getCanvasWidth().getValue(),
  223. document.getCanvasHeight().getValue());
  224. }
  225. ~TestComponent()
  226. {
  227. }
  228. void resized()
  229. {
  230. document.getCanvasWidth() = getWidth();
  231. document.getCanvasHeight() = getHeight();
  232. ComponentEditorCanvas::ComponentHolder::resized();
  233. updateComponents (document, selected);
  234. }
  235. private:
  236. ComponentDocument document;
  237. ComponentEditorCanvas::SelectedItems selected;
  238. TooltipWindow tooltipWindow;
  239. };
  240. void ComponentEditor::test()
  241. {
  242. TestComponent testComp (getDocument());
  243. DialogWindow::showModalDialog ("Testing: " + getDocument().getClassName().toString(),
  244. &testComp, this, Colours::lightgrey, true, true);
  245. }
  246. //==============================================================================
  247. void ComponentEditor::getAllCommands (Array <CommandID>& commands)
  248. {
  249. DocumentEditorComponent::getAllCommands (commands);
  250. const CommandID ids[] = { CommandIDs::undo,
  251. CommandIDs::redo,
  252. CommandIDs::toFront,
  253. CommandIDs::toBack,
  254. CommandIDs::test,
  255. CommandIDs::showOrHideProperties,
  256. CommandIDs::showOrHideTree,
  257. StandardApplicationCommandIDs::del };
  258. commands.addArray (ids, numElementsInArray (ids));
  259. }
  260. void ComponentEditor::getCommandInfo (CommandID commandID, ApplicationCommandInfo& result)
  261. {
  262. result.setActive (document != 0);
  263. switch (commandID)
  264. {
  265. case CommandIDs::undo:
  266. result.setInfo ("Undo", "Undoes the last change", CommandCategories::general, 0);
  267. result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::commandModifier, 0));
  268. break;
  269. case CommandIDs::redo:
  270. result.setInfo ("Redo", "Redoes the last change", CommandCategories::general, 0);
  271. result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0));
  272. result.defaultKeypresses.add (KeyPress ('y', ModifierKeys::commandModifier, 0));
  273. break;
  274. case CommandIDs::toFront:
  275. result.setInfo ("Bring to Front", "Brings the selected items to the front", CommandCategories::editing, 0);
  276. break;
  277. case CommandIDs::toBack:
  278. result.setInfo ("Send to Back", "Moves the selected items to the back", CommandCategories::editing, 0);
  279. break;
  280. case CommandIDs::test:
  281. result.setInfo ("Test", "Test the current component", CommandCategories::editing, 0);
  282. result.defaultKeypresses.add (KeyPress ('t', ModifierKeys::commandModifier, 0));
  283. break;
  284. case CommandIDs::showOrHideProperties:
  285. result.setInfo ("Show/Hide Tree", "Shows or hides the component tree view", CommandCategories::editing, 0);
  286. break;
  287. case CommandIDs::showOrHideTree:
  288. result.setInfo ("Show/Hide Properties", "Shows or hides the component properties panel", CommandCategories::editing, 0);
  289. break;
  290. case StandardApplicationCommandIDs::del:
  291. result.setInfo ("Delete", String::empty, CommandCategories::general, 0);
  292. result.defaultKeypresses.add (KeyPress (KeyPress::deleteKey, 0, 0));
  293. result.defaultKeypresses.add (KeyPress (KeyPress::backspaceKey, 0, 0));
  294. break;
  295. default:
  296. DocumentEditorComponent::getCommandInfo (commandID, result);
  297. break;
  298. }
  299. }
  300. bool ComponentEditor::perform (const InvocationInfo& info)
  301. {
  302. switch (info.commandID)
  303. {
  304. case CommandIDs::undo:
  305. getDocument().getUndoManager()->undo();
  306. return true;
  307. case CommandIDs::redo:
  308. getDocument().getUndoManager()->redo();
  309. return true;
  310. case CommandIDs::toFront:
  311. getCanvas()->selectionToFront();
  312. return true;
  313. case CommandIDs::toBack:
  314. getCanvas()->selectionToBack();
  315. return true;
  316. case CommandIDs::test:
  317. test();
  318. return true;
  319. case CommandIDs::showOrHideProperties:
  320. layoutEditorHolder->showOrHideProperties();
  321. return true;
  322. case CommandIDs::showOrHideTree:
  323. layoutEditorHolder->showOrHideTree();
  324. return true;
  325. case StandardApplicationCommandIDs::del:
  326. getCanvas()->deleteSelection();
  327. return true;
  328. default:
  329. break;
  330. }
  331. return DocumentEditorComponent::perform (info);
  332. }