1
2
3
4
5
6
7
8
9
10
11 package pl.edu.agh.cast.tool;
12
13 import java.beans.PropertyChangeEvent;
14 import java.beans.PropertyChangeListener;
15
16 import org.eclipse.draw2d.ColorConstants;
17 import org.eclipse.draw2d.Cursors;
18 import org.eclipse.draw2d.FigureListener;
19 import org.eclipse.draw2d.IFigure;
20 import org.eclipse.draw2d.RectangleFigure;
21 import org.eclipse.draw2d.Viewport;
22 import org.eclipse.draw2d.geometry.Dimension;
23 import org.eclipse.draw2d.geometry.Point;
24 import org.eclipse.draw2d.geometry.Rectangle;
25 import org.eclipse.gef.DragTracker;
26 import org.eclipse.gef.EditPartViewer;
27 import org.eclipse.gef.GraphicalEditPart;
28 import org.eclipse.gef.RequestConstants;
29 import org.eclipse.gef.editparts.ZoomListener;
30 import org.eclipse.gef.editparts.ZoomManager;
31 import org.eclipse.gef.tools.AbstractTool;
32 import org.eclipse.swt.events.ControlEvent;
33 import org.eclipse.swt.events.ControlListener;
34 import org.eclipse.swt.events.MouseEvent;
35
36
37
38
39
40
41
42 public class OverviewRectangleTool extends AbstractTool implements DragTracker, ControlListener, ZoomListener,
43 PropertyChangeListener, FigureListener {
44
45 public static final String ZOOM_MANAGER = "zoomManager";
46
47 private RectangleFigure focusFigure;
48
49 private int dragState;
50
51 private Rectangle startBounds;
52
53 private TargetShape target;
54
55 private FigureListener focusFigureListener;
56
57 private Rectangle referenceBounds;
58
59 private ZoomManager currentManager;
60
61 private static final int OUTSIDE = 0;
62
63 private static final int INSIDE = 1 << 1;
64
65 private static final int NORTH = INSIDE | 1 << 2;
66
67 private static final int EAST = INSIDE | 1 << 3;
68
69 private static final int SOUTH = INSIDE | 1 << 4;
70
71 private static final int WEST = INSIDE | 1 << 5;
72
73 private static final int NORTHWEST = INSIDE | NORTH | WEST;
74
75 private static final int NORTHEAST = INSIDE | NORTH | EAST;
76
77 private static final int SOUTHWEST = INSIDE | SOUTH | WEST;
78
79 private static final int SOUTHEAST = INSIDE | SOUTH | EAST;
80
81 private class FocusMoveListener implements FigureListener {
82
83
84
85
86
87
88 public void figureMoved(IFigure source) {
89
90 setTargetCenter(source.getBounds().getCenter());
91 }
92
93 }
94
95
96
97
98 public OverviewRectangleTool() {
99 setUnloadWhenFinished(false);
100 referenceBounds = new Rectangle();
101
102 }
103
104
105
106
107
108
109 protected boolean handleDragStarted() {
110 setState(STATE_DRAG);
111 setDragState(getRelativeCursorLocation(getStartLocation()));
112 Rectangle bounds = getFeedBackFigure().getBounds().getCopy();
113 getFeedBackFigure().translateToAbsolute(bounds);
114 setDragStartBounds(bounds);
115 return true;
116 }
117
118
119
120
121 private void setDragStartBounds(Rectangle bounds) {
122 this.startBounds = bounds.getCopy();
123
124 }
125
126 private Rectangle getDragStartBounds() {
127 return startBounds;
128 }
129
130 private void setDragState(int state) {
131 this.dragState = state;
132 }
133
134
135
136
137 private int getDragState() {
138 return dragState;
139 }
140
141
142
143
144
145
146 protected boolean handleDragInProgress() {
147 setState(STATE_DRAG_IN_PROGRESS);
148 Dimension delta = getDragMoveDelta();
149 Point start = getStartLocation();
150 RectangleFigure feedBack = getFeedBackFigure();
151 boolean moving = false;
152 int state = getDragState();
153 Rectangle oldBounds = getDragStartBounds();
154 Rectangle newBounds = oldBounds.getCopy();
155 if (isNorth(state)) {
156 newBounds.y = oldBounds.y + delta.height;
157 newBounds.height = oldBounds.height - delta.height;
158 } else if (isSouth(state)) {
159 newBounds.height = oldBounds.height + delta.height;
160 }
161 if (isWest(state)) {
162 newBounds.x = oldBounds.x + delta.width;
163 newBounds.width = oldBounds.width - delta.width;
164 } else if (isEast(state)) {
165 newBounds.width = oldBounds.width + delta.width;
166 }
167 if (!(isWest(state) || isEast(state) || isNorth(state) || isSouth(state))) {
168 if (isInside(state)) {
169 moving = true;
170 newBounds.x = oldBounds.x + delta.width;
171 newBounds.y = oldBounds.y + delta.height;
172 } else {
173
174 newBounds = new Rectangle(start, delta);
175 }
176 }
177
178 if (newBounds.width < 0) {
179 newBounds.x += newBounds.width;
180 newBounds.width = -newBounds.width;
181 }
182 if (newBounds.height < 0) {
183 newBounds.y += newBounds.height;
184 newBounds.height = -newBounds.height;
185 }
186 int minX = getCurrentViewer().getControl().getBounds().x;
187 int minY = getCurrentViewer().getControl().getBounds().y;
188 int maxWidth = getCurrentViewer().getControl().getBounds().width;
189 int maxHeight = getCurrentViewer().getControl().getBounds().height;
190 if (newBounds.x < minX || newBounds.y < minY || newBounds.x + newBounds.width > minX + maxWidth
191 || newBounds.y + newBounds.height > minY + maxHeight) {
192 if (moving) {
193 if (newBounds.x < minX) {
194 newBounds.x = minX;
195 }
196 if (newBounds.y < minY) {
197 newBounds.y = minY;
198 }
199 if (newBounds.x + newBounds.width > minX + maxWidth) {
200 newBounds.x = maxWidth - newBounds.width;
201 }
202 if (newBounds.y + newBounds.height > minY + maxHeight) {
203 newBounds.y = maxHeight - newBounds.height;
204 }
205 } else {
206 if (newBounds.x < minX) {
207 newBounds.width = newBounds.x + newBounds.width - minX;
208 newBounds.x = minX;
209 }
210 if (newBounds.y < minY) {
211 newBounds.height = newBounds.y + newBounds.height - minY;
212 newBounds.y = minY;
213 }
214 if (newBounds.x + newBounds.width > minX + maxWidth) {
215 newBounds.width = maxWidth - newBounds.x;
216 }
217 if (newBounds.y + newBounds.height > minY + maxHeight) {
218 newBounds.height = maxHeight - newBounds.y;
219 }
220 }
221 }
222 feedBack.translateToRelative(newBounds);
223 feedBack.setBounds(newBounds);
224 return true;
225 }
226
227
228
229
230
231
232 protected boolean handleMove() {
233 Point location = getLocation();
234 switch (getRelativeCursorLocation(location)) {
235 case NORTH:
236 case SOUTH:
237 setCursor(Cursors.SIZENS);
238 break;
239 case EAST:
240 case WEST:
241 setCursor(Cursors.SIZEWE);
242 break;
243 case NORTHWEST:
244 case SOUTHEAST:
245 setCursor(Cursors.SIZENWSE);
246 break;
247 case NORTHEAST:
248 case SOUTHWEST:
249 setCursor(Cursors.SIZENESW);
250 break;
251 case INSIDE:
252 setCursor(Cursors.SIZEALL);
253 break;
254 default:
255 setCursor(getDefaultCursor());
256
257 }
258 return true;
259 }
260
261
262
263
264
265
266 protected boolean handleButtonUp(int button) {
267 handleFinished();
268 return true;
269 }
270
271
272
273
274
275
276 protected void handleFinished() {
277 if (isInState(STATE_DRAG_IN_PROGRESS) || isInState(STATE_DRAG)) {
278
279 } else {
280 Point location = getLocation();
281 getFeedBackFigure().setBounds(new Rectangle(location.x, location.y, 0, 0));
282 }
283 setState(STATE_TERMINAL);
284 resetFlags();
285 zoomTo(getFeedBackFigure().getBounds().getCopy());
286
287
288 }
289
290
291
292
293 private void zoomTo(Rectangle rect) {
294 referenceBounds = rect.getCopy();
295 GraphicalEditPart part = (GraphicalEditPart)getCurrentViewer().getContents();
296 if (part != null) {
297 part.getFigure().translateFromParent(referenceBounds);
298 if (rect.isEmpty()) {
299
300 referenceBounds.setSize(0, 0);
301 }
302 if (this.currentManager == null) {
303
304 }
305
306 if (this.currentManager != null) {
307
308 this.currentManager.zoomTo(referenceBounds);
309 }
310 if (referenceBounds.isEmpty()) {
311
312 getFeedBackFigure().setBounds(rect);
313 }
314 }
315 }
316
317 boolean isNorth(int loc) {
318 loc = (isInside(loc)) ? loc ^ INSIDE : loc;
319 return (loc & NORTH) != 0;
320 }
321
322 boolean isEast(int loc) {
323 loc = (isInside(loc)) ? loc ^ INSIDE : loc;
324 return (loc & EAST) != 0;
325 }
326
327 boolean isSouth(int loc) {
328 loc = (isInside(loc)) ? loc ^ INSIDE : loc;
329 return (loc & SOUTH) != 0;
330 }
331
332 boolean isWest(int loc) {
333 loc = (isInside(loc)) ? loc ^ INSIDE : loc;
334 return (loc & WEST) != 0;
335 }
336
337 boolean isInside(int loc) {
338 return (loc & INSIDE) != 0;
339 }
340
341 private int getRelativeCursorLocation(Point location) {
342 RectangleFigure feedBack = getFeedBackFigure();
343 Rectangle bounds = feedBack.getBounds();
344 location = location.getCopy();
345 feedBack.translateToRelative(location);
346 int result = OUTSIDE;
347 if (feedBack.containsPoint(location)) {
348 result |= INSIDE;
349
350
351 if (Math.abs(location.y - bounds.y) <= 2) {
352 result |= NORTH;
353 } else if (Math.abs(location.y - (bounds.y + bounds.height - 1)) <= 2) {
354 result |= SOUTH;
355 }
356 if (Math.abs(location.x - bounds.x) <= 2) {
357 result |= WEST;
358 } else if (Math.abs(location.x - (bounds.x + bounds.width - 1)) <= 2) {
359 result |= EAST;
360 }
361 }
362 return result;
363 }
364
365 private RectangleFigure getFeedBackFigure() {
366 if (focusFigure == null) {
367 focusFigure = new RectangleFigure();
368 focusFigure.setForegroundColor(ColorConstants.red);
369 focusFigure.setFill(false);
370 focusFigure.setLineWidth(2);
371 focusFigureListener = new FocusMoveListener();
372 focusFigure.addFigureListener(focusFigureListener);
373 focusFigure.setBounds(new Rectangle());
374 addFeedback(focusFigure);
375
376
377 }
378 return focusFigure;
379 }
380
381 private TargetShape getTargetFigure() {
382 if (target == null) {
383 target = new TargetShape();
384 target.setForegroundColor(ColorConstants.red);
385 target.setFill(false);
386 target.setBounds(new Rectangle(-10, -10, 20, 20));
387 target.setLineWidth(2);
388 addFeedback(target);
389 }
390 return target;
391 }
392
393 private void setTargetCenter(Point center) {
394 Point newCenter = center.getCopy();
395 newCenter.translate(-getTargetFigure().getSize().width / 2, -getTargetFigure().getSize().height / 2);
396 getTargetFigure().setLocation(newCenter);
397 }
398
399
400
401
402
403
404 public void deactivate() {
405 if (focusFigure != null) {
406 focusFigure.removeFigureListener(focusFigureListener);
407 removeFeedback(focusFigure);
408 focusFigure = null;
409 }
410 if (target != null) {
411 removeFeedback(target);
412 target = null;
413 }
414 if (getCurrentViewer() != null) {
415 getCurrentViewer().getControl().removeControlListener(this);
416 if (getCurrentViewer().getContents() instanceof GraphicalEditPart) {
417 ((GraphicalEditPart)getCurrentViewer().getContents()).getFigure().removeFigureListener(this);
418 }
419 }
420 if (this.currentManager != null) {
421 this.currentManager.removeZoomListener(this);
422 this.currentManager.getViewport().getHorizontalRangeModel().removePropertyChangeListener(this);
423 this.currentManager.getViewport().getVerticalRangeModel().removePropertyChangeListener(this);
424 }
425 super.deactivate();
426 }
427
428
429
430
431
432
433 public void activate() {
434
435 super.activate();
436 }
437
438
439
440
441
442
443 protected String getCommandName() {
444 return RequestConstants.REQ_SELECTION;
445 }
446
447
448
449
450
451
452 public void setViewer(EditPartViewer viewer) {
453 if (getCurrentViewer() != null) {
454 getCurrentViewer().getControl().removeControlListener(this);
455 GraphicalEditPart part = (GraphicalEditPart)getCurrentViewer().getContents();
456 if (part != null) {
457 IFigure referenceFigure = part.getContentPane();
458 referenceFigure.removeFigureListener(this);
459 }
460 }
461 super.setViewer(viewer);
462
463 if (getCurrentViewer() != null) {
464 getCurrentViewer().getControl().addControlListener(this);
465 GraphicalEditPart part = (GraphicalEditPart)getCurrentViewer().getContents();
466 if (part != null) {
467 IFigure referenceFigure = part.getContentPane();
468 referenceFigure.addFigureListener(this);
469 }
470 }
471 }
472
473
474
475
476
477
478 public void controlMoved(ControlEvent e) {
479 }
480
481
482
483
484
485
486 public void controlResized(ControlEvent e) {
487 }
488
489
490
491
492
493
494
495 public void viewerExited(MouseEvent me, EditPartViewer viewer) {
496
497
498
499
500
501 super.viewerExited(me, viewer);
502 }
503
504
505
506
507 public void setZoomManager(ZoomManager zoomManager) {
508 if (this.currentManager != null) {
509 this.currentManager.removeZoomListener(this);
510 this.currentManager.getViewport().getHorizontalRangeModel().removePropertyChangeListener(this);
511 this.currentManager.getViewport().getVerticalRangeModel().removePropertyChangeListener(this);
512 }
513 this.currentManager = zoomManager;
514 if (this.currentManager != null) {
515 this.currentManager.addZoomListener(this);
516 this.currentManager.getViewport().getHorizontalRangeModel().addPropertyChangeListener(this);
517 this.currentManager.getViewport().getVerticalRangeModel().addPropertyChangeListener(this);
518
519 IFigure referenceFigure = getReferenceFigure();
520 if (referenceFigure != null)
521 getCurrentViewer().flush();
522 }
523 updateViewPort();
524 }
525
526 private IFigure getReferenceFigure() {
527 GraphicalEditPart part = getReferenceEditPart();
528 if (part != null)
529 return part.getFigure();
530 return null;
531 }
532
533
534
535
536 private GraphicalEditPart getReferenceEditPart() {
537 if (getCurrentViewer() == null)
538 return null;
539 if (getCurrentViewer().getContents() instanceof GraphicalEditPart) {
540 return (GraphicalEditPart)getCurrentViewer().getContents();
541 }
542 return null;
543 }
544
545
546
547
548
549
550 public void zoomChanged(double zoom) {
551
552
553
554
555
556
557
558
559
560
561
562
563
564 }
565
566
567
568
569
570
571 public void propertyChange(PropertyChangeEvent evt) {
572 updateViewPort();
573 }
574
575
576
577
578 private void updateViewPort() {
579 if (this.currentManager == null)
580 return;
581 if (getCurrentViewer() == null)
582 return;
583 Viewport viewport = this.currentManager.getViewport();
584 double zoom = this.currentManager.getZoom();
585
586 int x = viewport.getHorizontalRangeModel().getValue();
587 int width = viewport.getHorizontalRangeModel().getExtent();
588 int y = viewport.getVerticalRangeModel().getValue();
589 int height = viewport.getVerticalRangeModel().getExtent();
590 if (Math.abs(1 - zoom) < .1) {
591
592 x += width / 2;
593 y += height / 2;
594 width = 0;
595 height = 0;
596 }
597 Rectangle newBounds = new Rectangle(x, y, width, height);
598 GraphicalEditPart part = (GraphicalEditPart)getCurrentViewer().getContents();
599 if (part != null) {
600 IFigure referenceFigure = part.getContentPane();
601 newBounds.scale(1 / this.currentManager.getZoom());
602 referenceFigure.translateToParent(newBounds);
603
604
605 newBounds.shrink(1, 1);
606 getFeedBackFigure().setBounds(newBounds);
607 }
608
609 }
610
611
612
613
614
615
616 public void figureMoved(IFigure source) {
617 updateViewPort();
618
619 }
620
621 }