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.

282 lines
8.0KB

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