1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.vectomatic.svg.edit.client.command.path;
19
20 import org.vectomatic.dom.svg.OMSVGCircleElement;
21 import org.vectomatic.dom.svg.OMSVGDocument;
22 import org.vectomatic.dom.svg.OMSVGLineElement;
23 import org.vectomatic.dom.svg.OMSVGMatrix;
24 import org.vectomatic.dom.svg.OMSVGPathSeg;
25 import org.vectomatic.dom.svg.OMSVGPathSegCurvetoCubicAbs;
26 import org.vectomatic.dom.svg.OMSVGPoint;
27 import org.vectomatic.svg.edit.client.command.path.IPathRepOwner.Mode;
28
29 import com.google.gwt.dom.client.Element;
30
31
32
33
34
35 public class SVGCubicSegRep extends SVGSegRep {
36 protected OMSVGPathSegCurvetoCubicAbs cubicToSeg;
37 protected OMSVGCircleElement cp1;
38 protected OMSVGCircleElement cp2;
39 protected OMSVGLineElement tg1;
40 protected OMSVGLineElement tg2;
41
42 public SVGCubicSegRep(IPathRepOwner owner, OMSVGPathSegCurvetoCubicAbs cubicToSeg) {
43 super(owner);
44 this.cubicToSeg = cubicToSeg;
45
46
47 OMSVGDocument document = (OMSVGDocument) owner.getSvg().getOwnerDocument();
48 cp1 = document.createSVGCircleElement();
49 cp2 = document.createSVGCircleElement();
50 tg1 = document.createSVGLineElement();
51 tg2 = document.createSVGLineElement();
52 tangents.appendChild(tg1);
53 tangents.appendChild(tg2);
54 tangents.appendChild(cp1);
55 tangents.appendChild(cp2);
56 }
57
58 @Override
59 public OMSVGPathSeg getElement() {
60 return cubicToSeg;
61 }
62
63 @Override
64 public float getX() {
65 return cubicToSeg.getX();
66 }
67 @Override
68 public void setX(float x) {
69 cubicToSeg.setX(x);
70 }
71 @Override
72 public float getY() {
73 return cubicToSeg.getY();
74 }
75 @Override
76 public void setY(float y) {
77 cubicToSeg.setY(y);
78 }
79 @Override
80 public float getX1() {
81 return cubicToSeg.getX1();
82 }
83 @Override
84 public float getY1() {
85 return cubicToSeg.getY1();
86 }
87 @Override
88 public float getX2() {
89 return cubicToSeg.getX2();
90 }
91 @Override
92 public float getY2() {
93 return cubicToSeg.getY2();
94 }
95 @Override
96 public Element getCp1() {
97 return cp1.getElement();
98 }
99 @Override
100 public void setCp1(OMSVGPoint p, float hs) {
101 cubicToSeg.setX1(p.getX());
102 cubicToSeg.setY1(p.getY());
103 update(hs);
104 }
105 @Override
106 public Element getCp2() {
107 return cp2.getElement();
108 }
109 @Override
110 public void setCp2(OMSVGPoint p, float hs) {
111 cubicToSeg.setX2(p.getX());
112 cubicToSeg.setY2(p.getY());
113 update(hs);
114 }
115
116 @Override
117 public void update(float hs) {
118 float x = cubicToSeg.getX();
119 float y = cubicToSeg.getY();
120 vertex.getX().getBaseVal().setValue(x - hs);
121 vertex.getY().getBaseVal().setValue(y - hs);
122 vertex.getWidth().getBaseVal().setValue(hs * 2);
123 vertex.getHeight().getBaseVal().setValue(hs * 2);
124 if (owner.getMode() == Mode.TANGENT) {
125 float px = previous != null ? previous.getX() : 0;
126 float py = previous != null ? previous.getY() : 0;
127 float x1 = cubicToSeg.getX1();
128 float y1 = cubicToSeg.getY1();
129 float x2 = cubicToSeg.getX2();
130 float y2 = cubicToSeg.getY2();
131 tg1.getX1().getBaseVal().setValue(px);
132 tg1.getY1().getBaseVal().setValue(py);
133 tg1.getX2().getBaseVal().setValue(x1);
134 tg1.getY2().getBaseVal().setValue(y1);
135
136 tg2.getX1().getBaseVal().setValue(x);
137 tg2.getY1().getBaseVal().setValue(y);
138 tg2.getX2().getBaseVal().setValue(x2);
139 tg2.getY2().getBaseVal().setValue(y2);
140
141 cp1.getCx().getBaseVal().setValue(x1);
142 cp1.getCy().getBaseVal().setValue(y1);
143 cp1.getR().getBaseVal().setValue(hs);
144
145 cp2.getCx().getBaseVal().setValue(x2);
146 cp2.getCy().getBaseVal().setValue(y2);
147 cp2.getR().getBaseVal().setValue(hs);
148 }
149 }
150
151 @Override
152 public void updateStart(OMSVGPoint delta, float hs) {
153 cubicToSeg.setX1(cubicToSeg.getX1() + delta.getX());
154 cubicToSeg.setY1(cubicToSeg.getY1() + delta.getY());
155 update(hs);
156 }
157
158 @Override
159 public void updateEnd(OMSVGPoint delta, float hs) {
160 cubicToSeg.setX2(cubicToSeg.getX2() + delta.getX());
161 cubicToSeg.setY2(cubicToSeg.getY2() + delta.getY());
162 cubicToSeg.setX(cubicToSeg.getX() + delta.getX());
163 cubicToSeg.setY(cubicToSeg.getY() + delta.getY());
164 update(hs);
165 }
166
167 @Override
168 public void processMouseMove(OMSVGPoint delta, Element target, float hs, boolean isCtrlKeyDown) {
169 if (target == null || tg2.getElement() == target) {
170 updateEnd(delta, hs);
171 if (next != null) {
172 next.updateStart(delta, hs);
173 }
174 } else if (tg1.getElement() == target) {
175 updateStart(delta, hs);
176 if (previous != null) {
177 previous.updateEnd(delta, hs);
178 }
179 } else if (cp1.getElement() == target) {
180 SVGSegRep prevSeg = getPreviousSplineSeg();
181 Float angle = null;
182 if (isCtrlKeyDown && prevSeg != null) {
183
184 OMSVGPoint v1 = owner.getSvg().createSVGPoint(
185 cubicToSeg.getX1() - prevSeg.getX(),
186 cubicToSeg.getY1() - prevSeg.getY());
187 OMSVGPoint v2 = owner.getSvg().createSVGPoint(
188 cubicToSeg.getX1() + delta.getX() - prevSeg.getX(),
189 cubicToSeg.getY1() + delta.getY() - prevSeg.getY());
190 float d = v1.length() * v2.length();
191 if (d != 0) {
192 angle = (float)(Math.acos(v1.dotProduct(v2) / d) * 180 / Math.PI);
193 if (v1.crossProduct(v2) < 0) {
194 angle = 360 - angle;
195 }
196 }
197 }
198 cubicToSeg.setX1(cubicToSeg.getX1() + delta.getX());
199 cubicToSeg.setY1(cubicToSeg.getY1() + delta.getY());
200 update(hs);
201 if (angle != null) {
202
203 OMSVGMatrix m = owner.getSvg().createSVGMatrix();
204 m = m.translate(prevSeg.getX(), prevSeg.getY());
205 m = m.rotate(angle);
206 m = m.translate(-prevSeg.getX(), -prevSeg.getY());
207 OMSVGPoint p0 = owner.getSvg().createSVGPoint(
208 prevSeg.getX2(),
209 prevSeg.getY2());
210 OMSVGPoint p1 = p0.matrixTransform(m).substract(p0);
211 prevSeg.processMouseMove(p1, prevSeg.getCp2(), hs, false);
212 }
213 } else if (cp2.getElement() == target) {
214 SVGSegRep nextSeg = getNextSplineSeg();
215 Float angle = null;
216 if (isCtrlKeyDown && next != null) {
217
218 OMSVGPoint v1 = owner.getSvg().createSVGPoint(
219 cubicToSeg.getX2() - cubicToSeg.getX(),
220 cubicToSeg.getY2() - cubicToSeg.getY());
221 OMSVGPoint v2 = owner.getSvg().createSVGPoint(
222 cubicToSeg.getX2() + delta.getX() - cubicToSeg.getX(),
223 cubicToSeg.getY2() + delta.getY() - cubicToSeg.getY());
224 float d = v1.length() * v2.length();
225 if (d != 0) {
226 angle = (float)(Math.acos(v1.dotProduct(v2) / d) * 180 / Math.PI);
227 if (v1.crossProduct(v2) < 0) {
228 angle = 360 - angle;
229 }
230 }
231 }
232 cubicToSeg.setX2(cubicToSeg.getX2() + delta.getX());
233 cubicToSeg.setY2(cubicToSeg.getY2() + delta.getY());
234 update(hs);
235 if (angle != null) {
236
237 OMSVGMatrix m = owner.getSvg().createSVGMatrix();
238 m = m.translate(cubicToSeg.getX(), cubicToSeg.getY());
239 m = m.rotate(angle);
240 m = m.translate(-cubicToSeg.getX(), -cubicToSeg.getY());
241 OMSVGPoint p0 = owner.getSvg().createSVGPoint(
242 nextSeg.getX1(),
243 nextSeg.getY1());
244 OMSVGPoint p1 = p0.matrixTransform(m).substract(p0);
245 nextSeg.processMouseMove(p1, nextSeg.getCp1(), hs, false);
246 }
247 }
248 }
249
250 @Override
251 public String toString() {
252 StringBuilder builder = new StringBuilder("C ");
253 builder.append(cubicToSeg.getX1());
254 builder.append(",");
255 builder.append(cubicToSeg.getY1());
256 builder.append(" ");
257 builder.append(cubicToSeg.getX2());
258 builder.append(",");
259 builder.append(cubicToSeg.getY2());
260 builder.append(" ");
261 builder.append(cubicToSeg.getX());
262 builder.append(",");
263 builder.append(cubicToSeg.getY());
264 return builder.toString();
265 }
266 }