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