1 // Copyright (C) 2012-2019 The VPaint Developers.
2 // See the COPYRIGHT file at the top-level directory of this distribution
3 // and at https://github.com/dalboris/vpaint/blob/master/COPYRIGHT
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 #include "Layer.h"
18
19 #include "Background/Background.h"
20 #include "VectorAnimationComplex/VAC.h"
21 #include "XmlStreamReader.h"
22 #include "XmlStreamWriter.h"
23
Layer(NoInit_)24 Layer::Layer(NoInit_)
25 {
26
27 }
28
init_(Background * background,VectorAnimationComplex::VAC * vac,const QString & layerName,bool isVisible)29 void Layer::init_(
30 Background * background,
31 VectorAnimationComplex::VAC * vac,
32 const QString & layerName,
33 bool isVisible)
34 {
35 background_ = background;
36 vac_ = vac;
37 name_ = layerName;
38 isVisible_ = isVisible;
39
40 connect(background_, SIGNAL(changed()), this, SIGNAL(changed()));
41 connect(background_, SIGNAL(checkpoint()), this, SIGNAL(checkpoint()));
42
43 connect(vac_, SIGNAL(changed()), this, SIGNAL(changed()));
44 connect(vac_, SIGNAL(checkpoint()), this, SIGNAL(checkpoint()));
45 connect(vac_, SIGNAL(needUpdatePicking()), this, SIGNAL(needUpdatePicking()));
46 connect(vac_, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
47 }
48
Layer(const QString & layerName)49 Layer::Layer(const QString & layerName)
50 {
51 init_(new Background(this),
52 new VectorAnimationComplex::VAC(),
53 layerName,
54 true);
55 }
56
~Layer()57 Layer::~Layer()
58 {
59 delete vac_;
60 }
61
clone()62 Layer * Layer::clone()
63 {
64 // Two previous attempts at implementing this resulted
65 // in bugs. The first is because I called
66 // new Background(background())
67 // instead of
68 // new Background(*background())
69 // And the second because new Background(this) was called
70 // in a constructor before "this" was properly initialized,
71 // that is, parent-child relationship were messed up.
72 // The conclusion is that using copy-constructor is much
73 // trickier than the "clone" idiom, which should be preferred
74 // based on this experience: it is much less bug-prone when dealing
75 // with pointer-like objects with identity.
76 //
77
78 Layer * res = new Layer(NoInit_());
79 res->init_(new Background(*background(), res),
80 vac_->clone(),
81 name_,
82 isVisible_);
83 return res;
84 }
85
stringType()86 QString Layer::stringType()
87 {
88 return "Layer";
89 }
90
draw(Time time,ViewSettings & viewSettings)91 void Layer::draw(Time time, ViewSettings & viewSettings)
92 {
93 // Draw the VAC only. Drawing the background is handled by View.
94 if (isVisible()) {
95 vac()->draw(time, viewSettings);
96 }
97 }
98
drawPick(Time time,ViewSettings & viewSettings)99 void Layer::drawPick(Time time, ViewSettings & viewSettings)
100 {
101 if (isVisible()) {
102 vac()->drawPick(time, viewSettings);
103 }
104 }
105
setHoveredObject(Time time,int id)106 void Layer::setHoveredObject(Time time, int id)
107 {
108 vac()->setHoveredObject(time, id);
109 }
110
setNoHoveredObject()111 void Layer::setNoHoveredObject()
112 {
113 vac()->setNoHoveredObject();
114 }
115
select(Time time,int id)116 void Layer::select(Time time, int id)
117 {
118 vac()->select(time, id);
119 }
120
deselect(Time time,int id)121 void Layer::deselect(Time time, int id)
122 {
123 vac()->deselect(time, id);
124 }
125
toggle(Time time,int id)126 void Layer::toggle(Time time, int id)
127 {
128 vac()->toggle(time, id);
129 }
130
deselectAll(Time time)131 void Layer::deselectAll(Time time)
132 {
133 vac()->deselectAll(time);
134 }
135
deselectAll()136 void Layer::deselectAll()
137 {
138 vac()->deselectAll();
139 }
140
invertSelection()141 void Layer::invertSelection()
142 {
143 vac()->invertSelection();
144 }
145
read(XmlStreamReader & xml)146 void Layer::read(XmlStreamReader & xml)
147 {
148 // Name
149 name_ = "Layer";
150 if(xml.attributes().hasAttribute("name"))
151 {
152 name_ = xml.attributes().value("name").toString();
153 }
154
155 // Visible
156 isVisible_ = true;
157 if(xml.attributes().hasAttribute("visible"))
158 {
159 QString value = xml.attributes().value("visible").toString();
160 if (value == "true")
161 {
162 isVisible_ = true;
163 }
164 else if (value == "false")
165 {
166 isVisible_ = false;
167 }
168 }
169
170 while (xml.readNextStartElement())
171 {
172 if (xml.name() == "background")
173 {
174 background()->read(xml);
175 }
176 else if (xml.name() == "objects")
177 {
178 vac()->read(xml);
179 }
180 else
181 {
182 xml.skipCurrentElement();
183 }
184 }
185
186 emit needUpdatePicking();
187 emit changed();
188 emit selectionChanged();
189 emit layerAttributesChanged();
190 }
191
write(XmlStreamWriter & xml)192 void Layer::write(XmlStreamWriter & xml)
193 {
194 // Name
195 xml.writeAttribute("name", name());
196
197 // Visible
198 xml.writeAttribute("visible", isVisible() ? "true" : "false");
199
200 // Background
201 xml.writeStartElement("background");
202 background()->write(xml);
203 xml.writeEndElement();
204
205 // Vector animation complex
206 xml.writeStartElement("objects");
207 vac()->write(xml);
208 xml.writeEndElement();
209 }
210
name() const211 QString Layer::name() const
212 {
213 return name_;
214 }
215
setName(const QString & newName)216 void Layer::setName(const QString & newName)
217 {
218 if (newName != name_)
219 {
220 name_ = newName;
221 emit layerAttributesChanged();
222 }
223 }
224
isVisible() const225 bool Layer::isVisible() const
226 {
227 return isVisible_;
228 }
229
setVisible(bool b)230 void Layer::setVisible(bool b)
231 {
232 if (b != isVisible_)
233 {
234 isVisible_ = b;
235 emit changed();
236 emit needUpdatePicking();
237 emit layerAttributesChanged();
238 }
239 }
240
exportSVG_(Time t,QTextStream & out)241 void Layer::exportSVG_(Time t, QTextStream & out)
242 {
243 // This function does not export the background, because the API
244 // for Background::exportSVG() requires the canvas' size, which
245 // we don't know here.
246 //
247 // Therefore, it is the responsibility of clients to manually call
248 // background()->exportSVG beforehand if they wish.
249 //
250 // XXX We should improve this ugly design
251 //
252 vac()->exportSVG(t, out);
253 }
254