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.

871 lines
27KB

  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 "../../utility/jucer_TickIterator.h"
  20. #include "jucer_EditorCanvas.h"
  21. #include "jucer_EditorPanel.h"
  22. //==============================================================================
  23. class EditorCanvasBase::ResizeFrame : public EditorCanvasBase::OverlayItemComponent
  24. {
  25. public:
  26. ResizeFrame (EditorCanvasBase* canvas_, const String& objectId_, const ValueTree& objectState_)
  27. : OverlayItemComponent (canvas_),
  28. objectState (objectState_),
  29. objectId (objectId_),
  30. borderThickness (4),
  31. isDragging (false),
  32. isRotating (false),
  33. canRotate (canvas_->canRotate())
  34. {
  35. jassert (objectState.isValid());
  36. }
  37. ~ResizeFrame()
  38. {
  39. }
  40. void paint (Graphics& g)
  41. {
  42. if (! canvas->isRotating())
  43. {
  44. g.setColour (resizableBorderColour);
  45. g.drawRect (0, 0, getWidth(), getHeight(), borderThickness);
  46. g.fillRect (rotateArea);
  47. }
  48. }
  49. void mouseEnter (const MouseEvent& e) { updateDragZone (e.getPosition()); }
  50. void mouseExit (const MouseEvent& e) { updateDragZone (e.getPosition()); }
  51. void mouseMove (const MouseEvent& e) { updateDragZone (e.getPosition()); }
  52. void mouseDown (const MouseEvent& e)
  53. {
  54. updateDragZone (e.getPosition());
  55. isDragging = false;
  56. if (e.mods.isPopupMenu())
  57. {
  58. canvas->showPopupMenu (true);
  59. }
  60. }
  61. void mouseDrag (const MouseEvent& e)
  62. {
  63. if (! (isDragging || e.mods.isPopupMenu() || e.mouseWasClicked()))
  64. {
  65. isDragging = true;
  66. bool isRotating = rotateArea.contains (e.getMouseDownPosition());
  67. canvas->beginDrag (e.withNewPosition (e.getMouseDownPosition()),
  68. dragZone, isRotating, canvas->getObjectPosition (objectState).getCentre().toFloat());
  69. if (! isRotating)
  70. canvas->showSizeGuides();
  71. repaint();
  72. }
  73. if (isDragging)
  74. {
  75. canvas->continueDrag (e);
  76. autoScrollForMouseEvent (e);
  77. }
  78. }
  79. void mouseUp (const MouseEvent& e)
  80. {
  81. if (isDragging || isRotating)
  82. {
  83. isRotating = false;
  84. canvas->hideSizeGuides();
  85. canvas->endDrag (e);
  86. updateDragZone (e.getPosition());
  87. repaint();
  88. }
  89. }
  90. void mouseDoubleClick (const MouseEvent& e)
  91. {
  92. canvas->objectDoubleClicked (e, objectState);
  93. }
  94. bool hitTest (int x, int y)
  95. {
  96. if (ModifierKeys::getCurrentModifiers().isAnyModifierKeyDown())
  97. return rotateArea.contains (x, y) || ! getCentreArea().contains (x, y);
  98. return true;
  99. }
  100. bool updatePosition()
  101. {
  102. if (! objectState.getParent().isValid())
  103. return false;
  104. const Rectangle<int> bounds (canvas->getObjectPosition (objectState));
  105. setBoundsInTargetSpace (bounds.expanded (borderThickness, borderThickness));
  106. if (canRotate)
  107. rotateArea = Rectangle<int> (2, 2, 10, 10);
  108. int i;
  109. for (i = sizeGuides.size(); --i >= 0;)
  110. {
  111. sizeGuides.getUnchecked(i)->setVisible (isVisible());
  112. sizeGuides.getUnchecked(i)->updatePosition (bounds);
  113. }
  114. return true;
  115. }
  116. const String& getTargetObjectID() const { return objectId; }
  117. //==============================================================================
  118. class SizeGuideComponent : public OverlayItemComponent,
  119. public ComponentListener
  120. {
  121. public:
  122. enum Type { left, right, top, bottom };
  123. //==============================================================================
  124. SizeGuideComponent (EditorCanvasBase* canvas_, const ValueTree& state_, Type type_)
  125. : OverlayItemComponent (canvas_), state (state_), type (type_)
  126. {
  127. setAlwaysOnTop (true);
  128. canvas->addAndMakeVisible (this);
  129. setInterceptsMouseClicks (false, false);
  130. }
  131. //==============================================================================
  132. void paint (Graphics& g)
  133. {
  134. const float dashes[] = { 4.0f, 3.0f };
  135. g.setColour (resizableBorderColour);
  136. g.drawDashedLine (0.5f, 0.5f, getWidth() - 0.5f, getHeight() - 0.5f, dashes, 2, 1.0f);
  137. }
  138. //==============================================================================
  139. void updatePosition (const Rectangle<int>& bounds)
  140. {
  141. RelativeRectangle coords (canvas->getObjectCoords (state));
  142. RelativeCoordinate coord;
  143. Rectangle<int> r;
  144. switch (type)
  145. {
  146. case left: coord = coords.left; r.setBounds (bounds.getX(), 0, 1, bounds.getY()); break;
  147. case right: coord = coords.right; r.setBounds (bounds.getRight(), 0, 1, bounds.getY()); break;
  148. case top: coord = coords.top; r.setBounds (0, bounds.getY(), bounds.getX(), 1); break;
  149. case bottom: coord = coords.bottom; r.setBounds (0, bounds.getBottom(), bounds.getX(), 1); break;
  150. default: jassertfalse; break;
  151. }
  152. setBoundsInTargetSpace (r);
  153. label.update (getParentComponent(), coord.toString(), Colours::darkgrey, getX(), getY(), type != left, type != top);
  154. }
  155. private:
  156. ValueTree state;
  157. Type type;
  158. FloatingLabelComponent label;
  159. };
  160. void showSizeGuides()
  161. {
  162. if (sizeGuides.size() == 0 && canvas->hasSizeGuides())
  163. {
  164. sizeGuides.add (new SizeGuideComponent (canvas, objectState, SizeGuideComponent::left));
  165. sizeGuides.add (new SizeGuideComponent (canvas, objectState, SizeGuideComponent::right));
  166. sizeGuides.add (new SizeGuideComponent (canvas, objectState, SizeGuideComponent::top));
  167. sizeGuides.add (new SizeGuideComponent (canvas, objectState, SizeGuideComponent::bottom));
  168. }
  169. }
  170. void hideSizeGuides()
  171. {
  172. sizeGuides.clear();
  173. }
  174. private:
  175. ValueTree objectState;
  176. String objectId;
  177. ResizableBorderComponent::Zone dragZone;
  178. const int borderThickness;
  179. OwnedArray <SizeGuideComponent> sizeGuides;
  180. Rectangle<int> rotateArea;
  181. bool isDragging, canRotate, isRotating;
  182. const Rectangle<int> getCentreArea() const
  183. {
  184. return getLocalBounds().reduced (borderThickness, borderThickness);
  185. }
  186. void updateDragZone (const Point<int>& p)
  187. {
  188. ResizableBorderComponent::Zone newZone
  189. = ResizableBorderComponent::Zone::fromPositionOnBorder (getLocalBounds(),
  190. BorderSize (borderThickness), p);
  191. if (dragZone != newZone)
  192. {
  193. dragZone = newZone;
  194. setMouseCursor (newZone.getMouseCursor());
  195. }
  196. }
  197. };
  198. //==============================================================================
  199. class EditorCanvasBase::OverlayComponent : public Component,
  200. public LassoSource <SelectedItems::ItemType>,
  201. public ChangeListener
  202. {
  203. public:
  204. OverlayComponent (EditorCanvasBase* canvas_)
  205. : canvas (canvas_)
  206. {
  207. setWantsKeyboardFocus (true);
  208. getSelection().addChangeListener (this);
  209. }
  210. ~OverlayComponent()
  211. {
  212. getSelection().removeChangeListener (this);
  213. lasso = 0;
  214. resizers.clear();
  215. controlPoints.clear();
  216. deleteAllChildren();
  217. }
  218. //==============================================================================
  219. void mouseDown (const MouseEvent& e)
  220. {
  221. lasso = 0;
  222. mouseDownCompUID = SelectedItems::ItemType();
  223. isDraggingClickedComp = false;
  224. const MouseEvent e2 (e.getEventRelativeTo (canvas->getComponentHolder()));
  225. const SelectedItems::ItemType underMouse (canvas->findObjectIdAt (canvas->screenSpaceToObjectSpace (e2.getPosition())));
  226. if (e.mods.isPopupMenu())
  227. {
  228. if (underMouse.isNotEmpty() && ! getSelection().isSelected (underMouse))
  229. {
  230. canvas->enableResizingMode();
  231. getSelection().selectOnly (underMouse);
  232. }
  233. canvas->showPopupMenu (underMouse.isNotEmpty());
  234. }
  235. else
  236. {
  237. if (underMouse.isEmpty() || e.mods.isAltDown())
  238. {
  239. canvas->deselectNonDraggableObjects();
  240. addAndMakeVisible (lasso = new LassoComponent <SelectedItems::ItemType>());
  241. lasso->beginLasso (e, this);
  242. }
  243. else
  244. {
  245. mouseDownCompUID = underMouse;
  246. canvas->deselectNonDraggableObjects();
  247. canvas->enableResizingMode();
  248. mouseDownResult = getSelection().addToSelectionOnMouseDown (mouseDownCompUID, e.mods);
  249. updateResizeFrames();
  250. hideSizeGuides();
  251. showSizeGuides();
  252. }
  253. }
  254. }
  255. void mouseDrag (const MouseEvent& e)
  256. {
  257. if (lasso != 0)
  258. {
  259. lasso->dragLasso (e);
  260. }
  261. else
  262. {
  263. if ((! isDraggingClickedComp)
  264. && mouseDownCompUID.isNotEmpty()
  265. && (! e.mouseWasClicked())
  266. && (! e.mods.isPopupMenu())
  267. && e.getDistanceFromDragStart() > 7) // whenever this drag occurs, it's selecting the object
  268. // and beginning a drag, so allow for more wobble than
  269. // when when dragging an already-selected object
  270. {
  271. isDraggingClickedComp = true;
  272. canvas->enableResizingMode();
  273. getSelection().addToSelectionOnMouseUp (mouseDownCompUID, e.mods, true, mouseDownResult);
  274. canvas->beginDrag (e.withNewPosition (e.getMouseDownPosition()),
  275. ResizableBorderComponent::Zone (ResizableBorderComponent::Zone::centre),
  276. false, Point<float>());
  277. }
  278. if (isDraggingClickedComp)
  279. {
  280. canvas->continueDrag (e);
  281. showSizeGuides();
  282. }
  283. }
  284. autoScrollForMouseEvent (e);
  285. }
  286. void mouseUp (const MouseEvent& e)
  287. {
  288. hideSizeGuides();
  289. if (lasso != 0)
  290. {
  291. lasso->endLasso();
  292. lasso = 0;
  293. if (e.mouseWasClicked())
  294. getSelection().deselectAll();
  295. }
  296. else if (! e.mods.isPopupMenu())
  297. {
  298. if (! isDraggingClickedComp)
  299. getSelection().addToSelectionOnMouseUp (mouseDownCompUID, e.mods, ! e.mouseWasClicked(), mouseDownResult);
  300. }
  301. canvas->endDrag (e);
  302. }
  303. void mouseDoubleClick (const MouseEvent& e)
  304. {
  305. const MouseEvent e2 (e.getEventRelativeTo (canvas->getComponentHolder()));
  306. const SelectedItems::ItemType underMouse (canvas->findObjectIdAt (canvas->screenSpaceToObjectSpace (e2.getPosition())));
  307. if (underMouse.isNotEmpty())
  308. {
  309. const ValueTree state (canvas->getObjectState (underMouse));
  310. canvas->objectDoubleClicked (e2, state);
  311. }
  312. }
  313. void findLassoItemsInArea (Array <SelectedItems::ItemType>& itemsFound, const Rectangle<int>& area)
  314. {
  315. const Rectangle<int> sourceArea (area + relativePositionToOtherComponent (canvas->getComponentHolder(), Point<int>()));
  316. canvas->findLassoItemsInArea (itemsFound, canvas->screenSpaceToObjectSpace (sourceArea));
  317. }
  318. SelectedItems& getSelection() { return canvas->getSelection(); }
  319. SelectedItems& getLassoSelection() { return getSelection(); }
  320. void changeListenerCallback (void*)
  321. {
  322. update();
  323. }
  324. void modifierKeysChanged (const ModifierKeys&)
  325. {
  326. Desktop::getInstance().getMainMouseSource().triggerFakeMove();
  327. }
  328. void showSizeGuides()
  329. {
  330. if (canvas->hasSizeGuides())
  331. {
  332. for (int i = getNumChildComponents(); --i >= 0;)
  333. {
  334. ResizeFrame* resizer = dynamic_cast <ResizeFrame*> (getChildComponent(i));
  335. if (resizer != 0)
  336. resizer->showSizeGuides();
  337. }
  338. }
  339. }
  340. void hideSizeGuides()
  341. {
  342. if (canvas->hasSizeGuides())
  343. {
  344. for (int i = getNumChildComponents(); --i >= 0;)
  345. {
  346. ResizeFrame* resizer = dynamic_cast <ResizeFrame*> (getChildComponent(i));
  347. if (resizer != 0)
  348. resizer->hideSizeGuides();
  349. }
  350. }
  351. }
  352. void update()
  353. {
  354. updateResizeFrames();
  355. updateControlPoints();
  356. }
  357. private:
  358. //==============================================================================
  359. EditorCanvasBase* canvas;
  360. ScopedPointer <LassoComponent <SelectedItems::ItemType> > lasso;
  361. bool mouseDownResult, isDraggingClickedComp;
  362. SelectedItems::ItemType mouseDownCompUID;
  363. OwnedArray <ResizeFrame> resizers;
  364. OwnedArray <OverlayItemComponent> controlPoints;
  365. void updateResizeFrames()
  366. {
  367. if (! canvas->isResizingMode())
  368. {
  369. resizers.clear();
  370. return;
  371. }
  372. SelectedItems& selection = getSelection();
  373. StringArray requiredIds;
  374. const int num = selection.getNumSelected();
  375. int i;
  376. for (i = 0; i < num; ++i)
  377. requiredIds.add (selection.getSelectedItem(i));
  378. for (i = resizers.size(); --i >= 0;)
  379. {
  380. ResizeFrame* resizer = resizers.getUnchecked(i);
  381. const int index = requiredIds.indexOf (resizer->getTargetObjectID());
  382. if (index >= 0)
  383. {
  384. if (resizer->updatePosition())
  385. {
  386. requiredIds.remove (index);
  387. }
  388. else
  389. {
  390. resizers.remove (i);
  391. canvas->getSelection().deselect (requiredIds[i]);
  392. }
  393. }
  394. else
  395. {
  396. resizers.remove (i);
  397. }
  398. }
  399. for (i = requiredIds.size(); --i >= 0;)
  400. {
  401. const ValueTree state (canvas->getObjectState (requiredIds[i]));
  402. if (state.isValid()) // (the id may be a marker)
  403. {
  404. ResizeFrame* frame = new ResizeFrame (canvas, requiredIds[i], state);
  405. resizers.add (frame);
  406. addAndMakeVisible (frame);
  407. frame->updatePosition();
  408. }
  409. }
  410. }
  411. void updateControlPoints()
  412. {
  413. if (! canvas->isControlPointMode())
  414. {
  415. controlPoints.clear();
  416. return;
  417. }
  418. canvas->updateControlPointComponents (this, controlPoints);
  419. }
  420. };
  421. //==============================================================================
  422. class EditorCanvasBase::DocumentResizeFrame : public Component
  423. {
  424. public:
  425. DocumentResizeFrame (EditorCanvasBase* canvas_)
  426. : canvas (canvas_), resizerThickness (4)
  427. {
  428. }
  429. ~DocumentResizeFrame()
  430. {
  431. }
  432. void paint (Graphics& g)
  433. {
  434. const Rectangle<int> content (getContentArea());
  435. g.setColour (Colour::greyLevel (0.1f).withAlpha (0.3f));
  436. g.drawRect (content.expanded (1, 1), 1);
  437. const int bottomGap = getHeight() - content.getBottom();
  438. g.setFont (bottomGap - 5.0f);
  439. g.setColour (Colour::greyLevel (0.9f));
  440. g.drawText (String (content.getWidth()) + " x " + String (content.getHeight()),
  441. 0, 0, jmax (content.getRight(), jmin (60, getWidth())), getHeight(), Justification::bottomRight, false);
  442. }
  443. void mouseMove (const MouseEvent& e)
  444. {
  445. updateDragZone (e.getPosition());
  446. }
  447. void mouseDown (const MouseEvent& e)
  448. {
  449. updateDragZone (e.getPosition());
  450. dragStartBounds = canvas->getCanvasBounds();
  451. canvas->showSizeGuides();
  452. }
  453. void mouseDrag (const MouseEvent& e)
  454. {
  455. Rectangle<int> newBounds (dragStartBounds);
  456. if (dragZone.isDraggingRightEdge())
  457. newBounds.setWidth (jmax (1, newBounds.getWidth() + e.getDistanceFromDragStartX()));
  458. if (dragZone.isDraggingBottomEdge())
  459. newBounds.setHeight (jmax (1, newBounds.getHeight() + e.getDistanceFromDragStartY()));
  460. canvas->setCanvasBounds (newBounds);
  461. }
  462. void mouseUp (const MouseEvent& e)
  463. {
  464. canvas->hideSizeGuides();
  465. updateDragZone (e.getPosition());
  466. }
  467. void updateDragZone (const Point<int>& p)
  468. {
  469. ResizableBorderComponent::Zone newZone
  470. = ResizableBorderComponent::Zone::fromPositionOnBorder (getContentArea().expanded (resizerThickness, resizerThickness),
  471. BorderSize (0, 0, resizerThickness, resizerThickness), p);
  472. if (dragZone != newZone)
  473. {
  474. dragZone = newZone;
  475. setMouseCursor (newZone.getMouseCursor());
  476. }
  477. }
  478. bool hitTest (int x, int y)
  479. {
  480. if (! canvas->canResizeCanvas())
  481. return false;
  482. const Rectangle<int> content (getContentArea());
  483. return (x >= content.getRight() || y >= content.getBottom())
  484. && (! content.contains (x, y))
  485. && content.expanded (resizerThickness, resizerThickness).contains (x, y);
  486. }
  487. private:
  488. EditorCanvasBase* canvas;
  489. ResizableBorderComponent::Zone dragZone;
  490. Rectangle<int> dragStartBounds;
  491. const int resizerThickness;
  492. const Rectangle<int> getContentArea() const { return canvas->getContentArea(); }
  493. };
  494. //==============================================================================
  495. EditorCanvasBase::EditorCanvasBase()
  496. : border (8, 8, 14, 14)
  497. {
  498. //setOpaque (true);
  499. addChildComponent (&spacebarDragOverlay);
  500. }
  501. EditorCanvasBase::~EditorCanvasBase()
  502. {
  503. jassert (overlay == 0);
  504. }
  505. void EditorCanvasBase::initialise()
  506. {
  507. addAndMakeVisible (componentHolder = createComponentHolder());
  508. addAndMakeVisible (overlay = new OverlayComponent (this));
  509. overlay->addAndMakeVisible (resizeFrame = new DocumentResizeFrame (this));
  510. handleAsyncUpdate();
  511. }
  512. void EditorCanvasBase::shutdown()
  513. {
  514. dragger = 0;
  515. resizeFrame = 0;
  516. overlay = 0;
  517. componentHolder = 0;
  518. }
  519. EditorPanelBase* EditorCanvasBase::getPanel() const
  520. {
  521. return findParentComponentOfClass ((EditorPanelBase*) 0);
  522. }
  523. const Point<int> EditorCanvasBase::screenSpaceToObjectSpace (const Point<int>& p) const
  524. {
  525. return p - scale.origin;
  526. }
  527. const Point<int> EditorCanvasBase::objectSpaceToScreenSpace (const Point<int>& p) const
  528. {
  529. return p + scale.origin;
  530. }
  531. const Point<float> EditorCanvasBase::screenSpaceToObjectSpace (const Point<float>& p) const
  532. {
  533. return p - scale.origin.toFloat();
  534. }
  535. const Point<float> EditorCanvasBase::objectSpaceToScreenSpace (const Point<float>& p) const
  536. {
  537. return p + scale.origin.toFloat();
  538. }
  539. const Rectangle<int> EditorCanvasBase::screenSpaceToObjectSpace (const Rectangle<int>& r) const
  540. {
  541. return r - scale.origin;
  542. }
  543. const Rectangle<int> EditorCanvasBase::objectSpaceToScreenSpace (const Rectangle<int>& r) const
  544. {
  545. return r + scale.origin;
  546. }
  547. void EditorCanvasBase::enableResizingMode()
  548. {
  549. enableControlPointMode (ValueTree::invalid);
  550. }
  551. void EditorCanvasBase::enableControlPointMode (const ValueTree& objectToEdit)
  552. {
  553. if (controlPointEditingTarget != objectToEdit)
  554. {
  555. controlPointEditingTarget = objectToEdit;
  556. getSelection().deselectAll();
  557. overlay->update();
  558. }
  559. }
  560. bool EditorCanvasBase::isRotating() const
  561. {
  562. return dragger != 0 && dragger->isRotating();
  563. }
  564. //==============================================================================
  565. void EditorCanvasBase::paint (Graphics& g)
  566. {
  567. }
  568. bool EditorCanvasBase::keyStateChanged (bool)
  569. {
  570. return spacebarDragOverlay.updateVisibility();
  571. }
  572. bool EditorCanvasBase::keyPressed (const KeyPress& key)
  573. {
  574. return key.isKeyCode (KeyPress::spaceKey); // required to consume the spacebar events and avoid a warning beep
  575. }
  576. void EditorCanvasBase::setScale (const Scale& newScale)
  577. {
  578. jassertfalse;
  579. }
  580. const Rectangle<int> EditorCanvasBase::getContentArea() const
  581. {
  582. return border.subtractedFrom (getLocalBounds());
  583. }
  584. //==============================================================================
  585. void EditorCanvasBase::handleAsyncUpdate()
  586. {
  587. documentChanged();
  588. const Rectangle<int> canvasBounds (getCanvasBounds());
  589. const Point<int> newOrigin (jmax (0, -canvasBounds.getX()), jmax (0, -canvasBounds.getY()));
  590. const int newWidth = jmax (canvasBounds.getWidth(), canvasBounds.getRight()) + border.getLeftAndRight();
  591. const int newHeight = jmax (canvasBounds.getHeight(), canvasBounds.getBottom()) + border.getTopAndBottom();
  592. if (scale.origin != newOrigin)
  593. {
  594. repaint();
  595. const Point<int> oldOrigin (scale.origin);
  596. scale.origin = newOrigin;
  597. setBounds (jmin (0, getX() + oldOrigin.getX() - scale.origin.getX()),
  598. jmin (0, getY() + oldOrigin.getY() - scale.origin.getY()),
  599. newWidth, newHeight);
  600. EditorPanelBase* panel = getPanel();
  601. if (panel != 0)
  602. panel->updateRulers();
  603. }
  604. else if (getWidth() != newWidth || getHeight() != newHeight)
  605. {
  606. setSize (newWidth, newHeight);
  607. }
  608. else
  609. {
  610. overlay->update();
  611. EditorPanelBase* panel = getPanel();
  612. if (panel != 0)
  613. panel->updateMarkers();
  614. }
  615. }
  616. void EditorCanvasBase::resized()
  617. {
  618. componentHolder->setBounds (getContentArea());
  619. overlay->setBounds (getLocalBounds());
  620. resizeFrame->setBounds (getLocalBounds());
  621. spacebarDragOverlay.setBounds (getLocalBounds());
  622. overlay->update();
  623. handleUpdateNowIfNeeded();
  624. }
  625. //==============================================================================
  626. void EditorCanvasBase::showSizeGuides() { overlay->showSizeGuides(); }
  627. void EditorCanvasBase::hideSizeGuides() { overlay->hideSizeGuides(); }
  628. //==============================================================================
  629. void EditorCanvasBase::beginDrag (const MouseEvent& e, const ResizableBorderComponent::Zone& zone,
  630. bool isRotating, const Point<float>& rotationCentre)
  631. {
  632. dragger = createDragOperation (screenSpaceToObjectSpace (e.getEventRelativeTo (overlay).getPosition()), overlay, zone, isRotating);
  633. dragger->setRotationCentre (rotationCentre);
  634. repaint();
  635. }
  636. void EditorCanvasBase::continueDrag (const MouseEvent& e)
  637. {
  638. MouseEvent e2 (e.getEventRelativeTo (overlay));
  639. if (dragger != 0)
  640. dragger->drag (e2, screenSpaceToObjectSpace (e2.getPosition()));
  641. }
  642. void EditorCanvasBase::endDrag (const MouseEvent& e)
  643. {
  644. if (dragger != 0)
  645. {
  646. MouseEvent e2 (e.getEventRelativeTo (overlay));
  647. dragger->drag (e2, screenSpaceToObjectSpace (e2.getPosition()));
  648. dragger = 0;
  649. getUndoManager().beginNewTransaction();
  650. repaint();
  651. }
  652. }
  653. //==============================================================================
  654. EditorCanvasBase::OverlayItemComponent::OverlayItemComponent (EditorCanvasBase* canvas_)
  655. : canvas (canvas_)
  656. {
  657. }
  658. EditorCanvasBase::OverlayItemComponent::~OverlayItemComponent()
  659. {
  660. }
  661. void EditorCanvasBase::OverlayItemComponent::setBoundsInTargetSpace (const Rectangle<int>& r)
  662. {
  663. setBounds (canvas->objectSpaceToScreenSpace (r)
  664. + canvas->getComponentHolder()->relativePositionToOtherComponent (getParentComponent(), Point<int>()));
  665. }
  666. const Point<float> EditorCanvasBase::OverlayItemComponent::pointToLocalSpace (const Point<float>& p) const
  667. {
  668. return canvas->objectSpaceToScreenSpace (p)
  669. + (canvas->getComponentHolder()->relativePositionToOtherComponent (getParentComponent(), Point<int>())
  670. - getPosition()).toFloat();
  671. }
  672. //==============================================================================
  673. EditorCanvasBase::SpacebarDragOverlay::SpacebarDragOverlay()
  674. {
  675. setAlwaysOnTop (true);
  676. setMouseCursor (MouseCursor::DraggingHandCursor);
  677. }
  678. EditorCanvasBase::SpacebarDragOverlay::~SpacebarDragOverlay()
  679. {
  680. }
  681. bool EditorCanvasBase::SpacebarDragOverlay::updateVisibility()
  682. {
  683. bool isSpaceDown = KeyPress::isKeyCurrentlyDown (KeyPress::spaceKey);
  684. if (isSpaceDown == isVisible())
  685. return false;
  686. setVisible (isSpaceDown);
  687. return true;
  688. }
  689. void EditorCanvasBase::SpacebarDragOverlay::paint (Graphics&)
  690. {
  691. }
  692. void EditorCanvasBase::SpacebarDragOverlay::mouseMove (const MouseEvent& e)
  693. {
  694. updateVisibility();
  695. }
  696. void EditorCanvasBase::SpacebarDragOverlay::mouseDown (const MouseEvent& e)
  697. {
  698. Viewport* vp = findParentComponentOfClass ((Viewport*) 0);
  699. if (vp != 0)
  700. dragStart = vp->getViewPosition();
  701. }
  702. void EditorCanvasBase::SpacebarDragOverlay::mouseDrag (const MouseEvent& e)
  703. {
  704. Viewport* vp = findParentComponentOfClass ((Viewport*) 0);
  705. if (vp != 0)
  706. vp->setViewPosition (dragStart - Point<int> (e.getDistanceFromDragStartX(),
  707. e.getDistanceFromDragStartY()));
  708. }
  709. void EditorCanvasBase::SpacebarDragOverlay::modifierKeysChanged (const ModifierKeys& modifiers)
  710. {
  711. }
  712. //==============================================================================
  713. EditorCanvasBase::Scale::Scale()
  714. : scale (1.0)
  715. {
  716. }