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.

897 lines
29KB

  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. {
  427. public:
  428. CodeEditorHolder (ComponentEditor& editor_)
  429. : editor (editor_)
  430. {
  431. addAndMakeVisible (viewport = new Viewport());
  432. viewport->setScrollBarsShown (true, false);
  433. viewport->setViewedComponent (new ContentHolder (editor));
  434. }
  435. ~CodeEditorHolder()
  436. {
  437. }
  438. void resized()
  439. {
  440. viewport->setBounds (getLocalBounds());
  441. int visWidth = viewport->getMaximumVisibleWidth();
  442. dynamic_cast <ContentHolder*> (viewport->getViewedComponent())->updateSize (visWidth);
  443. if (viewport->getMaximumVisibleWidth() != visWidth)
  444. dynamic_cast <ContentHolder*> (viewport->getViewedComponent())->updateSize (viewport->getMaximumVisibleWidth());
  445. }
  446. private:
  447. ComponentEditor& editor;
  448. enum { updateCommandId = 0x23427fa1 };
  449. class EditorHolder : public Component,
  450. public CodeDocument::Listener
  451. {
  452. public:
  453. EditorHolder (const CodeGenerator::CustomCodeList::CodeDocumentRef::Ptr doc,
  454. const String& name, const String& textBefore, const String& textAfter)
  455. : Component (name), document (doc), cppTokeniser(), codeEditor (doc->getDocument(), &cppTokeniser)
  456. {
  457. linesBefore.addLines (textBefore);
  458. linesAfter.addLines (textAfter);
  459. addAndMakeVisible (&codeEditor);
  460. doc->getDocument().addListener (this);
  461. }
  462. ~EditorHolder()
  463. {
  464. document->getDocument().removeListener (this);
  465. }
  466. void paint (Graphics& g)
  467. {
  468. g.setFont (codeEditor.getFont());
  469. g.setColour (Colours::darkgrey);
  470. const int fontHeight = codeEditor.getLineHeight();
  471. const int fontAscent = (int) codeEditor.getFont().getAscent();
  472. const int textX = 5;
  473. int i;
  474. for (i = 0; i < linesBefore.size(); ++i)
  475. g.drawSingleLineText (linesBefore[i], textX, i * fontHeight + fontAscent);
  476. for (i = 0; i < linesAfter.size(); ++i)
  477. g.drawSingleLineText (linesAfter[i], textX, codeEditor.getBottom() + i * fontHeight + fontAscent);
  478. }
  479. void updateSize (int width)
  480. {
  481. const int fontHeight = codeEditor.getLineHeight();
  482. codeEditor.setBounds (0, fontHeight * linesBefore.size() + 1,
  483. width, 2 + codeEditor.getScrollbarThickness()
  484. + fontHeight * jmax (1, document->getDocument().getNumLines()));
  485. setSize (width, (linesBefore.size() + linesAfter.size()) * fontHeight + codeEditor.getHeight());
  486. }
  487. void codeDocumentChanged (const CodeDocument::Position&, const CodeDocument::Position&)
  488. {
  489. int oldHeight = getHeight();
  490. updateSize (getWidth());
  491. if (getHeight() != oldHeight)
  492. getParentComponent()->handleCommandMessage (updateCommandId);
  493. }
  494. const CodeGenerator::CustomCodeList::CodeDocumentRef::Ptr document;
  495. CPlusPlusCodeTokeniser cppTokeniser;
  496. CodeEditorComponent codeEditor;
  497. StringArray linesBefore, linesAfter;
  498. };
  499. class ContentHolder : public Component,
  500. public ChangeListener
  501. {
  502. public:
  503. ContentHolder (ComponentEditor& editor_)
  504. : editor (editor_)
  505. {
  506. setOpaque (true);
  507. editor.getDocument().getCustomCodeList().addChangeListener (this);
  508. changeListenerCallback (0);
  509. }
  510. ~ContentHolder()
  511. {
  512. editor.getDocument().getCustomCodeList().removeChangeListener (this);
  513. }
  514. void paint (Graphics& g)
  515. {
  516. g.fillAll (Colours::lightgrey);
  517. }
  518. void updateSize (int width)
  519. {
  520. int y = 2;
  521. for (int i = 0; i < editors.size(); ++i)
  522. {
  523. editors.getUnchecked(i)->updateSize (width - 8);
  524. editors.getUnchecked(i)->setTopLeftPosition (4, y + 1);
  525. y = editors.getUnchecked(i)->getBottom() + 1;
  526. }
  527. setSize (width, y + 2);
  528. }
  529. void changeListenerCallback (void*)
  530. {
  531. editors.clear();
  532. CodeGenerator::CustomCodeList::Iterator iter (editor.getDocument().getCppTemplate(),
  533. editor.getDocument().getCustomCodeList());
  534. while (iter.next())
  535. {
  536. EditorHolder* ed = new EditorHolder (iter.codeDocument, iter.sectionName, iter.textBefore, iter.textAfter);
  537. editors.add (ed);
  538. addAndMakeVisible (ed);
  539. }
  540. updateSize (getWidth());
  541. }
  542. void handleCommandMessage (int commandId)
  543. {
  544. if (commandId == updateCommandId)
  545. updateSize (getWidth());
  546. else
  547. Component::handleCommandMessage (commandId);
  548. }
  549. OwnedArray <EditorHolder> editors;
  550. ComponentEditor& editor;
  551. };
  552. Viewport* viewport;
  553. };
  554. //==============================================================================
  555. ComponentEditor::ComponentEditor (OpenDocumentManager::Document* document,
  556. Project* project_, ComponentDocument* componentDocument_)
  557. : DocumentEditorComponent (document),
  558. project (project_),
  559. componentDocument (componentDocument_),
  560. classInfoHolder (0),
  561. layoutEditorHolder (0),
  562. backgroundEditorHolder (0),
  563. codeEditorHolder (0)
  564. {
  565. setOpaque (true);
  566. if (componentDocument != 0)
  567. {
  568. classInfoHolder = new ClassInfoHolder (*this);
  569. layoutEditorHolder = new LayoutEditorHolder (*this);
  570. backgroundEditorHolder = new BackgroundEditorHolder (*this);
  571. codeEditorHolder = new CodeEditorHolder (*this);
  572. layoutEditorHolder->createCanvas();
  573. }
  574. addAndMakeVisible (tabs = new TabbedComponent (TabbedButtonBar::TabsAtRight));
  575. tabs->setTabBarDepth (22);
  576. tabs->addTab ("Class Settings", Colour::greyLevel (0.88f), classInfoHolder, true);
  577. tabs->addTab ("Components", Colours::white, layoutEditorHolder, true);
  578. tabs->addTab ("Background", Colours::white, backgroundEditorHolder, true);
  579. tabs->addTab ("Source Code", Colours::white, codeEditorHolder, true);
  580. tabs->setCurrentTabIndex (1);
  581. }
  582. ComponentEditor::~ComponentEditor()
  583. {
  584. deleteAllChildren();
  585. }
  586. void ComponentEditor::paint (Graphics& g)
  587. {
  588. g.fillAll (Colours::white);
  589. }
  590. void ComponentEditor::resized()
  591. {
  592. tabs->setBounds (getLocalBounds());
  593. }
  594. ComponentEditorCanvas* ComponentEditor::getCanvas() const
  595. {
  596. return dynamic_cast <ComponentEditorCanvas*> (getViewport()->getViewedComponent());
  597. }
  598. Viewport* ComponentEditor::getViewport() const
  599. {
  600. return layoutEditorHolder->getViewport();
  601. }
  602. //==============================================================================
  603. class TestComponent : public ComponentEditorCanvas::ComponentHolder
  604. {
  605. public:
  606. TestComponent (ComponentDocument& document_)
  607. : document (document_)
  608. {
  609. setSize (document.getCanvasWidth().getValue(),
  610. document.getCanvasHeight().getValue());
  611. }
  612. ~TestComponent()
  613. {
  614. }
  615. void resized()
  616. {
  617. document.getCanvasWidth() = getWidth();
  618. document.getCanvasHeight() = getHeight();
  619. ComponentEditorCanvas::ComponentHolder::resized();
  620. updateComponents (document, selected);
  621. }
  622. private:
  623. ComponentDocument document;
  624. ComponentEditorCanvas::SelectedItems selected;
  625. };
  626. void ComponentEditor::test()
  627. {
  628. TestComponent testComp (getDocument());
  629. DialogWindow::showModalDialog ("Testing: " + getDocument().getClassName().toString(),
  630. &testComp, this, Colours::lightgrey, true, true);
  631. }
  632. //==============================================================================
  633. void ComponentEditor::getAllCommands (Array <CommandID>& commands)
  634. {
  635. DocumentEditorComponent::getAllCommands (commands);
  636. const CommandID ids[] = { CommandIDs::undo,
  637. CommandIDs::redo,
  638. CommandIDs::toFront,
  639. CommandIDs::toBack,
  640. CommandIDs::test,
  641. CommandIDs::showOrHideProperties,
  642. CommandIDs::showOrHideTree,
  643. StandardApplicationCommandIDs::del };
  644. commands.addArray (ids, numElementsInArray (ids));
  645. }
  646. void ComponentEditor::getCommandInfo (CommandID commandID, ApplicationCommandInfo& result)
  647. {
  648. result.setActive (document != 0);
  649. switch (commandID)
  650. {
  651. case CommandIDs::undo:
  652. result.setInfo ("Undo", "Undoes the last change", CommandCategories::general, 0);
  653. result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::commandModifier, 0));
  654. break;
  655. case CommandIDs::redo:
  656. result.setInfo ("Redo", "Redoes the last change", CommandCategories::general, 0);
  657. result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0));
  658. result.defaultKeypresses.add (KeyPress ('y', ModifierKeys::commandModifier, 0));
  659. break;
  660. case CommandIDs::toFront:
  661. result.setInfo ("Bring to Front", "Brings the selected items to the front", CommandCategories::editing, 0);
  662. break;
  663. case CommandIDs::toBack:
  664. result.setInfo ("Send to Back", "Moves the selected items to the back", CommandCategories::editing, 0);
  665. break;
  666. case CommandIDs::test:
  667. result.setInfo ("Test", "Test the current component", CommandCategories::editing, 0);
  668. result.defaultKeypresses.add (KeyPress ('t', ModifierKeys::commandModifier, 0));
  669. break;
  670. case CommandIDs::showOrHideProperties:
  671. result.setInfo ("Show/Hide Tree", "Shows or hides the component tree view", CommandCategories::editing, 0);
  672. break;
  673. case CommandIDs::showOrHideTree:
  674. result.setInfo ("Show/Hide Properties", "Shows or hides the component properties panel", CommandCategories::editing, 0);
  675. break;
  676. case StandardApplicationCommandIDs::del:
  677. result.setInfo ("Delete", String::empty, CommandCategories::general, 0);
  678. result.defaultKeypresses.add (KeyPress (KeyPress::deleteKey, 0, 0));
  679. result.defaultKeypresses.add (KeyPress (KeyPress::backspaceKey, 0, 0));
  680. break;
  681. default:
  682. DocumentEditorComponent::getCommandInfo (commandID, result);
  683. break;
  684. }
  685. }
  686. bool ComponentEditor::perform (const InvocationInfo& info)
  687. {
  688. switch (info.commandID)
  689. {
  690. case CommandIDs::undo:
  691. getDocument().getUndoManager()->undo();
  692. return true;
  693. case CommandIDs::redo:
  694. getDocument().getUndoManager()->redo();
  695. return true;
  696. case CommandIDs::toFront:
  697. getCanvas()->selectionToFront();
  698. return true;
  699. case CommandIDs::toBack:
  700. getCanvas()->selectionToBack();
  701. return true;
  702. case CommandIDs::test:
  703. test();
  704. return true;
  705. case CommandIDs::showOrHideProperties:
  706. layoutEditorHolder->showOrHideProperties();
  707. return true;
  708. case CommandIDs::showOrHideTree:
  709. layoutEditorHolder->showOrHideTree();
  710. return true;
  711. case StandardApplicationCommandIDs::del:
  712. getCanvas()->deleteSelection();
  713. return true;
  714. default:
  715. break;
  716. }
  717. return DocumentEditorComponent::perform (info);
  718. }