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.

828 lines
27KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 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. //==============================================================================
  21. class SizeGuideComponent : public Component,
  22. public ComponentListener
  23. {
  24. public:
  25. enum Type
  26. {
  27. left, right, top, bottom
  28. };
  29. SizeGuideComponent (ComponentDocument& document_, const ValueTree& state_, Component* component_,
  30. Component* parentForOverlays, Type type_)
  31. : document (document_), state (state_), component (component_), type (type_),
  32. font (10.0f)
  33. {
  34. component->addComponentListener (this);
  35. setAlwaysOnTop (true);
  36. parentForOverlays->addAndMakeVisible (this);
  37. updatePosition();
  38. }
  39. ~SizeGuideComponent()
  40. {
  41. if (component != 0)
  42. component->removeComponentListener (this);
  43. }
  44. void updatePosition()
  45. {
  46. RectangleCoordinates coords (document.getCoordsFor (state));
  47. Coordinate coord (false);
  48. bool isHorizontal = false;
  49. switch (type)
  50. {
  51. case left: coord = coords.left; isHorizontal = true; break;
  52. case right: coord = coords.right; isHorizontal = true; break;
  53. case top: coord = coords.top; break;
  54. case bottom: coord = coords.bottom; break;
  55. default: jassertfalse; break;
  56. }
  57. setName (coord.toString());
  58. ScopedPointer<Coordinate::MarkerResolver> markers (document.createMarkerResolver (state, component->getParentComponent()));
  59. int anchor1 = coord.getAnchorPoint1().resolve (*markers);
  60. int anchor2 = coord.getAnchorPoint2().resolve (*markers);
  61. Point<int> p1, p2;
  62. switch (type)
  63. {
  64. case left: p1 = Point<int> (component->getX(), component->getY() + component->proportionOfHeight (0.33f));
  65. p2 = Point<int> (anchor1, p1.getY()); break;
  66. case right: p1 = Point<int> (component->getRight(), component->getY() + component->proportionOfHeight (0.66f));
  67. p2 = Point<int> (anchor1, p1.getY()); break;
  68. case top: p1 = Point<int> (component->getX() + component->proportionOfWidth (0.33f), component->getY());
  69. p2 = Point<int> (p1.getX(), anchor1); break;
  70. case bottom: p1 = Point<int> (component->getX() + component->proportionOfWidth (0.66f), component->getBottom());
  71. p2 = Point<int> (p1.getX(), anchor1); break;
  72. default: jassertfalse; break;
  73. }
  74. Rectangle<int> bounds (Rectangle<int> (p1, p2).expanded (4, 4));
  75. Point<int> textPos ((p1.getX() + p2.getX()) / 2,
  76. (p1.getY() + p2.getY()) / 2);
  77. int textW = (int) font.getStringWidth (getName());
  78. int textH = (int) font.getHeight();
  79. Rectangle<int> textRect (textPos.getX() - textW / 2, textPos.getY() - textH / 2, textW, textH);
  80. if (isHorizontal)
  81. textRect = textRect - Point<int> (0, textH / 2 + 4);
  82. bounds = bounds.getUnion (textRect);
  83. setBounds (bounds);
  84. lineEnd1 = p1 - bounds.getPosition();
  85. lineEnd2 = p2 - bounds.getPosition();
  86. textArea = textRect - bounds.getPosition();
  87. repaint();
  88. }
  89. void paint (Graphics& g)
  90. {
  91. Path p;
  92. p.addLineSegment (lineEnd1.getX(), lineEnd1.getY(), lineEnd2.getX(), lineEnd2.getY(), 1.6f);
  93. const float startBlobSize = 2.0f;
  94. p.addEllipse (lineEnd1.getX() - startBlobSize, lineEnd1.getY() - startBlobSize, startBlobSize * 2.0f, startBlobSize * 2.0f);
  95. const float endBlobSize = 4.0f;
  96. p.addEllipse (lineEnd2.getX() - endBlobSize, lineEnd2.getY() - endBlobSize, endBlobSize * 2.0f, endBlobSize * 2.0f);
  97. g.setColour (Colours::black.withAlpha (0.3f));
  98. g.fillPath (p);
  99. g.setFont (font);
  100. g.setColour (Colours::white);
  101. for (int y = -1; y <= 1; ++y)
  102. for (int x = -1; x <= 1; ++x)
  103. g.drawText (getName(), textArea.getX() + x, textArea.getY() + y, textArea.getWidth(), textArea.getHeight(), Justification::centred, 1);
  104. g.setColour (Colours::black);
  105. g.drawText (getName(), textArea.getX(), textArea.getY(), textArea.getWidth(), textArea.getHeight(), Justification::centred, 1);
  106. }
  107. void componentMovedOrResized (Component&, bool, bool)
  108. {
  109. updatePosition();
  110. }
  111. void componentBeingDeleted (Component&)
  112. {
  113. setVisible (false);
  114. component = 0;
  115. }
  116. private:
  117. ComponentDocument& document;
  118. ValueTree state;
  119. Component* component;
  120. Type type;
  121. Font font;
  122. Point<int> lineEnd1, lineEnd2;
  123. Rectangle<int> textArea;
  124. };
  125. //==============================================================================
  126. class ComponentEditor::Canvas : public Component,
  127. public ValueTree::Listener,
  128. public Timer
  129. {
  130. public:
  131. Canvas (ComponentEditor& editor_)
  132. : editor (editor_), borderThickness (4)
  133. {
  134. setOpaque (true);
  135. addAndMakeVisible (componentHolder = new Component());
  136. addAndMakeVisible (overlay = new OverlayComponent (*this));
  137. setSize (500, 500);
  138. getDocument().getRoot().addListener (this);
  139. updateComponents();
  140. }
  141. ~Canvas()
  142. {
  143. getDocument().getRoot().removeListener (this);
  144. deleteAllChildren();
  145. }
  146. void paint (Graphics& g)
  147. {
  148. g.fillAll (Colours::white);
  149. g.setColour (Colour::greyLevel (0.9f));
  150. g.drawRect (0, 0, getWidth(), getHeight(), borderThickness);
  151. }
  152. void resized()
  153. {
  154. componentHolder->setBounds (getLocalBounds().reduced (borderThickness, borderThickness));
  155. overlay->setBounds (componentHolder->getBounds());
  156. updateComponents();
  157. }
  158. void zoom (float newScale, const Point<int>& centre)
  159. {
  160. }
  161. ComponentEditor& getEditor() { return editor; }
  162. ComponentDocument& getDocument() { return editor.getDocument(); }
  163. ComponentDocument::SelectedItems& getSelection() { return selection; }
  164. Component* findComponentFor (const ValueTree& state)
  165. {
  166. ComponentDocument& doc = getDocument();
  167. for (int i = componentHolder->getNumChildComponents(); --i >= 0;)
  168. {
  169. Component* c = componentHolder->getChildComponent (i);
  170. if (doc.isStateForComponent (state, c))
  171. return c;
  172. }
  173. return 0;
  174. }
  175. void updateComponents()
  176. {
  177. ComponentDocument& doc = getDocument();
  178. int i;
  179. for (i = componentHolder->getNumChildComponents(); --i >= 0;)
  180. {
  181. Component* c = componentHolder->getChildComponent (i);
  182. if (! doc.containsComponent (c))
  183. {
  184. selection.deselect (c->getComponentUID());
  185. delete c;
  186. }
  187. }
  188. const int num = doc.getNumComponents();
  189. for (i = 0; i < num; ++i)
  190. {
  191. const ValueTree v (doc.getComponent (i));
  192. Component* c = findComponentFor (v);
  193. if (c == 0)
  194. {
  195. c = doc.createComponent (i);
  196. componentHolder->addAndMakeVisible (c);
  197. }
  198. doc.updateComponent (c);
  199. }
  200. startTimer (500);
  201. }
  202. void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const var::identifier& property)
  203. {
  204. updateComponents();
  205. }
  206. void valueTreeChildrenChanged (ValueTree& treeWhoseChildHasChanged)
  207. {
  208. updateComponents();
  209. }
  210. void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged)
  211. {
  212. }
  213. Component* getComponentHolder() const { return componentHolder; }
  214. const Array<Component*> getSelectedComps() const
  215. {
  216. Array<Component*> comps;
  217. for (int i = 0; i < selection.getNumSelected(); ++i)
  218. {
  219. Component* c = getComponentForUID (selection.getSelectedItem (i));
  220. jassert (c != 0);
  221. if (c != 0)
  222. comps.add (c);
  223. }
  224. return comps;
  225. }
  226. void getSelectedItemProperties (Array <PropertyComponent*>& props)
  227. {
  228. //xxx needs to handle multiple selections..
  229. if (selection.getNumSelected() == 1)
  230. {
  231. Component* c = getComponentForUID (selection.getSelectedItem (0));
  232. getDocument().getComponentProperties (props, c);
  233. }
  234. }
  235. void timerCallback()
  236. {
  237. stopTimer();
  238. if (! Component::isMouseButtonDownAnywhere())
  239. getDocument().beginNewTransaction();
  240. }
  241. void mouseMove (const MouseEvent& e)
  242. {
  243. updateDragZone (e.getPosition());
  244. }
  245. void mouseDown (const MouseEvent& e)
  246. {
  247. updateDragZone (e.getPosition());
  248. dragStartSize = getBounds();
  249. }
  250. void mouseDrag (const MouseEvent& e)
  251. {
  252. if (dragZone.isDraggingRightEdge() || dragZone.isDraggingBottomEdge())
  253. {
  254. showSizeGuides();
  255. setSize (jmax (0, dragStartSize.getWidth() + e.getDistanceFromDragStartX()),
  256. jmax (0, dragStartSize.getHeight() + e.getDistanceFromDragStartY()));
  257. }
  258. }
  259. void mouseUp (const MouseEvent& e)
  260. {
  261. hideSizeGuides();
  262. updateDragZone (e.getPosition());
  263. }
  264. void updateDragZone (const Point<int>& p)
  265. {
  266. ResizableBorderComponent::Zone newZone
  267. = ResizableBorderComponent::Zone::fromPositionOnBorder (getLocalBounds(),
  268. BorderSize (borderThickness), p);
  269. newZone = ResizableBorderComponent::Zone (newZone.getZoneFlags()
  270. & (ResizableBorderComponent::Zone::right | ResizableBorderComponent::Zone::bottom));
  271. if (dragZone != newZone)
  272. {
  273. dragZone = newZone;
  274. setMouseCursor (newZone.getMouseCursor());
  275. }
  276. }
  277. void showSizeGuides() { overlay->showSizeGuides(); }
  278. void hideSizeGuides() { overlay->hideSizeGuides(); }
  279. private:
  280. ComponentEditor& editor;
  281. const int borderThickness;
  282. ResizableBorderComponent::Zone dragZone;
  283. Rectangle<int> dragStartSize;
  284. //==============================================================================
  285. class ComponentResizeFrame : public Component,
  286. public ComponentListener
  287. {
  288. public:
  289. ComponentResizeFrame (Canvas& canvas_,
  290. Component* componentToAttachTo)
  291. : canvas (canvas_),
  292. component (componentToAttachTo),
  293. borderThickness (4)
  294. {
  295. componentMovedOrResized (*componentToAttachTo, true, true);
  296. componentToAttachTo->addComponentListener (this);
  297. }
  298. ~ComponentResizeFrame()
  299. {
  300. if (component != 0)
  301. component->removeComponentListener (this);
  302. }
  303. void paint (Graphics& g)
  304. {
  305. g.setColour (Colours::red.withAlpha (0.1f));
  306. g.drawRect (0, 0, getWidth(), getHeight(), borderThickness);
  307. }
  308. void mouseEnter (const MouseEvent& e)
  309. {
  310. //repaint();
  311. updateDragZone (e.getPosition());
  312. }
  313. void mouseExit (const MouseEvent& e)
  314. {
  315. //repaint();
  316. updateDragZone (e.getPosition());
  317. }
  318. void mouseMove (const MouseEvent& e)
  319. {
  320. updateDragZone (e.getPosition());
  321. }
  322. void mouseDown (const MouseEvent& e)
  323. {
  324. jassert (component != 0);
  325. if (component != 0)
  326. {
  327. updateDragZone (e.getPosition());
  328. canvas.getDocument().beginDrag (canvas.getSelectedComps(), e, getParentComponent(), dragZone);
  329. }
  330. }
  331. void mouseDrag (const MouseEvent& e)
  332. {
  333. if (component != 0)
  334. {
  335. canvas.showSizeGuides();
  336. canvas.getDocument().continueDrag (e);
  337. }
  338. }
  339. void mouseUp (const MouseEvent& e)
  340. {
  341. canvas.hideSizeGuides();
  342. if (component != 0)
  343. canvas.getDocument().endDrag (e);
  344. updateDragZone (e.getPosition());
  345. }
  346. void componentMovedOrResized (Component&, bool wasMoved, bool wasResized)
  347. {
  348. if (component != 0)
  349. setBounds (component->getBounds().expanded (borderThickness, borderThickness));
  350. }
  351. bool hitTest (int x, int y)
  352. {
  353. return ! getCentreArea().contains (x, y);
  354. }
  355. uint32 getTargetComponentUID() const { return component == 0 ? 0 : component->getComponentUID(); }
  356. void showSizeGuides()
  357. {
  358. if (sizeGuides.size() == 0)
  359. {
  360. const ValueTree v (canvas.getDocument().getComponentState (component));
  361. sizeGuides.add (new SizeGuideComponent (canvas.getDocument(), v, component, getParentComponent(), SizeGuideComponent::left));
  362. sizeGuides.add (new SizeGuideComponent (canvas.getDocument(), v, component, getParentComponent(), SizeGuideComponent::right));
  363. sizeGuides.add (new SizeGuideComponent (canvas.getDocument(), v, component, getParentComponent(), SizeGuideComponent::top));
  364. sizeGuides.add (new SizeGuideComponent (canvas.getDocument(), v, component, getParentComponent(), SizeGuideComponent::bottom));
  365. }
  366. }
  367. void hideSizeGuides()
  368. {
  369. sizeGuides.clear();
  370. }
  371. private:
  372. Canvas& canvas;
  373. Component::SafePointer<Component> component;
  374. ResizableBorderComponent::Zone dragZone;
  375. const int borderThickness;
  376. OwnedArray <SizeGuideComponent> sizeGuides;
  377. const Rectangle<int> getCentreArea() const
  378. {
  379. return getLocalBounds().reduced (borderThickness, borderThickness);
  380. }
  381. void updateDragZone (const Point<int>& p)
  382. {
  383. ResizableBorderComponent::Zone newZone
  384. = ResizableBorderComponent::Zone::fromPositionOnBorder (getLocalBounds(),
  385. BorderSize (borderThickness), p);
  386. if (dragZone != newZone)
  387. {
  388. dragZone = newZone;
  389. setMouseCursor (newZone.getMouseCursor());
  390. }
  391. }
  392. };
  393. //==============================================================================
  394. class OverlayComponent : public Component,
  395. public LassoSource <ComponentDocument::SelectedItems::ItemType>,
  396. public ChangeListener
  397. {
  398. public:
  399. OverlayComponent (Canvas& canvas_)
  400. : canvas (canvas_)
  401. {
  402. setAlwaysOnTop (true);
  403. setWantsKeyboardFocus (true);
  404. canvas.getSelection().addChangeListener (this);
  405. }
  406. ~OverlayComponent()
  407. {
  408. canvas.getSelection().removeChangeListener (this);
  409. lasso = 0;
  410. deleteAllChildren();
  411. }
  412. void mouseDown (const MouseEvent& e)
  413. {
  414. lasso = 0;
  415. mouseDownCompUID = 0;
  416. isDraggingClickedComp = false;
  417. if (e.mods.isPopupMenu())
  418. {
  419. PopupMenu m;
  420. canvas.getDocument().addNewComponentMenuItems (m);
  421. const int r = m.show();
  422. canvas.getDocument().performNewComponentMenuItem (r);
  423. }
  424. else
  425. {
  426. Component* underMouse = canvas.getComponentHolder()->getComponentAt (e.x, e.y);
  427. if (underMouse == canvas.getComponentHolder())
  428. underMouse = 0;
  429. if (underMouse == 0 || e.mods.isAltDown())
  430. {
  431. addAndMakeVisible (lasso = new LassoComponent <ComponentDocument::SelectedItems::ItemType>());
  432. lasso->beginLasso (e, this);
  433. }
  434. else
  435. {
  436. mouseDownCompUID = underMouse->getComponentUID();
  437. mouseDownResult = canvas.getSelection().addToSelectionOnMouseDown (mouseDownCompUID, e.mods);
  438. }
  439. }
  440. }
  441. void mouseDrag (const MouseEvent& e)
  442. {
  443. if (lasso != 0)
  444. {
  445. lasso->dragLasso (e);
  446. }
  447. else if (mouseDownCompUID != 0 && (! e.mouseWasClicked()) && (! e.mods.isPopupMenu()))
  448. {
  449. if (! isDraggingClickedComp)
  450. {
  451. isDraggingClickedComp = true;
  452. canvas.getSelection().addToSelectionOnMouseUp (mouseDownCompUID, e.mods, true, mouseDownResult);
  453. canvas.getDocument().beginDrag (canvas.getSelectedComps(), e, getParentComponent(),
  454. ResizableBorderComponent::Zone (ResizableBorderComponent::Zone::centre));
  455. }
  456. canvas.getDocument().continueDrag (e);
  457. showSizeGuides();
  458. }
  459. }
  460. void mouseUp (const MouseEvent& e)
  461. {
  462. hideSizeGuides();
  463. if (lasso != 0)
  464. {
  465. lasso->endLasso();
  466. lasso = 0;
  467. if (e.mouseWasClicked())
  468. canvas.getSelection().deselectAll();
  469. }
  470. else if (! e.mods.isPopupMenu())
  471. {
  472. if (! isDraggingClickedComp)
  473. canvas.getSelection().addToSelectionOnMouseUp (mouseDownCompUID, e.mods, ! e.mouseWasClicked(), mouseDownResult);
  474. }
  475. canvas.getDocument().endDrag (e);
  476. }
  477. void findLassoItemsInArea (Array <ComponentDocument::SelectedItems::ItemType>& itemsFound, int x, int y, int width, int height)
  478. {
  479. const Rectangle<int> lassoArea (x, y, width, height);
  480. for (int i = canvas.getComponentHolder()->getNumChildComponents(); --i >= 0;)
  481. {
  482. Component* c = canvas.getComponentHolder()->getChildComponent(i);
  483. if (c->getBounds().intersects (lassoArea))
  484. itemsFound.add (c->getComponentUID());
  485. }
  486. }
  487. ComponentDocument::SelectedItems& getLassoSelection() { return canvas.getSelection(); }
  488. void changeListenerCallback (void*)
  489. {
  490. updateSelectedComponentResizeFrames();
  491. }
  492. void modifierKeysChanged (const ModifierKeys&)
  493. {
  494. Desktop::getInstance().getMainMouseSource().triggerFakeMove();
  495. }
  496. void showSizeGuides()
  497. {
  498. for (int i = getNumChildComponents(); --i >= 0;)
  499. {
  500. ComponentResizeFrame* resizer = dynamic_cast <ComponentResizeFrame*> (getChildComponent(i));
  501. if (resizer != 0)
  502. resizer->showSizeGuides();
  503. }
  504. }
  505. void hideSizeGuides()
  506. {
  507. for (int i = getNumChildComponents(); --i >= 0;)
  508. {
  509. ComponentResizeFrame* resizer = dynamic_cast <ComponentResizeFrame*> (getChildComponent(i));
  510. if (resizer != 0)
  511. resizer->hideSizeGuides();
  512. }
  513. }
  514. private:
  515. Canvas& canvas;
  516. ScopedPointer <LassoComponent <ComponentDocument::SelectedItems::ItemType> > lasso;
  517. bool mouseDownResult, isDraggingClickedComp;
  518. uint32 mouseDownCompUID;
  519. ComponentResizeFrame* getSelectorFrameFor (Component* c) const
  520. {
  521. for (int i = getNumChildComponents(); --i >= 0;)
  522. {
  523. ComponentResizeFrame* resizer = dynamic_cast <ComponentResizeFrame*> (getChildComponent(i));
  524. if (resizer != 0 && resizer->getTargetComponentUID() == c->getComponentUID())
  525. return resizer;
  526. }
  527. return 0;
  528. }
  529. void updateSelectedComponentResizeFrames()
  530. {
  531. ComponentDocument::SelectedItems& selection = canvas.getSelection();
  532. int i;
  533. for (i = getNumChildComponents(); --i >= 0;)
  534. {
  535. ComponentResizeFrame* resizer = dynamic_cast <ComponentResizeFrame*> (getChildComponent(i));
  536. if (resizer != 0 && ! selection.isSelected (resizer->getTargetComponentUID()))
  537. delete resizer;
  538. }
  539. for (i = canvas.getComponentHolder()->getNumChildComponents(); --i >= 0;)
  540. {
  541. Component* c = canvas.getComponentHolder()->getChildComponent(i);
  542. if (c != this && selection.isSelected (c->getComponentUID()) && getSelectorFrameFor (c) == 0)
  543. addAndMakeVisible (new ComponentResizeFrame (canvas, c));
  544. }
  545. }
  546. };
  547. Component* componentHolder;
  548. OverlayComponent* overlay;
  549. ComponentDocument::SelectedItems selection;
  550. Component* getComponentForUID (const uint32 uid) const
  551. {
  552. for (int i = componentHolder->getNumChildComponents(); --i >= 0;)
  553. if (componentHolder->getChildComponent (i)->getComponentUID() == uid)
  554. return componentHolder->getChildComponent (i);
  555. return 0;
  556. }
  557. };
  558. //==============================================================================
  559. class ComponentEditor::InfoPanel : public Component,
  560. public ChangeListener
  561. {
  562. public:
  563. InfoPanel (ComponentEditor& editor_)
  564. : editor (editor_)
  565. {
  566. setOpaque (true);
  567. addAndMakeVisible (props = new PropertyPanel());
  568. editor.getCanvas()->getSelection().addChangeListener (this);
  569. }
  570. ~InfoPanel()
  571. {
  572. editor.getCanvas()->getSelection().removeChangeListener (this);
  573. props->clear();
  574. deleteAllChildren();
  575. }
  576. void changeListenerCallback (void*)
  577. {
  578. Array <PropertyComponent*> newComps;
  579. editor.getCanvas()->getSelectedItemProperties (newComps);
  580. props->clear();
  581. props->addProperties (newComps);
  582. }
  583. void paint (Graphics& g)
  584. {
  585. g.fillAll (Colour::greyLevel (0.92f));
  586. }
  587. void resized()
  588. {
  589. props->setSize (getWidth(), getHeight());
  590. }
  591. private:
  592. ComponentEditor& editor;
  593. PropertyPanel* props;
  594. };
  595. //==============================================================================
  596. ComponentEditor::ComponentEditor (OpenDocumentManager::Document* document,
  597. Project* project_, ComponentDocument* componentDocument_)
  598. : DocumentEditorComponent (document),
  599. project (project_),
  600. componentDocument (componentDocument_),
  601. infoPanel (0)
  602. {
  603. setOpaque (true);
  604. addAndMakeVisible (viewport = new Viewport());
  605. if (document != 0)
  606. {
  607. viewport->setViewedComponent (new Canvas (*this));
  608. addAndMakeVisible (infoPanel = new InfoPanel (*this));
  609. }
  610. }
  611. ComponentEditor::~ComponentEditor()
  612. {
  613. deleteAndZero (infoPanel);
  614. deleteAllChildren();
  615. }
  616. void ComponentEditor::paint (Graphics& g)
  617. {
  618. g.fillAll (Colours::white);
  619. }
  620. void ComponentEditor::resized()
  621. {
  622. const int infoPanelWidth = 200;
  623. viewport->setBounds (0, 0, getWidth() - infoPanelWidth, getHeight());
  624. if (infoPanel != 0)
  625. infoPanel->setBounds (getWidth() - infoPanelWidth, 0, infoPanelWidth, getHeight());
  626. }
  627. ComponentEditor::Canvas* ComponentEditor::getCanvas() const
  628. {
  629. return dynamic_cast <Canvas*> (viewport->getViewedComponent());
  630. }
  631. void ComponentEditor::getAllCommands (Array <CommandID>& commands)
  632. {
  633. DocumentEditorComponent::getAllCommands (commands);
  634. const CommandID ids[] = { CommandIDs::undo,
  635. CommandIDs::redo };
  636. commands.addArray (ids, numElementsInArray (ids));
  637. }
  638. void ComponentEditor::getCommandInfo (CommandID commandID, ApplicationCommandInfo& result)
  639. {
  640. result.setActive (document != 0);
  641. switch (commandID)
  642. {
  643. case CommandIDs::undo:
  644. result.setInfo ("Undo", "Undoes the last change",
  645. CommandCategories::general, 0);
  646. result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::commandModifier, 0));
  647. break;
  648. case CommandIDs::redo:
  649. result.setInfo ("Redo", "Redoes the last change",
  650. CommandCategories::general, 0);
  651. result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0));
  652. result.defaultKeypresses.add (KeyPress ('y', ModifierKeys::commandModifier, 0));
  653. break;
  654. default:
  655. DocumentEditorComponent::getCommandInfo (commandID, result);
  656. break;
  657. }
  658. }
  659. bool ComponentEditor::perform (const InvocationInfo& info)
  660. {
  661. switch (info.commandID)
  662. {
  663. case CommandIDs::undo:
  664. getDocument().getUndoManager()->undo();
  665. return true;
  666. case CommandIDs::redo:
  667. getDocument().getUndoManager()->redo();
  668. return true;
  669. default:
  670. break;
  671. }
  672. return DocumentEditorComponent::perform (info);
  673. }