1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.vectomatic.client.rep.controller;
19
20 import java.util.ArrayList;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.Set;
24
25 import org.vectomatic.client.rep.RepApplication;
26 import org.vectomatic.client.rep.command.DeleteVertexCommand;
27 import org.vectomatic.client.rep.command.ICommand;
28 import org.vectomatic.client.rep.command.MoveVertexCommand;
29 import org.vectomatic.client.rep.view.Cursor;
30 import org.vectomatic.client.rep.view.DrawingView;
31 import org.vectomatic.common.events.IDrawingModelListener;
32 import org.vectomatic.common.model.Attribute;
33 import org.vectomatic.common.model.CloneShapeVisitor;
34 import org.vectomatic.common.model.DrawingModel;
35 import org.vectomatic.common.model.FloatAttributeValue;
36 import org.vectomatic.common.model.Shape;
37 import org.vectomatic.common.model.geometry.Point;
38 import org.vectomatic.common.model.geometry.Polyline;
39 import org.vectomatic.common.model.geometry.TransformMatrix;
40 import org.vectomatic.common.model.style.Color;
41
42 import com.google.gwt.user.client.ui.KeyboardListener;
43
44
45
46
47
48 public class EditPolylineController extends ControllerBase implements IDrawingModelListener {
49 private static final int VERTEX_SIZE = 3;
50 private CloneShapeVisitor _cloner;
51 private MouseControllerButton _button;
52 private Set<Integer> _vertexIndices;
53 private Polyline _polyline;
54 private Polyline _clone;
55 private Point _p0;
56 private TransformMatrix _mInv;
57 private int _pickedVertex;
58
59 public EditPolylineController(RepApplication app) {
60 super(app);
61 _cloner = new CloneShapeVisitor();
62 _vertexIndices = new HashSet<Integer>();
63 _p0 = new Point();
64 _mInv = new TransformMatrix();
65 _button = new MouseControllerButton(_app.getIcons().editPolylineIcon().createImage(), _app.getConstants().editPolylineCommand(), this);
66 _app.getModel().addDrawingModelListener(this);
67 }
68
69 public MouseControllerButton getButton() {
70 return _button;
71 }
72
73 @Override
74 public void activate(DrawingView view) {
75 view.setCursor(Cursor.CURSOR_POINTER);
76 _app.getSelection().select(new ArrayList<Shape>());
77 selectPolyline(null, null);
78 _pickedVertex = -1;
79 }
80
81 @Override
82 public void deactivate(DrawingView view) {
83 if (_pickedVertex != -1) {
84 Point[] vertices = _polyline.getVertices();
85 Point[] cloneVertices = _clone.getVertices();
86 if (!vertices[_pickedVertex].equals(cloneVertices[_pickedVertex])) {
87 ICommand command = new MoveVertexCommand(_app, this, _polyline, _clone, _vertexIndices);
88 command.execute();
89 _app.getHistory().addCommand(command);
90 }
91 _pickedVertex = -1;
92 }
93 }
94
95 @Override
96 public void render(DrawingView view) {
97 if (_clone != null) {
98 view.getRenderer().visitPolyline(_clone);
99 Color.BLACK.acceptVisitor(view.getStrokeStyleVisitor());
100 Point[] cloneVertices = _clone.getVertices();
101 int length = cloneVertices.length - (_polyline.isClosed() ? 1 : 0);
102 for (int i = 0; i < length; i++) {
103 cloneVertices[i].transform(_clone.getTransform(), _p0);
104 if (_vertexIndices.contains(new Integer(i))) {
105 Color.GREEN.acceptVisitor(view.getFillStyleVisitor());
106 } else {
107 Color.WHITE.acceptVisitor(view.getFillStyleVisitor());
108 }
109 view.fillRect(_p0.x - VERTEX_SIZE, _p0.y - VERTEX_SIZE, VERTEX_SIZE * 2, VERTEX_SIZE * 2);
110 view.strokeRect(_p0.x - VERTEX_SIZE, _p0.y - VERTEX_SIZE, VERTEX_SIZE * 2, VERTEX_SIZE * 2);
111 }
112 }
113 }
114
115 @Override
116 public void keyDown(DrawingView view, char keyCode, int modifiers) {
117 if (keyCode == KeyboardListener.KEY_DELETE || keyCode == KeyboardListener.KEY_BACKSPACE && _app.getSelection().getSelectedShapes().size() > 0) {
118 if (_polyline != null) {
119 int size = _vertexIndices.size();
120 if (size > 0) {
121 int vertexCount = _polyline.getVertices().length - size;
122 int minVertex = _polyline.isClosed() ? 4 : 2;
123 if (vertexCount >= minVertex) {
124 ICommand command = new DeleteVertexCommand(_app, this, _polyline, _vertexIndices);
125 command.execute();
126 _app.getHistory().addCommand(command);
127 }
128 }
129 }
130 }
131 }
132
133 public void selectPolyline(Polyline polyline, Set<Integer> vertexIndices) {
134 if (polyline == null) {
135 _polyline = null;
136 _clone = null;
137 _vertexIndices.clear();
138 } else {
139 _polyline = polyline;
140 _cloner.visitPolyline(_polyline);
141 _clone = (Polyline)_cloner.getClone();
142 _clone.setAttribute(Attribute.FILL_OPACITY, new FloatAttributeValue(0.2f));
143 _polyline.getTransform().invert(_mInv);
144 _vertexIndices.clear();
145 _vertexIndices.addAll(vertexIndices);
146 }
147 }
148
149 @Override
150 public void mouseDown(DrawingView view, Point p, int modifiers) {
151 view.toModelCoordinates(p);
152 if (_polyline == null) {
153 Shape shape = view.getPicker().pick(p, _app.getModel().reverseIterator());
154 if (shape instanceof Polyline) {
155 selectPolyline((Polyline)shape, new HashSet<Integer>());
156 }
157 } else {
158 _pickedVertex = pickVertex(p);
159 if (_pickedVertex == -1) {
160 Shape shape = view.getPicker().pick(p, _app.getModel().reverseIterator());
161 if (shape instanceof Polyline) {
162 selectPolyline((Polyline)shape, new HashSet<Integer>());
163 } else {
164 selectPolyline(null, new HashSet<Integer>());
165 }
166 } else {
167 Integer vertex = new Integer(_pickedVertex);
168 boolean ctrlPressed = (modifiers & KeyboardListener.MODIFIER_CTRL) != 0;
169 if (ctrlPressed) {
170 if (_vertexIndices.contains(vertex)) {
171 _vertexIndices.remove(vertex);
172 } else {
173 _vertexIndices.add(vertex);
174 }
175 } else {
176 _vertexIndices.add(vertex);
177 }
178 }
179 }
180 }
181
182 @Override
183 public void mouseMove(DrawingView view, Point p, int modifiers) {
184 view.toModelCoordinates(p);
185 if (_pickedVertex != -1) {
186 if (_vertexIndices.size() > 0) {
187 p.transform(_mInv, _p0);
188 Point[] vertices = _polyline.getVertices();
189 _p0.subtract(vertices[_pickedVertex]);
190 Point[] cloneVertices = _clone.getVertices();
191 boolean closed = _polyline.isClosed();
192 Iterator<Integer> iterator = _vertexIndices.iterator();
193 while (iterator.hasNext()) {
194 int index = iterator.next().intValue();
195 vertices[index].add(_p0, cloneVertices[index]);
196 if (index == 0 && closed) {
197 vertices[vertices.length - 1].add(_p0, cloneVertices[vertices.length - 1]);
198 }
199 }
200 }
201 } else if (_polyline != null) {
202 float tol = VERTEX_SIZE;
203 p.transform(_mInv, _p0);
204 Point[] vertices = _polyline.getVertices();
205 for (int i = 0; i < vertices.length; i++) {
206 if ((vertices[i].x - tol < _p0.x) && (_p0.x < vertices[i].x + tol)
207 && (vertices[i].y - tol < _p0.y) && (_p0.y < vertices[i].y + tol)) {
208 view.setCursor(Cursor.CURSOR_MOVE);
209 return;
210 }
211 }
212 view.setCursor(Cursor.CURSOR_POINTER);
213 }
214 }
215
216 @Override
217 public void mouseUp(DrawingView view, Point p, int modifiers) {
218 deactivate(view);
219 }
220
221 private int pickVertex(Point p) {
222 int pickedVertex = -1;
223 p.transform(_mInv, _p0);
224 Point[] vertices = _polyline.getVertices();
225 float tol = VERTEX_SIZE;
226 for (int i = 0; i < vertices.length; i++) {
227 if ((vertices[i].x - tol < _p0.x) && (_p0.x < vertices[i].x + tol)
228 && (vertices[i].y - tol < _p0.y) && (_p0.y < vertices[i].y + tol)) {
229 pickedVertex = i;
230 break;
231 }
232 }
233 return pickedVertex;
234 }
235
236 public void modelHasChanged(DrawingModel model) {
237 if (_polyline != null && (!model.contains(_polyline))) {
238 selectPolyline(null, null);
239 }
240 }
241 }