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.

274 lines
9.2KB

  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. #ifndef __JUCER_COMPONENTEDITORCANVAS_H_37C33B56__
  19. #define __JUCER_COMPONENTEDITORCANVAS_H_37C33B56__
  20. //==============================================================================
  21. class ComponentEditorCanvas : public EditorCanvasBase,
  22. public Timer
  23. {
  24. public:
  25. //==============================================================================
  26. ComponentEditorCanvas (ComponentEditor& editor_)
  27. : editor (editor_)
  28. {
  29. initialise();
  30. getDocument().getRoot().addListener (this);
  31. }
  32. ~ComponentEditorCanvas()
  33. {
  34. getDocument().getRoot().removeListener (this);
  35. shutdown();
  36. }
  37. ComponentEditor& getEditor() { return editor; }
  38. ComponentDocument& getDocument() { return editor.getDocument(); }
  39. void timerCallback()
  40. {
  41. stopTimer();
  42. if (! Component::isMouseButtonDownAnywhere())
  43. getDocument().beginNewTransaction();
  44. }
  45. static Component* findComponentForState (Component* compHolder, ComponentDocument& doc, const ValueTree& state)
  46. {
  47. for (int i = compHolder->getNumChildComponents(); --i >= 0;)
  48. {
  49. Component* const c = compHolder->getChildComponent (i);
  50. if (doc.isStateForComponent (state, c))
  51. return c;
  52. }
  53. return 0;
  54. }
  55. static void updateComponentsIn (Component* compHolder, ComponentDocument& doc, SelectedItems& selection)
  56. {
  57. int i;
  58. for (i = compHolder->getNumChildComponents(); --i >= 0;)
  59. {
  60. Component* c = compHolder->getChildComponent (i);
  61. if (! doc.containsComponent (c))
  62. {
  63. selection.deselect (ComponentDocument::getJucerIDFor (c));
  64. delete c;
  65. }
  66. }
  67. Array <Component*> componentsInOrder;
  68. const int num = doc.getNumComponents();
  69. for (i = 0; i < num; ++i)
  70. {
  71. const ValueTree v (doc.getComponent (i));
  72. Component* c = findComponentForState (compHolder, doc, v);
  73. if (c == 0)
  74. {
  75. c = doc.createComponent (i);
  76. compHolder->addAndMakeVisible (c);
  77. }
  78. doc.updateComponent (c);
  79. componentsInOrder.add (c);
  80. }
  81. // Make sure the z-order is correct..
  82. if (num > 0)
  83. {
  84. componentsInOrder.getLast()->toFront (false);
  85. for (i = num - 1; --i >= 0;)
  86. componentsInOrder.getUnchecked(i)->toBehind (componentsInOrder.getUnchecked (i + 1));
  87. }
  88. }
  89. void updateComponents()
  90. {
  91. updateComponentsIn (getComponentHolder(), getDocument(), editor.getSelection());
  92. startTimer (500);
  93. }
  94. int getCanvasWidth() { return getDocument().getCanvasWidth().getValue(); }
  95. int getCanvasHeight() { return getDocument().getCanvasHeight().getValue(); }
  96. void setCanvasWidth (int w) { getDocument().getCanvasWidth() = w; }
  97. void setCanvasHeight (int h) { getDocument().getCanvasHeight() = h; }
  98. ComponentDocument::MarkerList& getMarkerList (bool isX)
  99. {
  100. return getDocument().getMarkerList (isX);
  101. }
  102. const SelectedItems::ItemType findObjectIdAt (const Point<int>& position)
  103. {
  104. for (int i = getComponentHolder()->getNumChildComponents(); --i >= 0;)
  105. {
  106. Component* const c = getComponentHolder()->getChildComponent(i);
  107. if (c->getBounds().contains (position))
  108. return ComponentDocument::getJucerIDFor (c);
  109. }
  110. return String::empty;
  111. }
  112. void showPopupMenu (const Point<int>& position)
  113. {
  114. PopupMenu m;
  115. if (findObjectIdAt (position).isNotEmpty())
  116. {
  117. m.addCommandItem (commandManager, CommandIDs::toFront);
  118. m.addCommandItem (commandManager, CommandIDs::toBack);
  119. m.addSeparator();
  120. m.addCommandItem (commandManager, StandardApplicationCommandIDs::del);
  121. const int r = m.show();
  122. (void) r;
  123. }
  124. else
  125. {
  126. getDocument().addNewComponentMenuItems (m);
  127. const int r = m.show();
  128. getDocument().performNewComponentMenuItem (r);
  129. }
  130. }
  131. const ValueTree getObjectState (const String& objectId)
  132. {
  133. return getDocument().getComponentWithID (objectId);
  134. }
  135. const Rectangle<int> getObjectPosition (const ValueTree& state)
  136. {
  137. return getDocument().getCoordsFor (state).resolve (getDocument());
  138. }
  139. RectangleCoordinates getObjectCoords (const ValueTree& state)
  140. {
  141. return getDocument().getCoordsFor (state);
  142. }
  143. SelectedItems& getSelection()
  144. {
  145. return editor.getSelection();
  146. }
  147. void deselectNonDraggableObjects()
  148. {
  149. editor.deselectNonComponents();
  150. }
  151. void findLassoItemsInArea (Array <SelectedItems::ItemType>& itemsFound, const Rectangle<int>& area)
  152. {
  153. for (int i = getComponentHolder()->getNumChildComponents(); --i >= 0;)
  154. {
  155. Component* c = getComponentHolder()->getChildComponent(i);
  156. if (c->getBounds().intersects (area))
  157. itemsFound.add (ComponentDocument::getJucerIDFor (c));
  158. }
  159. }
  160. //==============================================================================
  161. class DragOperation : public EditorDragOperation
  162. {
  163. public:
  164. DragOperation (ComponentEditorCanvas* canvas_,
  165. const MouseEvent& e,
  166. Component* snapGuideParentComp_,
  167. const ResizableBorderComponent::Zone& zone_)
  168. : EditorDragOperation (canvas_, e, snapGuideParentComp_, zone_)
  169. {
  170. }
  171. ~DragOperation()
  172. {
  173. getUndoManager().beginNewTransaction();
  174. }
  175. protected:
  176. ComponentDocument& getDocument() throw() { return static_cast <ComponentEditorCanvas*> (canvas)->getDocument(); }
  177. int getCanvasWidth() { return getDocument().getCanvasWidth().getValue(); }
  178. int getCanvasHeight() { return getDocument().getCanvasHeight().getValue(); }
  179. UndoManager& getUndoManager() { return *getDocument().getUndoManager(); }
  180. const Rectangle<float> getObjectPosition (const ValueTree& state)
  181. {
  182. ComponentDocument& doc = getDocument();
  183. RectangleCoordinates relativePos (doc.getCoordsFor (state));
  184. const Rectangle<int> intPos (relativePos.resolve (doc));
  185. return intPos.toFloat();
  186. }
  187. bool setObjectPosition (ValueTree& state, const Rectangle<float>& newBounds)
  188. {
  189. ComponentDocument& doc = getDocument();
  190. RectangleCoordinates pr (doc.getCoordsFor (state));
  191. pr.moveToAbsolute (newBounds, doc);
  192. return doc.setCoordsFor (state, pr);
  193. }
  194. };
  195. DragOperation* createDragOperation (const MouseEvent& e, Component* snapGuideParentComponent,
  196. const ResizableBorderComponent::Zone& zone)
  197. {
  198. DragOperation* d = new DragOperation (this, e, snapGuideParentComponent, zone);
  199. Array<ValueTree> selected, unselected;
  200. for (int i = getDocument().getNumComponents(); --i >= 0;)
  201. {
  202. const ValueTree v (getDocument().getComponent (i));
  203. if (editor.getSelection().isSelected (v [ComponentDocument::idProperty]))
  204. selected.add (v);
  205. else
  206. unselected.add (v);
  207. }
  208. d->initialise (selected, unselected);
  209. return d;
  210. }
  211. UndoManager& getUndoManager()
  212. {
  213. return *getDocument().getUndoManager();
  214. }
  215. private:
  216. //==============================================================================
  217. ComponentEditor& editor;
  218. };
  219. #endif // __JUCER_COMPONENTEDITORCANVAS_H_37C33B56__