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.

920 lines
30KB

  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_JucerTreeViewBase.h"
  21. //==============================================================================
  22. namespace ComponentTree
  23. {
  24. //==============================================================================
  25. class Base : public JucerTreeViewBase,
  26. public ValueTree::Listener,
  27. public ChangeListener
  28. {
  29. public:
  30. Base (ComponentEditor& editor_)
  31. : editor (editor_)
  32. {
  33. editor.getCanvas()->getSelection().addChangeListener (this);
  34. }
  35. ~Base()
  36. {
  37. editor.getCanvas()->getSelection().removeChangeListener (this);
  38. }
  39. //==============================================================================
  40. void valueTreePropertyChanged (ValueTree& tree, const var::identifier& property) {}
  41. void valueTreeParentChanged (ValueTree& tree) {}
  42. void valueTreeChildrenChanged (ValueTree& tree) {}
  43. const String getUniqueName() const
  44. {
  45. jassert (getItemId().isNotEmpty());
  46. return getItemId();
  47. }
  48. //==============================================================================
  49. void itemOpennessChanged (bool isNowOpen)
  50. {
  51. if (isNowOpen)
  52. refreshSubItems();
  53. }
  54. virtual void refreshSubItems() = 0;
  55. virtual const String getItemId() const = 0;
  56. void setName (const String& newName) {}
  57. void itemClicked (const MouseEvent& e) {}
  58. void itemDoubleClicked (const MouseEvent& e) {}
  59. void itemSelectionChanged (bool isNowSelected)
  60. {
  61. if (isNowSelected)
  62. editor.getCanvas()->getSelection().addToSelection (getItemId());
  63. else
  64. editor.getCanvas()->getSelection().deselect (getItemId());
  65. }
  66. void changeListenerCallback (void*) { updateSelectionState(); }
  67. void updateSelectionState()
  68. {
  69. setSelected (editor.getCanvas()->getSelection().isSelected (getItemId()), false);
  70. }
  71. bool isMissing() { return false; }
  72. const String getTooltip() { return String::empty; }
  73. protected:
  74. //==============================================================================
  75. ComponentEditor& editor;
  76. };
  77. //==============================================================================
  78. class ComponentItem : public Base
  79. {
  80. public:
  81. ComponentItem (ComponentEditor& editor_, const ValueTree& componentState_)
  82. : Base (editor_), componentState (componentState_)
  83. {
  84. componentState.addListener (this);
  85. updateSelectionState();
  86. }
  87. ~ComponentItem()
  88. {
  89. componentState.removeListener (this);
  90. }
  91. //==============================================================================
  92. const String getItemId() const { return componentState [ComponentDocument::idProperty]; }
  93. bool mightContainSubItems() { return false; }
  94. void refreshSubItems() {}
  95. const String getDisplayName() const { return getRenamingName(); }
  96. const String getRenamingName() const { return componentState [ComponentDocument::memberNameProperty]; }
  97. Image* getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultDocumentFileImage(); }
  98. const String getDragSourceDescription() { return componentItemDragType; }
  99. void valueTreePropertyChanged (ValueTree& tree, const var::identifier& property)
  100. {
  101. if (property == ComponentDocument::memberNameProperty)
  102. repaintItem();
  103. }
  104. private:
  105. //==============================================================================
  106. ValueTree componentState;
  107. };
  108. //==============================================================================
  109. class ComponentList : public Base
  110. {
  111. public:
  112. ComponentList (ComponentEditor& editor_)
  113. : Base (editor_), componentTree (editor.getDocument().getComponentGroup())
  114. {
  115. componentTree.addListener (this);
  116. }
  117. ~ComponentList()
  118. {
  119. componentTree.removeListener (this);
  120. }
  121. //==============================================================================
  122. const String getItemId() const { return "components"; }
  123. bool mightContainSubItems() { return true; }
  124. void valueTreeChildrenChanged (ValueTree& tree)
  125. {
  126. if (tree == componentTree)
  127. refreshSubItems();
  128. }
  129. void refreshSubItems()
  130. {
  131. ScopedPointer <XmlElement> openness (getOpennessState());
  132. clearSubItems();
  133. ComponentDocument& doc = editor.getDocument();
  134. const int num = doc.getNumComponents();
  135. for (int i = 0; i < num; ++i)
  136. addSubItem (new ComponentItem (editor, doc.getComponent (i)));
  137. if (openness != 0)
  138. restoreOpennessState (*openness);
  139. }
  140. const String getDisplayName() const { return getRenamingName(); }
  141. const String getRenamingName() const { return "Components"; }
  142. Image* getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultFolderImage(); }
  143. const String getDragSourceDescription() { return String::empty; }
  144. private:
  145. ValueTree componentTree;
  146. };
  147. //==============================================================================
  148. class MarkerItem : public Base
  149. {
  150. public:
  151. MarkerItem (ComponentEditor& editor_, const ValueTree& markerState_)
  152. : Base (editor_), markerState (markerState_)
  153. {
  154. markerState.addListener (this);
  155. updateSelectionState();
  156. }
  157. ~MarkerItem()
  158. {
  159. markerState.removeListener (this);
  160. }
  161. //==============================================================================
  162. const String getItemId() const { return markerState [ComponentDocument::idProperty]; }
  163. bool mightContainSubItems() { return false; }
  164. void refreshSubItems() {}
  165. const String getDisplayName() const { return getRenamingName(); }
  166. const String getRenamingName() const { return markerState [ComponentDocument::markerNameProperty]; }
  167. Image* getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultDocumentFileImage(); }
  168. const String getDragSourceDescription() { return componentItemDragType; }
  169. void valueTreePropertyChanged (ValueTree& tree, const var::identifier& property)
  170. {
  171. if (property == ComponentDocument::markerNameProperty)
  172. repaintItem();
  173. }
  174. private:
  175. //==============================================================================
  176. ValueTree markerState;
  177. };
  178. //==============================================================================
  179. class MarkerList : public Base
  180. {
  181. public:
  182. MarkerList (ComponentEditor& editor_, bool isX_)
  183. : Base (editor_), markerList (editor_.getDocument().getMarkerList (isX_).getGroup()), isX (isX_)
  184. {
  185. markerList.addListener (this);
  186. }
  187. ~MarkerList()
  188. {
  189. markerList.removeListener (this);
  190. }
  191. //==============================================================================
  192. const String getItemId() const { return isX ? "markersX" : "markersY"; }
  193. bool mightContainSubItems() { return true; }
  194. void valueTreeChildrenChanged (ValueTree& tree)
  195. {
  196. refreshSubItems();
  197. }
  198. void refreshSubItems()
  199. {
  200. ScopedPointer <XmlElement> openness (getOpennessState());
  201. clearSubItems();
  202. ComponentDocument::MarkerList& markers = editor.getDocument().getMarkerList (isX);
  203. const int num = markers.size();
  204. for (int i = 0; i < num; ++i)
  205. addSubItem (new MarkerItem (editor, markers.getMarker (i)));
  206. if (openness != 0)
  207. restoreOpennessState (*openness);
  208. }
  209. const String getDisplayName() const { return getRenamingName(); }
  210. const String getRenamingName() const { return isX ? "Markers (X-axis)" : "Markers (Y-axis)"; }
  211. Image* getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultFolderImage(); }
  212. const String getDragSourceDescription() { return String::empty; }
  213. private:
  214. ValueTree markerList;
  215. bool isX;
  216. };
  217. //==============================================================================
  218. class Root : public Base
  219. {
  220. public:
  221. Root (ComponentEditor& editor_) : Base (editor_) {}
  222. ~Root() {}
  223. //==============================================================================
  224. const String getItemId() const { return "root"; }
  225. bool mightContainSubItems() { return true; }
  226. void refreshSubItems()
  227. {
  228. ScopedPointer <XmlElement> openness (getOpennessState());
  229. clearSubItems();
  230. addSubItem (new ComponentList (editor));
  231. addSubItem (new MarkerList (editor, true));
  232. addSubItem (new MarkerList (editor, false));
  233. if (openness != 0)
  234. restoreOpennessState (*openness);
  235. }
  236. const String getDisplayName() const { return getRenamingName(); }
  237. const String getRenamingName() const { return editor.getDocument().getClassName().toString(); }
  238. Image* getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultFolderImage(); }
  239. const String getDragSourceDescription() { return String::empty; }
  240. };
  241. }
  242. //==============================================================================
  243. class ComponentEditor::ClassInfoHolder : public Component
  244. {
  245. public:
  246. ClassInfoHolder (ComponentEditor& editor_)
  247. : editor (editor_)
  248. {
  249. addAndMakeVisible (panel = new PropertyPanelWithTooltips());
  250. Array <PropertyComponent*> props;
  251. editor.getDocument().createClassProperties (props);
  252. panel->getPanel()->addSection ("Component Properties", props, true);
  253. }
  254. ~ClassInfoHolder()
  255. {
  256. deleteAllChildren();
  257. }
  258. void resized()
  259. {
  260. panel->setBounds (getLocalBounds());
  261. }
  262. private:
  263. ComponentEditor& editor;
  264. PropertyPanelWithTooltips* panel;
  265. };
  266. //==============================================================================
  267. class ComponentEditor::LayoutEditorHolder : public Component,
  268. public ToolbarItemFactory
  269. {
  270. public:
  271. LayoutEditorHolder (ComponentEditor& editor_)
  272. : editor (editor_), infoPanel (0), tree (0)
  273. {
  274. addAndMakeVisible (toolbar = new Toolbar());
  275. toolbar->addDefaultItems (*this);
  276. toolbar->setStyle (Toolbar::textOnly);
  277. addAndMakeVisible (viewport = new Viewport());
  278. addChildComponent (tree = new TreeView());
  279. tree->setRootItemVisible (true);
  280. tree->setMultiSelectEnabled (true);
  281. tree->setDefaultOpenness (true);
  282. tree->setColour (TreeView::backgroundColourId, Colours::white);
  283. tree->setIndentSize (15);
  284. }
  285. ~LayoutEditorHolder()
  286. {
  287. tree->deleteRootItem();
  288. deleteAndZero (infoPanel);
  289. deleteAllChildren();
  290. }
  291. void createCanvas()
  292. {
  293. viewport->setViewedComponent (new ComponentEditorCanvas (editor));
  294. addAndMakeVisible (infoPanel = new InfoPanel (editor));
  295. tree->setRootItem (new ComponentTree::Root (editor));
  296. resized();
  297. }
  298. void resized()
  299. {
  300. const int toolbarHeight = 22;
  301. toolbar->setBounds (0, 0, getWidth(), toolbarHeight);
  302. int infoPanelWidth = 200;
  303. if (infoPanel != 0 && infoPanel->isVisible())
  304. infoPanel->setBounds (getWidth() - infoPanelWidth, toolbar->getBottom(), infoPanelWidth, getHeight() - toolbar->getBottom());
  305. else
  306. infoPanelWidth = 0;
  307. if (tree->isVisible())
  308. {
  309. tree->setBounds (0, toolbar->getBottom(), infoPanelWidth, getHeight() - toolbar->getBottom());
  310. viewport->setBounds (infoPanelWidth, toolbar->getBottom(), getWidth() - infoPanelWidth * 2, getHeight() - toolbar->getBottom());
  311. }
  312. else
  313. {
  314. viewport->setBounds (0, toolbar->getBottom(), getWidth() - infoPanelWidth, getHeight() - toolbar->getBottom());
  315. }
  316. }
  317. void showOrHideProperties()
  318. {
  319. infoPanel->setVisible (! infoPanel->isVisible());
  320. resized();
  321. }
  322. void showOrHideTree()
  323. {
  324. tree->setVisible (! tree->isVisible());
  325. resized();
  326. }
  327. Viewport* getViewport() const { return viewport; }
  328. //==============================================================================
  329. enum DemoToolbarItemIds
  330. {
  331. createComponent = 1,
  332. showInfo = 2,
  333. showComponentTree = 3,
  334. };
  335. void getAllToolbarItemIds (Array <int>& ids)
  336. {
  337. ids.add (createComponent);
  338. ids.add (showInfo);
  339. ids.add (showComponentTree);
  340. ids.add (separatorBarId);
  341. ids.add (spacerId);
  342. ids.add (flexibleSpacerId);
  343. }
  344. void getDefaultItemSet (Array <int>& ids)
  345. {
  346. ids.add (createComponent);
  347. ids.add (flexibleSpacerId);
  348. ids.add (showInfo);
  349. ids.add (showComponentTree);
  350. }
  351. ToolbarItemComponent* createItem (int itemId)
  352. {
  353. String name;
  354. int commandId = 0;
  355. switch (itemId)
  356. {
  357. case createComponent: name = "new"; break;
  358. case showInfo: name = "info"; commandId = CommandIDs::showOrHideProperties; break;
  359. case showComponentTree: name = "tree"; commandId = CommandIDs::showOrHideTree; break;
  360. default: jassertfalse; return 0;
  361. }
  362. ToolbarButton* b = new ToolbarButton (itemId, name, new DrawablePath(), 0);
  363. b->setCommandToTrigger (commandManager, commandId, true);
  364. return b;
  365. }
  366. private:
  367. //==============================================================================
  368. class InfoPanel : public Component,
  369. public ChangeListener
  370. {
  371. public:
  372. InfoPanel (ComponentEditor& editor_)
  373. : editor (editor_)
  374. {
  375. setOpaque (true);
  376. addAndMakeVisible (props = new PropertyPanel());
  377. editor.getCanvas()->getSelection().addChangeListener (this);
  378. }
  379. ~InfoPanel()
  380. {
  381. editor.getCanvas()->getSelection().removeChangeListener (this);
  382. props->clear();
  383. deleteAllChildren();
  384. }
  385. void changeListenerCallback (void*)
  386. {
  387. Array <PropertyComponent*> newComps;
  388. editor.getCanvas()->getSelectedItemProperties (newComps);
  389. props->clear();
  390. props->addProperties (newComps);
  391. }
  392. void paint (Graphics& g)
  393. {
  394. g.fillAll (Colour::greyLevel (0.92f));
  395. }
  396. void resized()
  397. {
  398. props->setSize (getWidth(), getHeight());
  399. }
  400. private:
  401. ComponentEditor& editor;
  402. PropertyPanel* props;
  403. };
  404. Toolbar* toolbar;
  405. ComponentEditor& editor;
  406. Viewport* viewport;
  407. InfoPanel* infoPanel;
  408. TreeView* tree;
  409. };
  410. //==============================================================================
  411. class ComponentEditor::BackgroundEditorHolder : public Component
  412. {
  413. public:
  414. BackgroundEditorHolder (ComponentEditor& editor_)
  415. : editor (editor_)
  416. {
  417. }
  418. ~BackgroundEditorHolder()
  419. {
  420. }
  421. private:
  422. ComponentEditor& editor;
  423. };
  424. //==============================================================================
  425. class ComponentEditor::CodeEditorHolder : public Component,
  426. public ButtonListener
  427. {
  428. public:
  429. CodeEditorHolder (ComponentEditor& editor_)
  430. : editor (editor_), switchFileButton (String::empty), showingHeader (true)
  431. {
  432. addAndMakeVisible (&viewport);
  433. viewport.setScrollBarsShown (true, false);
  434. addAndMakeVisible (&switchFileButton);
  435. buttonClicked (0);
  436. switchFileButton.addButtonListener (this);
  437. }
  438. ~CodeEditorHolder()
  439. {
  440. }
  441. void resized()
  442. {
  443. viewport.setBounds (getLocalBounds());
  444. int visWidth = viewport.getMaximumVisibleWidth();
  445. dynamic_cast <ContentHolder*> (viewport.getViewedComponent())->updateSize (visWidth);
  446. if (viewport.getMaximumVisibleWidth() != visWidth)
  447. dynamic_cast <ContentHolder*> (viewport.getViewedComponent())->updateSize (viewport.getMaximumVisibleWidth());
  448. switchFileButton.setBounds (getWidth() - 150, 4, 120, 20);
  449. }
  450. void buttonClicked (Button*)
  451. {
  452. showingHeader = ! showingHeader;
  453. viewport.setViewedComponent (new ContentHolder (editor.getDocument(), showingHeader));
  454. resized();
  455. switchFileButton.setButtonText (showingHeader ? "Show CPP file" : "Show header file");
  456. }
  457. private:
  458. enum { updateCommandId = 0x23427fa1 };
  459. //==============================================================================
  460. class EditorHolder : public Component,
  461. public CodeDocument::Listener
  462. {
  463. public:
  464. EditorHolder (const CodeGenerator::CustomCodeList::CodeDocumentRef::Ptr doc,
  465. const String& textBefore, const String& textAfter)
  466. : document (doc), cppTokeniser(), codeEditor (doc->getDocument(), &cppTokeniser)
  467. {
  468. linesBefore.addLines (textBefore);
  469. linesAfter.addLines (textAfter);
  470. addAndMakeVisible (&codeEditor);
  471. doc->getDocument().addListener (this);
  472. }
  473. ~EditorHolder()
  474. {
  475. document->getDocument().removeListener (this);
  476. }
  477. void paint (Graphics& g)
  478. {
  479. g.setFont (codeEditor.getFont());
  480. g.setColour (Colours::darkgrey);
  481. const int fontHeight = codeEditor.getLineHeight();
  482. const int fontAscent = (int) codeEditor.getFont().getAscent();
  483. const int textX = 5;
  484. int i;
  485. for (i = 0; i < linesBefore.size(); ++i)
  486. g.drawSingleLineText (linesBefore[i], textX, i * fontHeight + fontAscent);
  487. for (i = 0; i < linesAfter.size(); ++i)
  488. g.drawSingleLineText (linesAfter[i], textX, codeEditor.getBottom() + i * fontHeight + fontAscent);
  489. }
  490. void updateSize (int width)
  491. {
  492. const int fontHeight = codeEditor.getLineHeight();
  493. codeEditor.setBounds (0, fontHeight * linesBefore.size() + 1,
  494. width, 2 + codeEditor.getScrollbarThickness()
  495. + fontHeight * jlimit (1, 50, document->getDocument().getNumLines()));
  496. setSize (width, (linesBefore.size() + linesAfter.size()) * fontHeight + codeEditor.getHeight());
  497. }
  498. void codeDocumentChanged (const CodeDocument::Position&, const CodeDocument::Position&)
  499. {
  500. int oldHeight = getHeight();
  501. updateSize (getWidth());
  502. if (getHeight() != oldHeight)
  503. getParentComponent()->handleCommandMessage (updateCommandId);
  504. }
  505. private:
  506. const CodeGenerator::CustomCodeList::CodeDocumentRef::Ptr document;
  507. CPlusPlusCodeTokeniser cppTokeniser;
  508. CodeEditorComponent codeEditor;
  509. StringArray linesBefore, linesAfter;
  510. };
  511. //==============================================================================
  512. class ContentHolder : public Component,
  513. public ChangeListener
  514. {
  515. public:
  516. ContentHolder (ComponentDocument& document_, bool isHeader_)
  517. : document (document_), isHeader (isHeader_)
  518. {
  519. setOpaque (true);
  520. document.getCustomCodeList().addChangeListener (this);
  521. changeListenerCallback (0);
  522. }
  523. ~ContentHolder()
  524. {
  525. document.getCustomCodeList().removeChangeListener (this);
  526. }
  527. void paint (Graphics& g)
  528. {
  529. g.fillAll (Colours::lightgrey);
  530. }
  531. void updateSize (int width)
  532. {
  533. int y = 2;
  534. for (int i = 0; i < editors.size(); ++i)
  535. {
  536. EditorHolder* const ed = editors.getUnchecked(i);
  537. ed->updateSize (width - 8);
  538. ed->setTopLeftPosition (4, y + 1);
  539. y = ed->getBottom() + 1;
  540. }
  541. setSize (width, y + 2);
  542. }
  543. void changeListenerCallback (void*)
  544. {
  545. editors.clear();
  546. CodeGenerator::CustomCodeList::Iterator iter (isHeader ? document.getHeaderContent()
  547. : document.getCppContent(),
  548. document.getCustomCodeList());
  549. while (iter.next())
  550. {
  551. EditorHolder* ed = new EditorHolder (iter.codeDocument, iter.textBefore, iter.textAfter);
  552. editors.add (ed);
  553. addAndMakeVisible (ed);
  554. }
  555. updateSize (getWidth());
  556. }
  557. void handleCommandMessage (int commandId)
  558. {
  559. if (commandId == updateCommandId)
  560. updateSize (getWidth());
  561. else
  562. Component::handleCommandMessage (commandId);
  563. }
  564. private:
  565. OwnedArray <EditorHolder> editors;
  566. ComponentDocument& document;
  567. bool isHeader;
  568. };
  569. ComponentEditor& editor;
  570. Viewport viewport;
  571. TextButton switchFileButton;
  572. bool showingHeader;
  573. };
  574. //==============================================================================
  575. ComponentEditor::ComponentEditor (OpenDocumentManager::Document* document,
  576. Project* project_, ComponentDocument* componentDocument_)
  577. : DocumentEditorComponent (document),
  578. project (project_),
  579. componentDocument (componentDocument_),
  580. classInfoHolder (0),
  581. layoutEditorHolder (0),
  582. backgroundEditorHolder (0),
  583. codeEditorHolder (0)
  584. {
  585. setOpaque (true);
  586. if (componentDocument != 0)
  587. {
  588. classInfoHolder = new ClassInfoHolder (*this);
  589. layoutEditorHolder = new LayoutEditorHolder (*this);
  590. backgroundEditorHolder = new BackgroundEditorHolder (*this);
  591. codeEditorHolder = new CodeEditorHolder (*this);
  592. layoutEditorHolder->createCanvas();
  593. }
  594. addAndMakeVisible (tabs = new TabbedComponent (TabbedButtonBar::TabsAtRight));
  595. tabs->setTabBarDepth (22);
  596. tabs->addTab ("Class Settings", Colour::greyLevel (0.88f), classInfoHolder, true);
  597. tabs->addTab ("Components", Colours::white, layoutEditorHolder, true);
  598. tabs->addTab ("Background", Colours::white, backgroundEditorHolder, true);
  599. tabs->addTab ("Source Code", Colours::white, codeEditorHolder, true);
  600. tabs->setCurrentTabIndex (1);
  601. }
  602. ComponentEditor::~ComponentEditor()
  603. {
  604. deleteAllChildren();
  605. }
  606. void ComponentEditor::paint (Graphics& g)
  607. {
  608. g.fillAll (Colours::white);
  609. }
  610. void ComponentEditor::resized()
  611. {
  612. tabs->setBounds (getLocalBounds());
  613. }
  614. ComponentEditorCanvas* ComponentEditor::getCanvas() const
  615. {
  616. return dynamic_cast <ComponentEditorCanvas*> (getViewport()->getViewedComponent());
  617. }
  618. Viewport* ComponentEditor::getViewport() const
  619. {
  620. return layoutEditorHolder->getViewport();
  621. }
  622. //==============================================================================
  623. class TestComponent : public ComponentEditorCanvas::ComponentHolder
  624. {
  625. public:
  626. TestComponent (ComponentDocument& document_)
  627. : document (document_)
  628. {
  629. setSize (document.getCanvasWidth().getValue(),
  630. document.getCanvasHeight().getValue());
  631. }
  632. ~TestComponent()
  633. {
  634. }
  635. void resized()
  636. {
  637. document.getCanvasWidth() = getWidth();
  638. document.getCanvasHeight() = getHeight();
  639. ComponentEditorCanvas::ComponentHolder::resized();
  640. updateComponents (document, selected);
  641. }
  642. private:
  643. ComponentDocument document;
  644. ComponentEditorCanvas::SelectedItems selected;
  645. };
  646. void ComponentEditor::test()
  647. {
  648. TestComponent testComp (getDocument());
  649. DialogWindow::showModalDialog ("Testing: " + getDocument().getClassName().toString(),
  650. &testComp, this, Colours::lightgrey, true, true);
  651. }
  652. //==============================================================================
  653. void ComponentEditor::getAllCommands (Array <CommandID>& commands)
  654. {
  655. DocumentEditorComponent::getAllCommands (commands);
  656. const CommandID ids[] = { CommandIDs::undo,
  657. CommandIDs::redo,
  658. CommandIDs::toFront,
  659. CommandIDs::toBack,
  660. CommandIDs::test,
  661. CommandIDs::showOrHideProperties,
  662. CommandIDs::showOrHideTree,
  663. StandardApplicationCommandIDs::del };
  664. commands.addArray (ids, numElementsInArray (ids));
  665. }
  666. void ComponentEditor::getCommandInfo (CommandID commandID, ApplicationCommandInfo& result)
  667. {
  668. result.setActive (document != 0);
  669. switch (commandID)
  670. {
  671. case CommandIDs::undo:
  672. result.setInfo ("Undo", "Undoes the last change", CommandCategories::general, 0);
  673. result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::commandModifier, 0));
  674. break;
  675. case CommandIDs::redo:
  676. result.setInfo ("Redo", "Redoes the last change", CommandCategories::general, 0);
  677. result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0));
  678. result.defaultKeypresses.add (KeyPress ('y', ModifierKeys::commandModifier, 0));
  679. break;
  680. case CommandIDs::toFront:
  681. result.setInfo ("Bring to Front", "Brings the selected items to the front", CommandCategories::editing, 0);
  682. break;
  683. case CommandIDs::toBack:
  684. result.setInfo ("Send to Back", "Moves the selected items to the back", CommandCategories::editing, 0);
  685. break;
  686. case CommandIDs::test:
  687. result.setInfo ("Test", "Test the current component", CommandCategories::editing, 0);
  688. result.defaultKeypresses.add (KeyPress ('t', ModifierKeys::commandModifier, 0));
  689. break;
  690. case CommandIDs::showOrHideProperties:
  691. result.setInfo ("Show/Hide Tree", "Shows or hides the component tree view", CommandCategories::editing, 0);
  692. break;
  693. case CommandIDs::showOrHideTree:
  694. result.setInfo ("Show/Hide Properties", "Shows or hides the component properties panel", CommandCategories::editing, 0);
  695. break;
  696. case StandardApplicationCommandIDs::del:
  697. result.setInfo ("Delete", String::empty, CommandCategories::general, 0);
  698. result.defaultKeypresses.add (KeyPress (KeyPress::deleteKey, 0, 0));
  699. result.defaultKeypresses.add (KeyPress (KeyPress::backspaceKey, 0, 0));
  700. break;
  701. default:
  702. DocumentEditorComponent::getCommandInfo (commandID, result);
  703. break;
  704. }
  705. }
  706. bool ComponentEditor::perform (const InvocationInfo& info)
  707. {
  708. switch (info.commandID)
  709. {
  710. case CommandIDs::undo:
  711. getDocument().getUndoManager()->undo();
  712. return true;
  713. case CommandIDs::redo:
  714. getDocument().getUndoManager()->redo();
  715. return true;
  716. case CommandIDs::toFront:
  717. getCanvas()->selectionToFront();
  718. return true;
  719. case CommandIDs::toBack:
  720. getCanvas()->selectionToBack();
  721. return true;
  722. case CommandIDs::test:
  723. test();
  724. return true;
  725. case CommandIDs::showOrHideProperties:
  726. layoutEditorHolder->showOrHideProperties();
  727. return true;
  728. case CommandIDs::showOrHideTree:
  729. layoutEditorHolder->showOrHideTree();
  730. return true;
  731. case StandardApplicationCommandIDs::del:
  732. getCanvas()->deleteSelection();
  733. return true;
  734. default:
  735. break;
  736. }
  737. return DocumentEditorComponent::perform (info);
  738. }