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.

284 lines
9.3KB

  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. Component* createComponentHolder()
  46. {
  47. return new ComponentHolder (getDocument().getBackgroundColour());
  48. }
  49. void updateComponents()
  50. {
  51. getDocument().updateComponentsIn (getComponentHolder());
  52. startTimer (500);
  53. }
  54. int getCanvasWidth() { return getDocument().getCanvasWidth().getValue(); }
  55. int getCanvasHeight() { return getDocument().getCanvasHeight().getValue(); }
  56. void setCanvasWidth (int w) { getDocument().getCanvasWidth() = w; }
  57. void setCanvasHeight (int h) { getDocument().getCanvasHeight() = h; }
  58. ComponentDocument::MarkerList& getMarkerList (bool isX)
  59. {
  60. return getDocument().getMarkerList (isX);
  61. }
  62. const SelectedItems::ItemType findObjectIdAt (const Point<int>& position)
  63. {
  64. for (int i = getComponentHolder()->getNumChildComponents(); --i >= 0;)
  65. {
  66. Component* const c = getComponentHolder()->getChildComponent(i);
  67. if (c->getBounds().contains (position))
  68. return ComponentDocument::getJucerIDFor (c);
  69. }
  70. return String::empty;
  71. }
  72. void showPopupMenu (bool isClickOnSelectedObject)
  73. {
  74. if (isClickOnSelectedObject)
  75. {
  76. PopupMenu m;
  77. m.addCommandItem (commandManager, CommandIDs::toFront);
  78. m.addCommandItem (commandManager, CommandIDs::toBack);
  79. m.addSeparator();
  80. m.addCommandItem (commandManager, StandardApplicationCommandIDs::del);
  81. const int r = m.show();
  82. (void) r;
  83. }
  84. else
  85. {
  86. editor.showNewComponentMenu (0);
  87. }
  88. }
  89. void objectDoubleClicked (const MouseEvent& e, const ValueTree& state)
  90. {
  91. getDocument().componentDoubleClicked (e, state);
  92. }
  93. const ValueTree getObjectState (const String& objectId)
  94. {
  95. return getDocument().getComponentWithID (objectId);
  96. }
  97. const Rectangle<int> getObjectPosition (const ValueTree& state)
  98. {
  99. return getDocument().getCoordsFor (state).resolve (getDocument());
  100. }
  101. RectangleCoordinates getObjectCoords (const ValueTree& state)
  102. {
  103. return getDocument().getCoordsFor (state);
  104. }
  105. SelectedItems& getSelection()
  106. {
  107. return editor.getSelection();
  108. }
  109. void deselectNonDraggableObjects()
  110. {
  111. editor.deselectNonComponents();
  112. }
  113. void findLassoItemsInArea (Array <SelectedItems::ItemType>& itemsFound, const Rectangle<int>& area)
  114. {
  115. for (int i = getComponentHolder()->getNumChildComponents(); --i >= 0;)
  116. {
  117. Component* c = getComponentHolder()->getChildComponent(i);
  118. if (c->getBounds().intersects (area))
  119. itemsFound.add (ComponentDocument::getJucerIDFor (c));
  120. }
  121. }
  122. //==============================================================================
  123. class DragOperation : public EditorDragOperation
  124. {
  125. public:
  126. DragOperation (ComponentEditorCanvas* canvas_,
  127. const MouseEvent& e,
  128. Component* snapGuideParentComp_,
  129. const ResizableBorderComponent::Zone& zone_)
  130. : EditorDragOperation (canvas_, e, snapGuideParentComp_, zone_)
  131. {
  132. }
  133. ~DragOperation()
  134. {
  135. getUndoManager().beginNewTransaction();
  136. }
  137. protected:
  138. ComponentDocument& getDocument() throw() { return static_cast <ComponentEditorCanvas*> (canvas)->getDocument(); }
  139. int getCanvasWidth() { return getDocument().getCanvasWidth().getValue(); }
  140. int getCanvasHeight() { return getDocument().getCanvasHeight().getValue(); }
  141. UndoManager& getUndoManager() { return *getDocument().getUndoManager(); }
  142. const Rectangle<float> getObjectPosition (const ValueTree& state)
  143. {
  144. ComponentDocument& doc = getDocument();
  145. RectangleCoordinates relativePos (doc.getCoordsFor (state));
  146. const Rectangle<int> intPos (relativePos.resolve (doc));
  147. return intPos.toFloat();
  148. }
  149. bool setObjectPosition (ValueTree& state, const Rectangle<float>& newBounds)
  150. {
  151. ComponentDocument& doc = getDocument();
  152. RectangleCoordinates pr (doc.getCoordsFor (state));
  153. pr.moveToAbsolute (newBounds, doc);
  154. return doc.setCoordsFor (state, pr);
  155. }
  156. float getMarkerPosition (const ValueTree& marker, bool isX)
  157. {
  158. ComponentDocument& doc = getDocument();
  159. return (float) doc.getMarkerList (isX).getCoordinate (marker).resolve (doc);
  160. }
  161. };
  162. DragOperation* createDragOperation (const MouseEvent& e, Component* snapGuideParentComponent,
  163. const ResizableBorderComponent::Zone& zone)
  164. {
  165. DragOperation* d = new DragOperation (this, e, snapGuideParentComponent, zone);
  166. Array<ValueTree> selected, unselected;
  167. for (int i = getDocument().getNumComponents(); --i >= 0;)
  168. {
  169. const ValueTree v (getDocument().getComponent (i));
  170. if (editor.getSelection().isSelected (v [ComponentDocument::idProperty]))
  171. selected.add (v);
  172. else
  173. unselected.add (v);
  174. }
  175. d->initialise (selected, unselected);
  176. return d;
  177. }
  178. UndoManager& getUndoManager()
  179. {
  180. return *getDocument().getUndoManager();
  181. }
  182. private:
  183. //==============================================================================
  184. ComponentEditor& editor;
  185. class ComponentHolder : public Component,
  186. public Value::Listener
  187. {
  188. public:
  189. ComponentHolder (const Value& backgroundColour_)
  190. : backgroundColour (backgroundColour_)
  191. {
  192. setOpaque (true);
  193. updateColour();
  194. backgroundColour.addListener (this);
  195. }
  196. ~ComponentHolder()
  197. {
  198. deleteAllChildren();
  199. }
  200. void updateColour()
  201. {
  202. Colour newColour (Colours::white);
  203. if (backgroundColour.toString().isNotEmpty())
  204. newColour = Colour::fromString (backgroundColour.toString());
  205. if (newColour != colour)
  206. {
  207. colour = newColour;
  208. repaint();
  209. }
  210. }
  211. void paint (Graphics& g)
  212. {
  213. if (colour.isOpaque())
  214. g.fillAll (colour);
  215. else
  216. g.fillCheckerBoard (0, 0, getWidth(), getHeight(), 24, 24,
  217. Colour (0xffeeeeee).overlaidWith (colour),
  218. Colour (0xffffffff).overlaidWith (colour));
  219. }
  220. void valueChanged (Value&)
  221. {
  222. updateColour();
  223. }
  224. private:
  225. Value backgroundColour;
  226. Colour colour;
  227. };
  228. };
  229. #endif // __JUCER_COMPONENTEDITORCANVAS_H_37C33B56__