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.

283 lines
8.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. #include "../../Application/jucer_Headers.h"
  20. #include "../../Application/jucer_Application.h"
  21. #include "../UI/jucer_JucerCommandIDs.h"
  22. #include "jucer_PaintRoutineEditor.h"
  23. #include "../jucer_ObjectTypes.h"
  24. #include "jucer_JucerDocumentEditor.h"
  25. //==============================================================================
  26. PaintRoutineEditor::PaintRoutineEditor (PaintRoutine& pr, JucerDocument& doc,
  27. JucerDocumentEditor* docHolder)
  28. : graphics (pr),
  29. document (doc),
  30. documentHolder (docHolder),
  31. componentOverlay (nullptr),
  32. componentOverlayOpacity (0.0f)
  33. {
  34. refreshAllElements();
  35. setSize (document.getInitialWidth(),
  36. document.getInitialHeight());
  37. }
  38. PaintRoutineEditor::~PaintRoutineEditor()
  39. {
  40. document.removeChangeListener (this);
  41. removeAllElementComps();
  42. removeChildComponent (&lassoComp);
  43. deleteAllChildren();
  44. }
  45. void PaintRoutineEditor::removeAllElementComps()
  46. {
  47. for (int i = getNumChildComponents(); --i >= 0;)
  48. if (PaintElement* const e = dynamic_cast<PaintElement*> (getChildComponent (i)))
  49. removeChildComponent (e);
  50. }
  51. Rectangle<int> PaintRoutineEditor::getComponentArea() const
  52. {
  53. if (document.isFixedSize())
  54. return Rectangle<int> ((getWidth() - document.getInitialWidth()) / 2,
  55. (getHeight() - document.getInitialHeight()) / 2,
  56. document.getInitialWidth(),
  57. document.getInitialHeight());
  58. return getLocalBounds().reduced (4);
  59. }
  60. //==============================================================================
  61. void PaintRoutineEditor::paint (Graphics& g)
  62. {
  63. const Rectangle<int> clip (getComponentArea());
  64. g.reduceClipRegion (clip);
  65. g.setOrigin (clip.getPosition());
  66. graphics.fillWithBackground (g, true);
  67. grid.draw (g, &graphics);
  68. }
  69. void PaintRoutineEditor::paintOverChildren (Graphics& g)
  70. {
  71. if (componentOverlay.isNull() && document.getComponentOverlayOpacity() > 0.0f)
  72. updateComponentOverlay();
  73. if (componentOverlay.isValid())
  74. {
  75. const Rectangle<int> clip (getComponentArea());
  76. g.drawImageAt (componentOverlay, clip.getX(), clip.getY());
  77. }
  78. }
  79. void PaintRoutineEditor::resized()
  80. {
  81. if (getWidth() > 0 && getHeight() > 0)
  82. {
  83. componentOverlay = Image();
  84. refreshAllElements();
  85. }
  86. }
  87. void PaintRoutineEditor::updateChildBounds()
  88. {
  89. const Rectangle<int> clip (getComponentArea());
  90. for (int i = 0; i < getNumChildComponents(); ++i)
  91. if (PaintElement* const e = dynamic_cast<PaintElement*> (getChildComponent (i)))
  92. e->updateBounds (clip);
  93. }
  94. void PaintRoutineEditor::updateComponentOverlay()
  95. {
  96. if (componentOverlay.isValid())
  97. repaint();
  98. componentOverlay = Image();
  99. componentOverlayOpacity = document.getComponentOverlayOpacity();
  100. if (componentOverlayOpacity > 0.0f)
  101. {
  102. if (documentHolder != nullptr)
  103. componentOverlay = documentHolder->createComponentLayerSnapshot();
  104. if (componentOverlay.isValid())
  105. {
  106. componentOverlay.multiplyAllAlphas (componentOverlayOpacity);
  107. repaint();
  108. }
  109. }
  110. }
  111. void PaintRoutineEditor::visibilityChanged()
  112. {
  113. document.beginTransaction();
  114. if (isVisible())
  115. {
  116. refreshAllElements();
  117. document.addChangeListener (this);
  118. }
  119. else
  120. {
  121. document.removeChangeListener (this);
  122. componentOverlay = Image();
  123. }
  124. }
  125. void PaintRoutineEditor::refreshAllElements()
  126. {
  127. for (int i = getNumChildComponents(); --i >= 0;)
  128. if (auto* e = dynamic_cast<PaintElement*> (getChildComponent (i)))
  129. if (! graphics.containsElement (e))
  130. removeChildComponent (e);
  131. Component* last = nullptr;
  132. for (int i = graphics.getNumElements(); --i >= 0;)
  133. {
  134. auto* e = graphics.getElement (i);
  135. addAndMakeVisible (e);
  136. if (last != nullptr)
  137. e->toBehind (last);
  138. else
  139. e->toFront (false);
  140. last = e;
  141. }
  142. updateChildBounds();
  143. if (grid.updateFromDesign (document))
  144. repaint();
  145. if (currentBackgroundColour != graphics.getBackgroundColour())
  146. {
  147. currentBackgroundColour = graphics.getBackgroundColour();
  148. repaint();
  149. }
  150. if (componentOverlayOpacity != document.getComponentOverlayOpacity())
  151. {
  152. componentOverlay = Image();
  153. componentOverlayOpacity = document.getComponentOverlayOpacity();
  154. repaint();
  155. }
  156. }
  157. void PaintRoutineEditor::changeListenerCallback (ChangeBroadcaster*)
  158. {
  159. refreshAllElements();
  160. }
  161. void PaintRoutineEditor::mouseDown (const MouseEvent& e)
  162. {
  163. if (e.mods.isPopupMenu())
  164. {
  165. ApplicationCommandManager* commandManager = &ProjucerApplication::getCommandManager();
  166. PopupMenu m;
  167. m.addCommandItem (commandManager, JucerCommandIDs::editCompLayout);
  168. m.addCommandItem (commandManager, JucerCommandIDs::editCompGraphics);
  169. m.addSeparator();
  170. for (int i = 0; i < ObjectTypes::numElementTypes; ++i)
  171. m.addCommandItem (commandManager, JucerCommandIDs::newElementBase + i);
  172. m.show();
  173. }
  174. else
  175. {
  176. addChildComponent (lassoComp);
  177. lassoComp.beginLasso (e, this);
  178. }
  179. }
  180. void PaintRoutineEditor::mouseDrag (const MouseEvent& e)
  181. {
  182. lassoComp.toFront (false);
  183. lassoComp.dragLasso (e);
  184. }
  185. void PaintRoutineEditor::mouseUp (const MouseEvent& e)
  186. {
  187. lassoComp.endLasso();
  188. if (! (e.mouseWasDraggedSinceMouseDown() || e.mods.isAnyModifierKeyDown()))
  189. {
  190. graphics.getSelectedElements().deselectAll();
  191. graphics.getSelectedPoints().deselectAll();
  192. }
  193. }
  194. void PaintRoutineEditor::findLassoItemsInArea (Array <PaintElement*>& results, const Rectangle<int>& lasso)
  195. {
  196. for (int i = 0; i < getNumChildComponents(); ++i)
  197. if (PaintElement* const e = dynamic_cast<PaintElement*> (getChildComponent (i)))
  198. if (e->getBounds().expanded (-e->borderThickness).intersects (lasso))
  199. results.add (e);
  200. }
  201. SelectedItemSet <PaintElement*>& PaintRoutineEditor::getLassoSelection()
  202. {
  203. return graphics.getSelectedElements();
  204. }
  205. bool PaintRoutineEditor::isInterestedInFileDrag (const StringArray& files)
  206. {
  207. return File::createFileWithoutCheckingPath (files[0])
  208. .hasFileExtension ("jpg;jpeg;png;gif;svg");
  209. }
  210. void PaintRoutineEditor::filesDropped (const StringArray& filenames, int x, int y)
  211. {
  212. const File f (filenames [0]);
  213. if (f.existsAsFile())
  214. {
  215. ScopedPointer<Drawable> d (Drawable::createFromImageFile (f));
  216. if (d != nullptr)
  217. {
  218. d.reset();
  219. document.beginTransaction();
  220. graphics.dropImageAt (f,
  221. jlimit (10, getWidth() - 10, x),
  222. jlimit (10, getHeight() - 10, y));
  223. document.beginTransaction();
  224. }
  225. }
  226. }