|
Lines 1-22
Link Here
|
| 1 |
/******************************************************************************* |
1 |
/******************************************************************************* |
| 2 |
* Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada. |
2 |
* Copyright 2005-2009, CHISEL Group, University of Victoria, Victoria, BC, |
| 3 |
* All rights reserved. This program and the accompanying materials are made |
3 |
* Canada. All rights reserved. This program and the accompanying materials are |
| 4 |
* available under the terms of the Eclipse Public License v1.0 which |
4 |
* made available under the terms of the Eclipse Public License v1.0 which |
| 5 |
* accompanies this distribution, and is available at |
5 |
* accompanies this distribution, and is available at |
| 6 |
* http://www.eclipse.org/legal/epl-v10.html |
6 |
* http://www.eclipse.org/legal/epl-v10.html |
| 7 |
* |
7 |
* |
| 8 |
* Contributors: The Chisel Group, University of Victoria |
8 |
* Contributors: The Chisel Group, University of Victoria |
|
|
9 |
* Mateusz Matela <mateusz.matela@gmail.com> - [tree] Add Space Tree support to Graph widget - https://bugs.eclipse.org/bugs/show_bug.cgi?id=277534 |
| 9 |
******************************************************************************/ |
10 |
******************************************************************************/ |
| 10 |
package org.eclipse.zest.core.widgets; |
11 |
package org.eclipse.zest.core.widgets; |
| 11 |
|
12 |
|
| 12 |
import java.util.ArrayList; |
13 |
import java.util.ArrayList; |
| 13 |
import java.util.HashMap; |
14 |
import java.util.HashMap; |
|
|
15 |
import java.util.HashSet; |
| 14 |
import java.util.Iterator; |
16 |
import java.util.Iterator; |
| 15 |
import java.util.LinkedList; |
|
|
| 16 |
import java.util.List; |
17 |
import java.util.List; |
| 17 |
|
18 |
|
| 18 |
import org.eclipse.draw2d.Animation; |
19 |
import org.eclipse.draw2d.Animation; |
| 19 |
import org.eclipse.draw2d.ColorConstants; |
20 |
import org.eclipse.draw2d.ColorConstants; |
|
|
21 |
import org.eclipse.draw2d.CoordinateListener; |
| 20 |
import org.eclipse.draw2d.FigureCanvas; |
22 |
import org.eclipse.draw2d.FigureCanvas; |
| 21 |
import org.eclipse.draw2d.FreeformLayer; |
23 |
import org.eclipse.draw2d.FreeformLayer; |
| 22 |
import org.eclipse.draw2d.FreeformLayout; |
24 |
import org.eclipse.draw2d.FreeformLayout; |
|
Lines 34-39
Link Here
|
| 34 |
import org.eclipse.draw2d.geometry.Point; |
36 |
import org.eclipse.draw2d.geometry.Point; |
| 35 |
import org.eclipse.draw2d.geometry.Rectangle; |
37 |
import org.eclipse.draw2d.geometry.Rectangle; |
| 36 |
import org.eclipse.swt.SWT; |
38 |
import org.eclipse.swt.SWT; |
|
|
39 |
import org.eclipse.swt.events.ControlEvent; |
| 40 |
import org.eclipse.swt.events.ControlListener; |
| 37 |
import org.eclipse.swt.events.PaintEvent; |
41 |
import org.eclipse.swt.events.PaintEvent; |
| 38 |
import org.eclipse.swt.events.PaintListener; |
42 |
import org.eclipse.swt.events.PaintListener; |
| 39 |
import org.eclipse.swt.events.SelectionAdapter; |
43 |
import org.eclipse.swt.events.SelectionAdapter; |
|
Lines 41-67
Link Here
|
| 41 |
import org.eclipse.swt.events.SelectionListener; |
45 |
import org.eclipse.swt.events.SelectionListener; |
| 42 |
import org.eclipse.swt.graphics.Color; |
46 |
import org.eclipse.swt.graphics.Color; |
| 43 |
import org.eclipse.swt.widgets.Composite; |
47 |
import org.eclipse.swt.widgets.Composite; |
| 44 |
import org.eclipse.swt.widgets.Control; |
|
|
| 45 |
import org.eclipse.swt.widgets.Display; |
48 |
import org.eclipse.swt.widgets.Display; |
| 46 |
import org.eclipse.swt.widgets.Event; |
49 |
import org.eclipse.swt.widgets.Event; |
| 47 |
import org.eclipse.swt.widgets.Item; |
50 |
import org.eclipse.swt.widgets.Item; |
|
|
51 |
import org.eclipse.swt.widgets.Widget; |
| 48 |
import org.eclipse.zest.core.widgets.internal.ContainerFigure; |
52 |
import org.eclipse.zest.core.widgets.internal.ContainerFigure; |
| 49 |
import org.eclipse.zest.core.widgets.internal.RevealListener; |
|
|
| 50 |
import org.eclipse.zest.core.widgets.internal.ZestRootLayer; |
53 |
import org.eclipse.zest.core.widgets.internal.ZestRootLayer; |
| 51 |
import org.eclipse.zest.layouts.InvalidLayoutConfiguration; |
|
|
| 52 |
import org.eclipse.zest.layouts.LayoutAlgorithm; |
54 |
import org.eclipse.zest.layouts.LayoutAlgorithm; |
| 53 |
import org.eclipse.zest.layouts.LayoutEntity; |
55 |
import org.eclipse.zest.layouts.dataStructures.DisplayIndependentRectangle; |
| 54 |
import org.eclipse.zest.layouts.LayoutRelationship; |
56 |
import org.eclipse.zest.layouts.interfaces.ExpandCollapseManager; |
| 55 |
import org.eclipse.zest.layouts.LayoutStyles; |
|
|
| 56 |
import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm; |
| 57 |
import org.eclipse.zest.layouts.constraints.LayoutConstraint; |
| 58 |
|
57 |
|
| 59 |
/* |
58 |
/** |
| 60 |
* Holds the nodes and connections for the graph. |
59 |
* @since 1.0 |
| 61 |
* |
|
|
| 62 |
* @author Chris Callendar |
| 63 |
* |
| 64 |
* @author Ian Bull |
| 65 |
*/ |
60 |
*/ |
| 66 |
public class Graph extends FigureCanvas implements IContainer { |
61 |
public class Graph extends FigureCanvas implements IContainer { |
| 67 |
|
62 |
|
|
Lines 85-107
Link Here
|
| 85 |
* These are all the children of this graph. These lists contains all nodes |
80 |
* These are all the children of this graph. These lists contains all nodes |
| 86 |
* and connections that have added themselves to this graph. |
81 |
* and connections that have added themselves to this graph. |
| 87 |
*/ |
82 |
*/ |
| 88 |
private final List nodes; |
83 |
private List nodes; |
| 89 |
protected List connections; |
84 |
protected List connections; |
|
|
85 |
HashSet subgraphFigures; |
| 90 |
private List selectedItems = null; |
86 |
private List selectedItems = null; |
| 91 |
IFigure fisheyedFigure = null; |
87 |
private ArrayList fisheyeListeners = new ArrayList(); |
| 92 |
private List /* SelectionListener */selectionListeners = null; |
88 |
private List selectionListeners = null; |
| 93 |
|
89 |
|
| 94 |
/** This maps all visible nodes to their model element. */ |
90 |
/** This maps all visible nodes to their model element. */ |
| 95 |
private HashMap figure2ItemMap = null; |
91 |
private HashMap figure2ItemMap = null; |
| 96 |
|
92 |
|
| 97 |
/** Maps user nodes to internal nodes */ |
|
|
| 98 |
private int connectionStyle; |
93 |
private int connectionStyle; |
| 99 |
private int nodeStyle; |
94 |
private int nodeStyle; |
| 100 |
private List constraintAdapters; |
|
|
| 101 |
private List revealListeners = null; |
| 102 |
|
| 103 |
private ScalableFreeformLayeredPane fishEyeLayer = null; |
95 |
private ScalableFreeformLayeredPane fishEyeLayer = null; |
| 104 |
LayoutAlgorithm layoutAlgorithm = null; |
96 |
private InternalLayoutContext layoutContext = null; |
|
|
97 |
private volatile boolean shouldSheduleLayout; |
| 98 |
private volatile Runnable scheduledLayoutRunnable = null; |
| 99 |
private volatile boolean scheduledLayoutClean = false; |
| 105 |
private Dimension preferredSize = null; |
100 |
private Dimension preferredSize = null; |
| 106 |
int style = 0; |
101 |
int style = 0; |
| 107 |
|
102 |
|
|
Lines 120-131
Link Here
|
| 120 |
this.style = style; |
115 |
this.style = style; |
| 121 |
this.setBackground(ColorConstants.white); |
116 |
this.setBackground(ColorConstants.white); |
| 122 |
|
117 |
|
| 123 |
LIGHT_BLUE = new Color(Display.getDefault(), 216, 228, 248); |
|
|
| 124 |
LIGHT_BLUE_CYAN = new Color(Display.getDefault(), 213, 243, 255); |
| 125 |
GREY_BLUE = new Color(Display.getDefault(), 139, 150, 171); |
| 126 |
DARK_BLUE = new Color(Display.getDefault(), 1, 70, 122); |
| 127 |
LIGHT_YELLOW = new Color(Display.getDefault(), 255, 255, 206); |
| 128 |
|
| 129 |
this.setViewport(new FreeformViewport()); |
118 |
this.setViewport(new FreeformViewport()); |
| 130 |
|
119 |
|
| 131 |
this.getVerticalBar().addSelectionListener(new SelectionAdapter() { |
120 |
this.getVerticalBar().addSelectionListener(new SelectionAdapter() { |
|
Lines 142-208
Link Here
|
| 142 |
|
131 |
|
| 143 |
// @tag CGraph.workaround : this allows me to handle mouse events |
132 |
// @tag CGraph.workaround : this allows me to handle mouse events |
| 144 |
// outside of the canvas |
133 |
// outside of the canvas |
| 145 |
this.getLightweightSystem().setEventDispatcher(new SWTEventDispatcher() { |
134 |
this.getLightweightSystem().setEventDispatcher( |
| 146 |
public void dispatchMouseMoved(org.eclipse.swt.events.MouseEvent me) { |
135 |
new SWTEventDispatcher() { |
| 147 |
super.dispatchMouseMoved(me); |
136 |
public void dispatchMouseMoved( |
| 148 |
|
137 |
org.eclipse.swt.events.MouseEvent me) { |
| 149 |
// If the current event is null, return |
138 |
super.dispatchMouseMoved(me); |
| 150 |
if (getCurrentEvent() == null) { |
139 |
|
| 151 |
return; |
140 |
// If the current event is null, return |
| 152 |
} |
141 |
if (getCurrentEvent() == null) { |
|
|
142 |
return; |
| 143 |
} |
| 153 |
|
144 |
|
| 154 |
if (getMouseTarget() == null) { |
145 |
if (getMouseTarget() == null) { |
| 155 |
setMouseTarget(getRoot()); |
146 |
setMouseTarget(getRoot()); |
| 156 |
} |
147 |
} |
| 157 |
if ((me.stateMask & SWT.BUTTON_MASK) != 0) { |
148 |
if ((me.stateMask & SWT.BUTTON_MASK) != 0) { |
| 158 |
// Sometimes getCurrentEvent() returns null |
149 |
// Sometimes getCurrentEvent() returns null |
| 159 |
getMouseTarget().handleMouseDragged(getCurrentEvent()); |
150 |
getMouseTarget().handleMouseDragged( |
| 160 |
} else { |
151 |
getCurrentEvent()); |
| 161 |
getMouseTarget().handleMouseMoved(getCurrentEvent()); |
152 |
} else { |
| 162 |
} |
153 |
getMouseTarget() |
| 163 |
} |
154 |
.handleMouseMoved(getCurrentEvent()); |
| 164 |
}); |
155 |
} |
|
|
156 |
} |
| 157 |
}); |
| 165 |
|
158 |
|
| 166 |
this.setContents(createLayers()); |
159 |
this.setContents(createLayers()); |
| 167 |
DragSupport dragSupport = new DragSupport(this); |
160 |
DragSupport dragSupport = new DragSupport(); |
| 168 |
this.getLightweightSystem().getRootFigure().addMouseListener(dragSupport); |
161 |
this.getLightweightSystem().getRootFigure().addMouseListener( |
| 169 |
this.getLightweightSystem().getRootFigure().addMouseMotionListener(dragSupport); |
162 |
dragSupport); |
|
|
163 |
this.getLightweightSystem().getRootFigure().addMouseMotionListener( |
| 164 |
dragSupport); |
| 170 |
|
165 |
|
| 171 |
this.nodes = new ArrayList(); |
166 |
this.nodes = new ArrayList(); |
| 172 |
this.preferredSize = new Dimension(-1, -1); |
167 |
this.preferredSize = new Dimension(-1, -1); |
| 173 |
this.connectionStyle = ZestStyles.NONE; |
168 |
this.connectionStyle = ZestStyles.NONE; |
| 174 |
this.nodeStyle = ZestStyles.NONE; |
169 |
this.nodeStyle = ZestStyles.NONE; |
| 175 |
this.connections = new ArrayList(); |
170 |
this.connections = new ArrayList(); |
| 176 |
this.constraintAdapters = new ArrayList(); |
171 |
this.subgraphFigures = new HashSet(); |
| 177 |
this.selectedItems = new ArrayList(); |
172 |
this.selectedItems = new ArrayList(); |
| 178 |
this.selectionListeners = new ArrayList(); |
173 |
this.selectionListeners = new ArrayList(); |
| 179 |
this.figure2ItemMap = new HashMap(); |
174 |
this.figure2ItemMap = new HashMap(); |
| 180 |
|
175 |
|
| 181 |
revealListeners = new ArrayList(1); |
|
|
| 182 |
this.addPaintListener(new PaintListener() { |
176 |
this.addPaintListener(new PaintListener() { |
| 183 |
public void paintControl(PaintEvent e) { |
177 |
public void paintControl(PaintEvent e) { |
| 184 |
if (!revealListeners.isEmpty()) { |
178 |
if (shouldSheduleLayout) { |
| 185 |
// Go through the reveal list and let everyone know that the |
179 |
applyLayoutInternal(true); |
| 186 |
// view is now available. Remove the listeners so they are |
180 |
shouldSheduleLayout = false; |
| 187 |
// only |
|
|
| 188 |
// called once! |
| 189 |
Iterator iterator = revealListeners.iterator(); |
| 190 |
while (iterator.hasNext()) { |
| 191 |
RevealListener reveallisetner = (RevealListener) iterator.next(); |
| 192 |
reveallisetner.revealed(Graph.this); |
| 193 |
iterator.remove(); |
| 194 |
} |
| 195 |
} |
| 196 |
/* |
| 197 |
Iterator iterator = getNodes().iterator(); |
| 198 |
while (iterator.hasNext()) { |
| 199 |
GraphNode node = (GraphNode) iterator.next(); |
| 200 |
node.paint(); |
| 201 |
} |
181 |
} |
| 202 |
*/ |
|
|
| 203 |
} |
182 |
} |
| 204 |
}); |
183 |
}); |
| 205 |
|
184 |
|
|
|
185 |
this.addControlListener(new ControlListener() { |
| 186 |
|
| 187 |
public void controlResized(ControlEvent e) { |
| 188 |
if (preferredSize.width == -1 || preferredSize.height == -1) { |
| 189 |
getLayoutContext().fireBoundsChangedEvent(); |
| 190 |
} |
| 191 |
} |
| 192 |
|
| 193 |
public void controlMoved(ControlEvent e) { |
| 194 |
// do nothing |
| 195 |
} |
| 196 |
}); |
| 206 |
} |
197 |
} |
| 207 |
|
198 |
|
| 208 |
/** |
199 |
/** |
|
Lines 235-257
Link Here
|
| 235 |
} |
226 |
} |
| 236 |
|
227 |
|
| 237 |
/** |
228 |
/** |
| 238 |
* Adds a new constraint adapter to the list of constraint adapters |
|
|
| 239 |
* @param constraintAdapter |
| 240 |
*/ |
| 241 |
public void addConstraintAdapter(ConstraintAdapter constraintAdapter) { |
| 242 |
this.constraintAdapters.add(constraintAdapter); |
| 243 |
} |
| 244 |
|
| 245 |
/** |
| 246 |
* Sets the constraint adapters on this model |
| 247 |
* |
| 248 |
* @param constraintAdapters |
| 249 |
*/ |
| 250 |
public void setConstraintAdapters(List /* ConstraintAdapters */constraintAdapters) { |
| 251 |
this.constraintAdapters = constraintAdapters; |
| 252 |
} |
| 253 |
|
| 254 |
/** |
| 255 |
* Gets the root layer for this graph |
229 |
* Gets the root layer for this graph |
| 256 |
* |
230 |
* |
| 257 |
* @return |
231 |
* @return |
|
Lines 326-331
Link Here
|
| 326 |
} |
300 |
} |
| 327 |
} |
301 |
} |
| 328 |
} |
302 |
} |
|
|
303 |
// TODO shouldn't this method fire a selection event? |
| 329 |
} |
304 |
} |
| 330 |
|
305 |
|
| 331 |
public void selectAll() { |
306 |
public void selectAll() { |
|
Lines 334-339
Link Here
|
| 334 |
selectedItems.add(nodes.get(i)); |
309 |
selectedItems.add(nodes.get(i)); |
| 335 |
((GraphNode) nodes.get(i)).highlight(); |
310 |
((GraphNode) nodes.get(i)).highlight(); |
| 336 |
} |
311 |
} |
|
|
312 |
// TODO shouldn't this method fire a selection event? |
| 337 |
} |
313 |
} |
| 338 |
|
314 |
|
| 339 |
/** |
315 |
/** |
|
Lines 351-366
Link Here
|
| 351 |
* @see org.eclipse.swt.widgets.Widget#toString() |
327 |
* @see org.eclipse.swt.widgets.Widget#toString() |
| 352 |
*/ |
328 |
*/ |
| 353 |
public String toString() { |
329 |
public String toString() { |
| 354 |
return "GraphModel {" + nodes.size() + " nodes, " + connections.size() + " connections}"; |
330 |
return "GraphModel {" + nodes.size() + " nodes, " + connections.size() |
| 355 |
} |
331 |
+ " connections}"; |
| 356 |
|
|
|
| 357 |
/* |
| 358 |
* (non-Javadoc) |
| 359 |
* |
| 360 |
* @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphItem#getGraphModel() |
| 361 |
*/ |
| 362 |
public Graph getGraphModel() { |
| 363 |
return this; |
| 364 |
} |
332 |
} |
| 365 |
|
333 |
|
| 366 |
/** |
334 |
/** |
|
Lines 389-409
Link Here
|
| 389 |
} |
357 |
} |
| 390 |
|
358 |
|
| 391 |
/** |
359 |
/** |
| 392 |
* Runs the layout on this graph. It uses the reveal listner to run the |
360 |
* Runs the layout on this graph. If the view is not visible layout will be |
| 393 |
* layout only if the view is visible. Otherwise it will be deferred until |
361 |
* deferred until after the view is available. |
| 394 |
* after the view is available. |
|
|
| 395 |
*/ |
362 |
*/ |
| 396 |
public void applyLayout() { |
363 |
public void applyLayout() { |
| 397 |
this.addRevealListener(new RevealListener() { |
364 |
scheduleLayoutOnReveal(true); |
| 398 |
public void revealed(Control c) { |
365 |
} |
| 399 |
Display.getDefault().asyncExec(new Runnable() { |
|
|
| 400 |
|
366 |
|
| 401 |
public void run() { |
367 |
/** |
| 402 |
applyLayoutInternal(); |
368 |
* Enables or disables dynamic layout (that is layout algorithm performing |
| 403 |
} |
369 |
* layout in background or when certain events occur). Dynamic layout should |
| 404 |
}); |
370 |
* be disabled before doing a long series of changes in the graph to make |
|
|
371 |
* sure that layout algorithm won't interfere with these changes. |
| 372 |
* |
| 373 |
* Enabling dynamic layout causes the layout algorithm to be applied even if |
| 374 |
* it's not actually a dynamic algorithm. |
| 375 |
* |
| 376 |
* @param enabled |
| 377 |
* |
| 378 |
* @since 2.0 |
| 379 |
*/ |
| 380 |
public void setDynamicLayout(boolean enabled) { |
| 381 |
if (getLayoutContext().isBackgroundLayoutEnabled() != enabled) { |
| 382 |
layoutContext.setBackgroundLayoutEnabled(enabled); |
| 383 |
if (enabled) { |
| 384 |
scheduleLayoutOnReveal(false); |
| 405 |
} |
385 |
} |
| 406 |
}); |
386 |
} |
|
|
387 |
} |
| 388 |
|
| 389 |
/** |
| 390 |
* |
| 391 |
* @return true if dynamic layout is enabled (see |
| 392 |
* {@link #setDynamicLayout(boolean)}) |
| 393 |
* @since 2.0 |
| 394 |
*/ |
| 395 |
public boolean isDynamicLayoutEnabled() { |
| 396 |
return getLayoutContext().isBackgroundLayoutEnabled(); |
| 397 |
} |
| 398 |
|
| 399 |
private void applyLayoutInternal(boolean clean) { |
| 400 |
if (getLayoutContext().getLayoutAlgorithm() == null) { |
| 401 |
return; |
| 402 |
} |
| 403 |
scheduledLayoutClean = scheduledLayoutClean || clean; |
| 404 |
synchronized (this) { |
| 405 |
if (scheduledLayoutRunnable == null) { |
| 406 |
Display.getDefault().asyncExec( |
| 407 |
scheduledLayoutRunnable = new Runnable() { |
| 408 |
public void run() { |
| 409 |
Animation.markBegin(); |
| 410 |
getLayoutContext().applyLayout( |
| 411 |
scheduledLayoutClean); |
| 412 |
layoutContext.flushChanges(false); |
| 413 |
Animation.run(ANIMATION_TIME); |
| 414 |
getLightweightSystem().getUpdateManager() |
| 415 |
.performUpdate(); |
| 416 |
synchronized (Graph.this) { |
| 417 |
scheduledLayoutRunnable = null; |
| 418 |
scheduledLayoutClean = false; |
| 419 |
} |
| 420 |
} |
| 421 |
}); |
| 422 |
} |
| 423 |
} |
| 407 |
} |
424 |
} |
| 408 |
|
425 |
|
| 409 |
/** |
426 |
/** |
|
Lines 415-434
Link Here
|
| 415 |
*/ |
432 |
*/ |
| 416 |
public void setPreferredSize(int width, int height) { |
433 |
public void setPreferredSize(int width, int height) { |
| 417 |
this.preferredSize = new Dimension(width, height); |
434 |
this.preferredSize = new Dimension(width, height); |
|
|
435 |
getLayoutContext().fireBoundsChangedEvent(); |
| 436 |
} |
| 437 |
|
| 438 |
/** |
| 439 |
* @return the preferred size of the layout area. |
| 440 |
* @since 2.0 |
| 441 |
*/ |
| 442 |
public Dimension getPreferredSize() { |
| 443 |
if (preferredSize.width < 0 || preferredSize.height < 0) { |
| 444 |
org.eclipse.swt.graphics.Point size = getSize(); |
| 445 |
double scale = getRootLayer().getScale(); |
| 446 |
return new Dimension((int) (size.x / scale + 0.5), (int) (size.y |
| 447 |
/ scale + 0.5)); |
| 448 |
} |
| 449 |
return preferredSize; |
| 450 |
} |
| 451 |
|
| 452 |
/** |
| 453 |
* @noreference This method is not intended to be referenced by clients. |
| 454 |
*/ |
| 455 |
public InternalLayoutContext getLayoutContext() { |
| 456 |
if (layoutContext == null) { |
| 457 |
layoutContext = new InternalLayoutContext(this); |
| 458 |
} |
| 459 |
return layoutContext; |
| 418 |
} |
460 |
} |
| 419 |
|
461 |
|
| 420 |
/** |
462 |
/** |
| 421 |
* @param algorithm |
463 |
* @param algorithm |
|
|
464 |
* @since 2.0 |
| 422 |
*/ |
465 |
*/ |
| 423 |
public void setLayoutAlgorithm(LayoutAlgorithm algorithm, boolean applyLayout) { |
466 |
public void setLayoutAlgorithm(LayoutAlgorithm algorithm, |
| 424 |
this.layoutAlgorithm = algorithm; |
467 |
boolean applyLayout) { |
|
|
468 |
getLayoutContext().setLayoutAlgorithm(algorithm); |
| 425 |
if (applyLayout) { |
469 |
if (applyLayout) { |
| 426 |
applyLayout(); |
470 |
applyLayout(); |
| 427 |
} |
471 |
} |
| 428 |
} |
472 |
} |
| 429 |
|
473 |
|
|
|
474 |
/** |
| 475 |
* @since 2.0 |
| 476 |
*/ |
| 430 |
public LayoutAlgorithm getLayoutAlgorithm() { |
477 |
public LayoutAlgorithm getLayoutAlgorithm() { |
| 431 |
return this.layoutAlgorithm; |
478 |
return getLayoutContext().getLayoutAlgorithm(); |
|
|
479 |
} |
| 480 |
|
| 481 |
/** |
| 482 |
* @since 2.0 |
| 483 |
*/ |
| 484 |
public void setSubgraphFactory(SubgraphFactory factory) { |
| 485 |
getLayoutContext().setSubgraphFactory(factory); |
| 486 |
} |
| 487 |
|
| 488 |
/** |
| 489 |
* @since 2.0 |
| 490 |
*/ |
| 491 |
public SubgraphFactory getSubgraphFactory() { |
| 492 |
return getLayoutContext().getSubgraphFactory(); |
| 493 |
} |
| 494 |
|
| 495 |
/** |
| 496 |
* @since 2.0 |
| 497 |
*/ |
| 498 |
public void setExpandCollapseManager( |
| 499 |
ExpandCollapseManager expandCollapseManager) { |
| 500 |
getLayoutContext().setExpandCollapseManager(expandCollapseManager); |
| 501 |
} |
| 502 |
|
| 503 |
/** |
| 504 |
* @since 2.0 |
| 505 |
*/ |
| 506 |
public ExpandCollapseManager getExpandCollapseManager() { |
| 507 |
return getLayoutContext().getExpandCollapseManager(); |
| 508 |
} |
| 509 |
|
| 510 |
/** |
| 511 |
* Adds a filter used for hiding elements from layout algorithm. |
| 512 |
* |
| 513 |
* NOTE: If a node or subgraph if filtered out, all connections adjacent to |
| 514 |
* it should also be filtered out. Otherwise layout algorithm may behave in |
| 515 |
* an unexpected way. |
| 516 |
* |
| 517 |
* @param filter |
| 518 |
* filter to add |
| 519 |
* @since 2.0 |
| 520 |
*/ |
| 521 |
public void addLayoutFilter(LayoutFilter filter) { |
| 522 |
getLayoutContext().addFilter(filter); |
| 523 |
} |
| 524 |
|
| 525 |
/** |
| 526 |
* Removes given layout filter. If it had not been added to this graph, this |
| 527 |
* method does nothing. |
| 528 |
* |
| 529 |
* @param filter |
| 530 |
* filter to remove |
| 531 |
* @since 2.0 |
| 532 |
*/ |
| 533 |
public void removeLayoutFilter(LayoutFilter filter) { |
| 534 |
getLayoutContext().removeFilter(filter); |
| 432 |
} |
535 |
} |
| 433 |
|
536 |
|
| 434 |
/** |
537 |
/** |
|
Lines 437-548
Link Here
|
| 437 |
* This point should be translated to relative before calling findFigureAt |
540 |
* This point should be translated to relative before calling findFigureAt |
| 438 |
*/ |
541 |
*/ |
| 439 |
public IFigure getFigureAt(int x, int y) { |
542 |
public IFigure getFigureAt(int x, int y) { |
| 440 |
IFigure figureUnderMouse = this.getContents().findFigureAt(x, y, new TreeSearch() { |
543 |
IFigure figureUnderMouse = this.getContents().findFigureAt(x, y, |
|
|
544 |
new TreeSearch() { |
| 441 |
|
545 |
|
| 442 |
public boolean accept(IFigure figure) { |
546 |
public boolean accept(IFigure figure) { |
| 443 |
return true; |
547 |
return true; |
| 444 |
} |
548 |
} |
| 445 |
|
|
|
| 446 |
public boolean prune(IFigure figure) { |
| 447 |
IFigure parent = figure.getParent(); |
| 448 |
// @tag TODO Zest : change these to from getParent to their actual layer names |
| 449 |
|
549 |
|
| 450 |
if (parent == fishEyeLayer) { |
550 |
public boolean prune(IFigure figure) { |
| 451 |
// If it node is on the fish eye layer, don't worry about it. |
551 |
IFigure parent = figure.getParent(); |
| 452 |
return true; |
552 |
// @tag TODO Zest : change these to from getParent to |
| 453 |
} |
553 |
// their |
| 454 |
if (parent instanceof ContainerFigure && figure instanceof PolylineConnection) { |
554 |
// actual layer names |
| 455 |
return false; |
555 |
|
| 456 |
} |
556 |
if (parent == fishEyeLayer) { |
| 457 |
if (parent == zestRootLayer || parent == zestRootLayer.getParent() || parent == zestRootLayer.getParent().getParent()) { |
557 |
// If it node is on the fish eye layer, don't worry |
| 458 |
return false; |
558 |
// about |
| 459 |
} |
559 |
// it. |
| 460 |
GraphItem item = (GraphItem) figure2ItemMap.get(figure); |
560 |
return true; |
| 461 |
if (item != null && item.getItemType() == GraphItem.CONTAINER) { |
561 |
} |
| 462 |
return false; |
562 |
if (parent instanceof ContainerFigure |
| 463 |
} else if (figure instanceof FreeformLayer || parent instanceof FreeformLayer || figure instanceof ScrollPane || parent instanceof ScrollPane || parent instanceof ScalableFreeformLayeredPane || figure instanceof ScalableFreeformLayeredPane || figure instanceof FreeformViewport || |
563 |
&& figure instanceof PolylineConnection) { |
| 464 |
parent instanceof FreeformViewport) { |
564 |
return false; |
| 465 |
return false; |
565 |
} |
| 466 |
} |
566 |
if (parent == zestRootLayer |
| 467 |
return true; |
567 |
|| parent == zestRootLayer.getParent() |
| 468 |
} |
568 |
|| parent == zestRootLayer.getParent() |
|
|
569 |
.getParent()) { |
| 570 |
return false; |
| 571 |
} |
| 572 |
GraphItem item = (GraphItem) figure2ItemMap.get(figure); |
| 573 |
if (item != null |
| 574 |
&& item.getItemType() == GraphItem.CONTAINER) { |
| 575 |
return false; |
| 576 |
} else if (figure instanceof FreeformLayer |
| 577 |
|| parent instanceof FreeformLayer |
| 578 |
|| figure instanceof ScrollPane |
| 579 |
|| parent instanceof ScrollPane |
| 580 |
|| parent instanceof ScalableFreeformLayeredPane |
| 581 |
|| figure instanceof ScalableFreeformLayeredPane |
| 582 |
|| figure instanceof FreeformViewport |
| 583 |
|| parent instanceof FreeformViewport) { |
| 584 |
return false; |
| 585 |
} |
| 586 |
return true; |
| 587 |
} |
| 469 |
|
588 |
|
| 470 |
}); |
589 |
}); |
| 471 |
return figureUnderMouse; |
590 |
return figureUnderMouse; |
| 472 |
|
591 |
|
| 473 |
} |
592 |
} |
| 474 |
|
593 |
|
| 475 |
// ///////////////////////////////////////////////////////////////////////////////// |
594 |
private class DragSupport implements MouseMotionListener, |
| 476 |
// PRIVATE METHODS. These are NON API |
595 |
org.eclipse.draw2d.MouseListener { |
| 477 |
// ///////////////////////////////////////////////////////////////////////////////// |
596 |
|
| 478 |
class DragSupport implements MouseMotionListener, org.eclipse.draw2d.MouseListener { |
597 |
Point dragStartLocation = null; |
| 479 |
/** |
598 |
IFigure draggedSubgraphFigure = null; |
| 480 |
* |
599 |
/** locations of dragged items relative to cursor position */ |
| 481 |
*/ |
600 |
ArrayList relativeLocations = new ArrayList(); |
| 482 |
Graph graph = null; |
|
|
| 483 |
Point lastLocation = null; |
| 484 |
GraphItem fisheyedItem = null; |
601 |
GraphItem fisheyedItem = null; |
| 485 |
boolean isDragging = false; |
602 |
boolean isDragging = false; |
| 486 |
|
603 |
|
| 487 |
DragSupport(Graph graph) { |
|
|
| 488 |
this.graph = graph; |
| 489 |
} |
| 490 |
|
| 491 |
public void mouseDragged(org.eclipse.draw2d.MouseEvent me) { |
604 |
public void mouseDragged(org.eclipse.draw2d.MouseEvent me) { |
| 492 |
if (!isDragging) { |
605 |
if (!isDragging) { |
| 493 |
return; |
606 |
return; |
| 494 |
} |
607 |
} |
| 495 |
Point mousePoint = new Point(me.x, me.y); |
608 |
if (selectedItems.isEmpty()) { |
| 496 |
Point tempPoint = mousePoint.getCopy(); |
609 |
IFigure figureUnderMouse = getFigureAt(dragStartLocation.x, |
| 497 |
if (selectedItems.size() > 0) { |
610 |
dragStartLocation.y); |
| 498 |
Iterator iterator = selectedItems.iterator(); |
611 |
if (subgraphFigures.contains(figureUnderMouse)) { |
| 499 |
while (iterator.hasNext()) { |
612 |
draggedSubgraphFigure = figureUnderMouse; |
| 500 |
GraphItem item = (GraphItem) iterator.next(); |
613 |
} |
| 501 |
if ((item.getItemType() == GraphItem.NODE) || (item.getItemType() == GraphItem.CONTAINER)) { |
614 |
} |
| 502 |
// @tag Zest.selection Zest.move : This is where the node movement is tracked |
|
|
| 503 |
Point pointCopy = mousePoint.getCopy(); |
| 504 |
|
615 |
|
| 505 |
Point tempLastLocation = lastLocation.getCopy(); |
616 |
Point mousePoint = new Point(me.x, me.y); |
| 506 |
item.getFigure().getParent().translateToRelative(tempLastLocation); |
617 |
if (!selectedItems.isEmpty() || draggedSubgraphFigure != null) { |
| 507 |
item.getFigure().getParent().translateFromParent(tempLastLocation); |
|
|
| 508 |
|
| 509 |
item.getFigure().getParent().translateToRelative(pointCopy); |
| 510 |
item.getFigure().getParent().translateFromParent(pointCopy); |
| 511 |
Point delta = new Point(pointCopy.x - tempLastLocation.x, pointCopy.y - tempLastLocation.y); |
| 512 |
if (item.getItemType() == GraphItem.NODE || item.getItemType() == GraphItem.CONTAINER) { |
| 513 |
GraphNode node = (GraphNode) item; |
| 514 |
node.setLocation(node.getLocation().x + delta.x, node.getLocation().y + delta.y); |
| 515 |
|
618 |
|
|
|
619 |
if (relativeLocations.isEmpty()) { |
| 620 |
for (Iterator iterator = selectedItems.iterator(); iterator |
| 621 |
.hasNext();) { |
| 622 |
GraphItem item = (GraphItem) iterator.next(); |
| 623 |
if ((item.getItemType() == GraphItem.NODE) |
| 624 |
|| (item.getItemType() == GraphItem.CONTAINER)) { |
| 625 |
relativeLocations.add(getRelativeLocation(item |
| 626 |
.getFigure())); |
| 516 |
} |
627 |
} |
| 517 |
/* |
628 |
} |
| 518 |
else if (item.getItemType() == GraphItem.CONTAINER) { |
629 |
if (draggedSubgraphFigure != null) { |
| 519 |
GraphContainer container = (GraphContainer) item; |
630 |
relativeLocations |
| 520 |
container.setLocation(container.getLocation().x + delta.x, container.getLocation().y + delta.y); |
631 |
.add(getRelativeLocation(draggedSubgraphFigure)); |
| 521 |
} |
632 |
} |
| 522 |
*/ |
633 |
} |
|
|
634 |
|
| 635 |
Iterator locationsIterator = relativeLocations.iterator(); |
| 636 |
for (Iterator selectionIterator = selectedItems.iterator(); selectionIterator |
| 637 |
.hasNext();) { |
| 638 |
GraphItem item = (GraphItem) selectionIterator.next(); |
| 639 |
if ((item.getItemType() == GraphItem.NODE) |
| 640 |
|| (item.getItemType() == GraphItem.CONTAINER)) { |
| 641 |
Point pointCopy = mousePoint.getCopy(); |
| 642 |
Point relativeLocation = (Point) locationsIterator |
| 643 |
.next(); |
| 644 |
|
| 645 |
item.getFigure().getParent().translateToRelative( |
| 646 |
pointCopy); |
| 647 |
item.getFigure().getParent().translateFromParent( |
| 648 |
pointCopy); |
| 649 |
|
| 650 |
((GraphNode) item) |
| 651 |
.setLocation(relativeLocation.x + pointCopy.x, |
| 652 |
relativeLocation.y + pointCopy.y); |
| 523 |
} else { |
653 |
} else { |
| 524 |
// There is no movement for connection |
654 |
// There is no movement for connection |
| 525 |
} |
655 |
} |
| 526 |
} |
656 |
} |
| 527 |
if (fisheyedFigure != null) { |
657 |
if (draggedSubgraphFigure != null) { |
| 528 |
Point pointCopy = mousePoint.getCopy(); |
658 |
Point pointCopy = mousePoint.getCopy(); |
| 529 |
|
659 |
draggedSubgraphFigure.getParent().translateToRelative( |
| 530 |
Point tempLastLocation = lastLocation.getCopy(); |
660 |
pointCopy); |
| 531 |
fisheyedFigure.translateToRelative(tempLastLocation); |
661 |
draggedSubgraphFigure.getParent().translateFromParent( |
| 532 |
fisheyedFigure.translateFromParent(tempLastLocation); |
662 |
pointCopy); |
| 533 |
|
663 |
Point relativeLocation = (Point) locationsIterator.next(); |
| 534 |
fisheyedFigure.translateToRelative(pointCopy); |
664 |
pointCopy.x += relativeLocation.x; |
| 535 |
fisheyedFigure.translateFromParent(pointCopy); |
665 |
pointCopy.y += relativeLocation.y; |
| 536 |
Point delta = new Point(pointCopy.x - tempLastLocation.x, pointCopy.y - tempLastLocation.y); |
666 |
|
| 537 |
Point point = new Point(fisheyedFigure.getBounds().x + delta.x, fisheyedFigure.getBounds().y + delta.y); |
667 |
draggedSubgraphFigure.setLocation(pointCopy); |
| 538 |
fishEyeLayer.setConstraint(fisheyedFigure, new Rectangle(point, fisheyedFigure.getSize())); |
|
|
| 539 |
fishEyeLayer.getUpdateManager().performUpdate(); |
| 540 |
//fisheyedFigure.setBounds(new Rectangle(point2, fisheyedFigure.getSize())); |
| 541 |
//fisheyedFigure.setLocation(new Point(fisheyedFigure.getBounds().x + delta.x, fisheyedFigure.getBounds().y + delta.y)); |
| 542 |
} |
668 |
} |
| 543 |
} |
669 |
} |
| 544 |
lastLocation = tempPoint; |
670 |
} |
| 545 |
//oldLocation = mousePoint; |
671 |
|
|
|
672 |
private Point getRelativeLocation(IFigure figure) { |
| 673 |
Point location = figure.getBounds().getTopLeft(); |
| 674 |
Point mousePointCopy = dragStartLocation.getCopy(); |
| 675 |
figure.getParent().translateToRelative(mousePointCopy); |
| 676 |
figure.getParent().translateFromParent(mousePointCopy); |
| 677 |
location.x -= mousePointCopy.x; |
| 678 |
location.y -= mousePointCopy.y; |
| 679 |
return location; |
| 546 |
} |
680 |
} |
| 547 |
|
681 |
|
| 548 |
public void mouseEntered(org.eclipse.draw2d.MouseEvent me) { |
682 |
public void mouseEntered(org.eclipse.draw2d.MouseEvent me) { |
|
Lines 559-565
Link Here
|
| 559 |
|
693 |
|
| 560 |
/** |
694 |
/** |
| 561 |
* This tracks whenever a mouse moves. The only thing we care about is |
695 |
* This tracks whenever a mouse moves. The only thing we care about is |
| 562 |
* fisheye(ing) nodes. This means whenever the mouse moves we check if |
696 |
* fisheye(ing) nodes. This means whenever the mouse moves we check if |
| 563 |
* we need to fisheye on a node or not. |
697 |
* we need to fisheye on a node or not. |
| 564 |
*/ |
698 |
*/ |
| 565 |
public void mouseMoved(org.eclipse.draw2d.MouseEvent me) { |
699 |
public void mouseMoved(org.eclipse.draw2d.MouseEvent me) { |
|
Lines 569-595
Link Here
|
| 569 |
|
703 |
|
| 570 |
if (figureUnderMouse != null) { |
704 |
if (figureUnderMouse != null) { |
| 571 |
// There is a figure under this mouse |
705 |
// There is a figure under this mouse |
| 572 |
GraphItem itemUnderMouse = (GraphItem) figure2ItemMap.get(figureUnderMouse); |
706 |
GraphItem itemUnderMouse = (GraphItem) figure2ItemMap |
|
|
707 |
.get(figureUnderMouse); |
| 573 |
if (itemUnderMouse == fisheyedItem) { |
708 |
if (itemUnderMouse == fisheyedItem) { |
| 574 |
|
709 |
return; |
| 575 |
} else if (itemUnderMouse != null && itemUnderMouse.getItemType() == GraphItem.NODE) { |
710 |
} |
|
|
711 |
if (fisheyedItem != null) { |
| 712 |
((GraphNode) fisheyedItem).fishEye(false, true); |
| 713 |
fisheyedItem = null; |
| 714 |
} |
| 715 |
if (itemUnderMouse != null |
| 716 |
&& itemUnderMouse.getItemType() == GraphItem.NODE) { |
| 576 |
fisheyedItem = itemUnderMouse; |
717 |
fisheyedItem = itemUnderMouse; |
| 577 |
fisheyedFigure = ((GraphNode) itemUnderMouse).fishEye(true, true); |
718 |
IFigure fisheyedFigure = ((GraphNode) itemUnderMouse) |
|
|
719 |
.fishEye(true, true); |
| 578 |
if (fisheyedFigure == null) { |
720 |
if (fisheyedFigure == null) { |
| 579 |
// If there is no fisheye figure (this means that the node does not support a fish eye) |
721 |
// If there is no fisheye figure (this means that the |
|
|
722 |
// node does not support a fish eye) |
| 580 |
// then remove the fisheyed item |
723 |
// then remove the fisheyed item |
| 581 |
fisheyedItem = null; |
724 |
fisheyedItem = null; |
| 582 |
} |
725 |
} |
| 583 |
} else if (fisheyedItem != null) { |
|
|
| 584 |
((GraphNode) fisheyedItem).fishEye(false, true); |
| 585 |
fisheyedItem = null; |
| 586 |
fisheyedFigure = null; |
| 587 |
} |
726 |
} |
| 588 |
} else { |
727 |
} else { |
| 589 |
if (fisheyedItem != null) { |
728 |
if (fisheyedItem != null) { |
| 590 |
((GraphNode) fisheyedItem).fishEye(false, true); |
729 |
((GraphNode) fisheyedItem).fishEye(false, true); |
| 591 |
fisheyedItem = null; |
730 |
fisheyedItem = null; |
| 592 |
fisheyedFigure = null; |
|
|
| 593 |
} |
731 |
} |
| 594 |
} |
732 |
} |
| 595 |
} |
733 |
} |
|
Lines 601-607
Link Here
|
| 601 |
public void mousePressed(org.eclipse.draw2d.MouseEvent me) { |
739 |
public void mousePressed(org.eclipse.draw2d.MouseEvent me) { |
| 602 |
isDragging = true; |
740 |
isDragging = true; |
| 603 |
Point mousePoint = new Point(me.x, me.y); |
741 |
Point mousePoint = new Point(me.x, me.y); |
| 604 |
lastLocation = mousePoint.getCopy(); |
742 |
dragStartLocation = mousePoint.getCopy(); |
| 605 |
|
743 |
|
| 606 |
getRootLayer().translateToRelative(mousePoint); |
744 |
getRootLayer().translateToRelative(mousePoint); |
| 607 |
|
745 |
|
|
Lines 610-619
Link Here
|
| 610 |
scale *= 1.05; |
748 |
scale *= 1.05; |
| 611 |
getRootLayer().setScale(scale); |
749 |
getRootLayer().setScale(scale); |
| 612 |
Point newMousePoint = mousePoint.getCopy().scale(1.05); |
750 |
Point newMousePoint = mousePoint.getCopy().scale(1.05); |
| 613 |
Point delta = new Point(newMousePoint.x - mousePoint.x, newMousePoint.y - mousePoint.y); |
751 |
Point delta = new Point(newMousePoint.x - mousePoint.x, |
| 614 |
Point newViewLocation = getViewport().getViewLocation().getCopy().translate(delta); |
752 |
newMousePoint.y - mousePoint.y); |
|
|
753 |
Point newViewLocation = getViewport().getViewLocation() |
| 754 |
.getCopy().translate(delta); |
| 615 |
getViewport().setViewLocation(newViewLocation); |
755 |
getViewport().setViewLocation(newViewLocation); |
| 616 |
lastLocation.scale(scale); |
|
|
| 617 |
|
756 |
|
| 618 |
clearSelection(); |
757 |
clearSelection(); |
| 619 |
return; |
758 |
return; |
|
Lines 623-644
Link Here
|
| 623 |
getRootLayer().setScale(scale); |
762 |
getRootLayer().setScale(scale); |
| 624 |
|
763 |
|
| 625 |
Point newMousePoint = mousePoint.getCopy().scale(1 / 1.05); |
764 |
Point newMousePoint = mousePoint.getCopy().scale(1 / 1.05); |
| 626 |
Point delta = new Point(newMousePoint.x - mousePoint.x, newMousePoint.y - mousePoint.y); |
765 |
Point delta = new Point(newMousePoint.x - mousePoint.x, |
| 627 |
Point newViewLocation = getViewport().getViewLocation().getCopy().translate(delta); |
766 |
newMousePoint.y - mousePoint.y); |
|
|
767 |
Point newViewLocation = getViewport().getViewLocation() |
| 768 |
.getCopy().translate(delta); |
| 628 |
getViewport().setViewLocation(newViewLocation); |
769 |
getViewport().setViewLocation(newViewLocation); |
| 629 |
clearSelection(); |
770 |
clearSelection(); |
| 630 |
return; |
771 |
return; |
| 631 |
} else { |
772 |
} else { |
| 632 |
boolean hasSelection = selectedItems.size() > 0; |
773 |
boolean hasSelection = selectedItems.size() > 0; |
| 633 |
IFigure figureUnderMouse = getFigureAt(mousePoint.x, mousePoint.y); |
774 |
IFigure figureUnderMouse = getFigureAt(mousePoint.x, |
|
|
775 |
mousePoint.y); |
| 634 |
getRootLayer().translateFromParent(mousePoint); |
776 |
getRootLayer().translateFromParent(mousePoint); |
| 635 |
|
777 |
|
| 636 |
if (figureUnderMouse != null) { |
778 |
if (figureUnderMouse != null) { |
| 637 |
figureUnderMouse.getParent().translateFromParent(mousePoint); |
779 |
figureUnderMouse.getParent() |
|
|
780 |
.translateFromParent(mousePoint); |
| 638 |
} |
781 |
} |
| 639 |
// If the figure under the mouse is the canvas, and CTRL is not being held down, then select |
782 |
// If the figure under the mouse is the canvas, and CTRL is not |
|
|
783 |
// being held down, then select |
| 640 |
// nothing |
784 |
// nothing |
| 641 |
if (figureUnderMouse == null || figureUnderMouse == graph) { |
785 |
if (figureUnderMouse == null || figureUnderMouse == Graph.this) { |
| 642 |
if (me.getState() != org.eclipse.draw2d.MouseEvent.CONTROL) { |
786 |
if (me.getState() != org.eclipse.draw2d.MouseEvent.CONTROL) { |
| 643 |
clearSelection(); |
787 |
clearSelection(); |
| 644 |
if (hasSelection) { |
788 |
if (hasSelection) { |
|
Lines 649-655
Link Here
|
| 649 |
return; |
793 |
return; |
| 650 |
} |
794 |
} |
| 651 |
|
795 |
|
| 652 |
GraphItem itemUnderMouse = (GraphItem) figure2ItemMap.get(figureUnderMouse); |
796 |
GraphItem itemUnderMouse = (GraphItem) figure2ItemMap |
|
|
797 |
.get(figureUnderMouse); |
| 653 |
if (itemUnderMouse == null) { |
798 |
if (itemUnderMouse == null) { |
| 654 |
if (me.getState() != org.eclipse.draw2d.MouseEvent.CONTROL) { |
799 |
if (me.getState() != org.eclipse.draw2d.MouseEvent.CONTROL) { |
| 655 |
clearSelection(); |
800 |
clearSelection(); |
|
Lines 661-668
Link Here
|
| 661 |
return; |
806 |
return; |
| 662 |
} |
807 |
} |
| 663 |
if (selectedItems.contains(itemUnderMouse)) { |
808 |
if (selectedItems.contains(itemUnderMouse)) { |
| 664 |
// We have already selected this node, and CTRL is being held down, remove this selection |
809 |
// We have already selected this node, and CTRL is being |
| 665 |
// @tag Zest.selection : This deselects when you have CTRL pressed |
810 |
// held down, remove this selection |
|
|
811 |
// @tag Zest.selection : This deselects when you have CTRL |
| 812 |
// pressed |
| 666 |
if (me.getState() == org.eclipse.draw2d.MouseEvent.CONTROL) { |
813 |
if (me.getState() == org.eclipse.draw2d.MouseEvent.CONTROL) { |
| 667 |
selectedItems.remove(itemUnderMouse); |
814 |
selectedItems.remove(itemUnderMouse); |
| 668 |
(itemUnderMouse).unhighlight(); |
815 |
(itemUnderMouse).unhighlight(); |
|
Lines 676-682
Link Here
|
| 676 |
} |
823 |
} |
| 677 |
|
824 |
|
| 678 |
if (itemUnderMouse.getItemType() == GraphItem.NODE) { |
825 |
if (itemUnderMouse.getItemType() == GraphItem.NODE) { |
| 679 |
// @tag Zest.selection : This is where the nodes are selected |
826 |
// @tag Zest.selection : This is where the nodes are |
|
|
827 |
// selected |
| 680 |
selectedItems.add(itemUnderMouse); |
828 |
selectedItems.add(itemUnderMouse); |
| 681 |
((GraphNode) itemUnderMouse).highlight(); |
829 |
((GraphNode) itemUnderMouse).highlight(); |
| 682 |
fireWidgetSelectedEvent(itemUnderMouse); |
830 |
fireWidgetSelectedEvent(itemUnderMouse); |
|
Lines 696-702
Link Here
|
| 696 |
|
844 |
|
| 697 |
public void mouseReleased(org.eclipse.draw2d.MouseEvent me) { |
845 |
public void mouseReleased(org.eclipse.draw2d.MouseEvent me) { |
| 698 |
isDragging = false; |
846 |
isDragging = false; |
| 699 |
|
847 |
relativeLocations.clear(); |
|
|
848 |
draggedSubgraphFigure = null; |
| 700 |
} |
849 |
} |
| 701 |
|
850 |
|
| 702 |
} |
851 |
} |
|
Lines 715-721
Link Here
|
| 715 |
private void fireWidgetSelectedEvent(Item item) { |
864 |
private void fireWidgetSelectedEvent(Item item) { |
| 716 |
Iterator iterator = selectionListeners.iterator(); |
865 |
Iterator iterator = selectionListeners.iterator(); |
| 717 |
while (iterator.hasNext()) { |
866 |
while (iterator.hasNext()) { |
| 718 |
SelectionListener selectionListener = (SelectionListener) iterator.next(); |
867 |
SelectionListener selectionListener = (SelectionListener) iterator |
|
|
868 |
.next(); |
| 719 |
Event swtEvent = new Event(); |
869 |
Event swtEvent = new Event(); |
| 720 |
swtEvent.item = item; |
870 |
swtEvent.item = item; |
| 721 |
swtEvent.widget = this; |
871 |
swtEvent.widget = this; |
|
Lines 726-804
Link Here
|
| 726 |
} |
876 |
} |
| 727 |
|
877 |
|
| 728 |
/** |
878 |
/** |
| 729 |
* Moves the edge to the highlight layer. This moves the edge above the |
|
|
| 730 |
* nodes |
| 731 |
* |
| 732 |
* @param connection |
| 733 |
*/ |
| 734 |
void highlightEdge(GraphConnection connection) { |
| 735 |
IFigure figure = connection.getConnectionFigure(); |
| 736 |
if (figure != null && !connection.isHighlighted()) { |
| 737 |
zestRootLayer.highlightConnection(figure); |
| 738 |
} |
| 739 |
} |
| 740 |
|
| 741 |
/** |
| 742 |
* Moves the edge from the edge feedback layer back to the edge layer |
| 743 |
* |
| 744 |
* @param graphConnection |
| 745 |
*/ |
| 746 |
void unhighlightEdge(GraphConnection connection) { |
| 747 |
IFigure figure = connection.getConnectionFigure(); |
| 748 |
if (figure != null && connection.isHighlighted()) { |
| 749 |
zestRootLayer.unHighlightConnection(figure); |
| 750 |
} |
| 751 |
} |
| 752 |
|
| 753 |
/** |
| 754 |
* Moves the node onto the node feedback layer |
| 755 |
* |
| 756 |
* @param node |
| 757 |
*/ |
| 758 |
void highlightNode(GraphNode node) { |
| 759 |
IFigure figure = node.getNodeFigure(); |
| 760 |
if (figure != null && !node.isHighlighted()) { |
| 761 |
zestRootLayer.highlightNode(figure); |
| 762 |
} |
| 763 |
} |
| 764 |
|
| 765 |
/** |
| 766 |
* Moves the node onto the node feedback layer |
| 767 |
* |
| 768 |
* @param node |
| 769 |
*/ |
| 770 |
void highlightNode(GraphContainer node) { |
| 771 |
IFigure figure = node.getNodeFigure(); |
| 772 |
if (figure != null && !node.isHighlighted()) { |
| 773 |
zestRootLayer.highlightNode(figure); |
| 774 |
} |
| 775 |
} |
| 776 |
|
| 777 |
/** |
| 778 |
* Moves the node off the node feedback layer |
| 779 |
* |
| 780 |
* @param node |
| 781 |
*/ |
| 782 |
void unhighlightNode(GraphContainer node) { |
| 783 |
IFigure figure = node.getNodeFigure(); |
| 784 |
if (figure != null && node.isHighlighted()) { |
| 785 |
zestRootLayer.unHighlightNode(figure); |
| 786 |
} |
| 787 |
} |
| 788 |
|
| 789 |
/** |
| 790 |
* Moves the node off the node feedback layer |
| 791 |
* |
| 792 |
* @param node |
| 793 |
*/ |
| 794 |
void unhighlightNode(GraphNode node) { |
| 795 |
IFigure figure = node.getNodeFigure(); |
| 796 |
if (figure != null && node.isHighlighted()) { |
| 797 |
zestRootLayer.unHighlightNode(figure); |
| 798 |
} |
| 799 |
} |
| 800 |
|
| 801 |
/** |
| 802 |
* Converts the list of GraphModelConnection objects into an array and |
879 |
* Converts the list of GraphModelConnection objects into an array and |
| 803 |
* returns it. |
880 |
* returns it. |
| 804 |
* |
881 |
* |
|
Lines 810-871
Link Here
|
| 810 |
return connsArray; |
887 |
return connsArray; |
| 811 |
} |
888 |
} |
| 812 |
|
889 |
|
| 813 |
LayoutRelationship[] getConnectionsToLayout(List nodesToLayout) { |
|
|
| 814 |
// @tag zest.bug.156528-Filters.follows : make sure not to layout |
| 815 |
// filtered connections, if the style says so. |
| 816 |
LayoutRelationship[] entities; |
| 817 |
if (ZestStyles.checkStyle(style, ZestStyles.IGNORE_INVISIBLE_LAYOUT)) { |
| 818 |
LinkedList connectionList = new LinkedList(); |
| 819 |
for (Iterator i = this.getConnections().iterator(); i.hasNext();) { |
| 820 |
GraphConnection next = (GraphConnection) i.next(); |
| 821 |
if (next.isVisible() && nodesToLayout.contains(next.getSource()) && nodesToLayout.contains(next.getDestination())) { |
| 822 |
connectionList.add(next.getLayoutRelationship()); |
| 823 |
} |
| 824 |
} |
| 825 |
entities = (LayoutRelationship[]) connectionList.toArray(new LayoutRelationship[] {}); |
| 826 |
} else { |
| 827 |
LinkedList nodeList = new LinkedList(); |
| 828 |
for (Iterator i = this.getConnections().iterator(); i.hasNext();) { |
| 829 |
GraphConnection next = (GraphConnection) i.next(); |
| 830 |
if (nodesToLayout.contains(next.getSource()) && nodesToLayout.contains(next.getDestination())) { |
| 831 |
nodeList.add(next.getLayoutRelationship()); |
| 832 |
} |
| 833 |
} |
| 834 |
entities = (LayoutRelationship[]) nodeList.toArray(new LayoutRelationship[] {}); |
| 835 |
} |
| 836 |
return entities; |
| 837 |
} |
| 838 |
|
| 839 |
LayoutEntity[] getNodesToLayout(List nodes) { |
| 840 |
// @tag zest.bug.156528-Filters.follows : make sure not to layout |
| 841 |
// filtered nodes, if the style says so. |
| 842 |
LayoutEntity[] entities; |
| 843 |
if (ZestStyles.checkStyle(style, ZestStyles.IGNORE_INVISIBLE_LAYOUT)) { |
| 844 |
LinkedList nodeList = new LinkedList(); |
| 845 |
for (Iterator i = nodes.iterator(); i.hasNext();) { |
| 846 |
GraphNode next = (GraphNode) i.next(); |
| 847 |
if (next.isVisible()) { |
| 848 |
nodeList.add(next.getLayoutEntity()); |
| 849 |
} |
| 850 |
} |
| 851 |
entities = (LayoutEntity[]) nodeList.toArray(new LayoutEntity[] {}); |
| 852 |
} else { |
| 853 |
LinkedList nodeList = new LinkedList(); |
| 854 |
for (Iterator i = nodes.iterator(); i.hasNext();) { |
| 855 |
GraphNode next = (GraphNode) i.next(); |
| 856 |
nodeList.add(next.getLayoutEntity()); |
| 857 |
} |
| 858 |
entities = (LayoutEntity[]) nodeList.toArray(new LayoutEntity[] {}); |
| 859 |
} |
| 860 |
return entities; |
| 861 |
} |
| 862 |
|
| 863 |
void removeConnection(GraphConnection connection) { |
890 |
void removeConnection(GraphConnection connection) { |
| 864 |
IFigure figure = connection.getConnectionFigure(); |
891 |
IFigure figure = connection.getConnectionFigure(); |
| 865 |
PolylineConnection sourceContainerConnectionFigure = connection.getSourceContainerConnectionFigure(); |
892 |
PolylineConnection sourceContainerConnectionFigure = connection |
| 866 |
PolylineConnection targetContainerConnectionFigure = connection.getTargetContainerConnectionFigure(); |
893 |
.getSourceContainerConnectionFigure(); |
|
|
894 |
PolylineConnection targetContainerConnectionFigure = connection |
| 895 |
.getTargetContainerConnectionFigure(); |
| 867 |
connection.removeFigure(); |
896 |
connection.removeFigure(); |
| 868 |
this.getConnections().remove(connection); |
897 |
this.getConnections().remove(connection); |
|
|
898 |
this.selectedItems.remove(connection); |
| 869 |
figure2ItemMap.remove(figure); |
899 |
figure2ItemMap.remove(figure); |
| 870 |
if (sourceContainerConnectionFigure != null) { |
900 |
if (sourceContainerConnectionFigure != null) { |
| 871 |
figure2ItemMap.remove(sourceContainerConnectionFigure); |
901 |
figure2ItemMap.remove(sourceContainerConnectionFigure); |
|
Lines 873-891
Link Here
|
| 873 |
if (targetContainerConnectionFigure != null) { |
903 |
if (targetContainerConnectionFigure != null) { |
| 874 |
figure2ItemMap.remove(targetContainerConnectionFigure); |
904 |
figure2ItemMap.remove(targetContainerConnectionFigure); |
| 875 |
} |
905 |
} |
|
|
906 |
getLayoutContext().fireConnectionRemovedEvent(connection.getLayout()); |
| 876 |
} |
907 |
} |
| 877 |
|
908 |
|
| 878 |
void removeNode(GraphNode node) { |
909 |
void removeNode(GraphNode node) { |
| 879 |
IFigure figure = node.getNodeFigure(); |
910 |
IFigure figure = node.getNodeFigure(); |
| 880 |
if (figure.getParent() != null) { |
911 |
if (figure.getParent() != null) { |
| 881 |
if (figure.getParent() instanceof ZestRootLayer) { |
912 |
figure.getParent().remove(figure); |
| 882 |
((ZestRootLayer) figure.getParent()).removeNode(figure); |
|
|
| 883 |
} else { |
| 884 |
figure.getParent().remove(figure); |
| 885 |
} |
| 886 |
} |
913 |
} |
| 887 |
this.getNodes().remove(node); |
914 |
this.getNodes().remove(node); |
|
|
915 |
this.selectedItems.remove(node); |
| 888 |
figure2ItemMap.remove(figure); |
916 |
figure2ItemMap.remove(figure); |
|
|
917 |
node.getLayout().dispose(); |
| 889 |
} |
918 |
} |
| 890 |
|
919 |
|
| 891 |
void addConnection(GraphConnection connection, boolean addToEdgeLayer) { |
920 |
void addConnection(GraphConnection connection, boolean addToEdgeLayer) { |
|
Lines 893-936
Link Here
|
| 893 |
if (addToEdgeLayer) { |
922 |
if (addToEdgeLayer) { |
| 894 |
zestRootLayer.addConnection(connection.getFigure()); |
923 |
zestRootLayer.addConnection(connection.getFigure()); |
| 895 |
} |
924 |
} |
|
|
925 |
getLayoutContext().fireConnectionAddedEvent(connection.getLayout()); |
| 896 |
} |
926 |
} |
| 897 |
|
927 |
|
| 898 |
/* |
928 |
/** |
| 899 |
public void redraw() { |
929 |
* @noreference This method is not intended to be referenced by clients. |
| 900 |
|
930 |
*/ |
| 901 |
Iterator iterator = this.getConnections().iterator(); |
931 |
public void addNode(GraphNode node) { |
| 902 |
while (iterator.hasNext()) { |
|
|
| 903 |
GraphConnection connection = (GraphConnection) iterator.next(); |
| 904 |
IFigure figure = connection.getFigure(); |
| 905 |
if (!zestRootLayer.getChildren().contains(figure)) { |
| 906 |
if (true || false || false) { |
| 907 |
zestRootLayer.addConnection(connection.getFigure()); |
| 908 |
} |
| 909 |
} |
| 910 |
} |
| 911 |
iterator = this.getNodes().iterator(); |
| 912 |
while (iterator.hasNext()) { |
| 913 |
GraphNode graphNode = (GraphNode) iterator.next(); |
| 914 |
IFigure figure = graphNode.getFigure(); |
| 915 |
if (!zestRootLayer.getChildren().contains(figure)) { |
| 916 |
zestRootLayer.addNode(graphNode.getFigure()); |
| 917 |
} |
| 918 |
} |
| 919 |
|
| 920 |
super.redraw(); |
| 921 |
|
| 922 |
} |
| 923 |
*/ |
| 924 |
|
| 925 |
void addNode(GraphNode node) { |
| 926 |
this.getNodes().add(node); |
932 |
this.getNodes().add(node); |
| 927 |
zestRootLayer.addNode(node.getFigure()); |
933 |
zestRootLayer.addNode(node.getFigure()); |
|
|
934 |
getLayoutContext().fireNodeAddedEvent(node.getLayout()); |
| 928 |
} |
935 |
} |
| 929 |
|
936 |
|
| 930 |
void addNode(GraphContainer graphContainer) { |
937 |
/** |
| 931 |
this.getNodes().add(graphContainer); |
938 |
* @noreference This method is not intended to be referenced by clients. |
| 932 |
zestRootLayer.addNode(graphContainer.getFigure()); |
939 |
*/ |
|
|
940 |
public void addSubgraphFigure(IFigure figure) { |
| 941 |
zestRootLayer.addSubgraph(figure); |
| 942 |
subgraphFigures.add(figure); |
| 943 |
} |
| 933 |
|
944 |
|
|
|
945 |
void removeSubgraphFigure(IFigure figure) { |
| 946 |
subgraphFigures.remove(figure); |
| 947 |
figure.getParent().remove(figure); |
| 934 |
} |
948 |
} |
| 935 |
|
949 |
|
| 936 |
void registerItem(GraphItem item) { |
950 |
void registerItem(GraphItem item) { |
|
Lines 941-1071
Link Here
|
| 941 |
IFigure figure = item.getFigure(); |
955 |
IFigure figure = item.getFigure(); |
| 942 |
figure2ItemMap.put(figure, item); |
956 |
figure2ItemMap.put(figure, item); |
| 943 |
if (((GraphConnection) item).getSourceContainerConnectionFigure() != null) { |
957 |
if (((GraphConnection) item).getSourceContainerConnectionFigure() != null) { |
| 944 |
figure2ItemMap.put(((GraphConnection) item).getSourceContainerConnectionFigure(), item); |
958 |
figure2ItemMap.put(((GraphConnection) item) |
|
|
959 |
.getSourceContainerConnectionFigure(), item); |
| 945 |
} |
960 |
} |
| 946 |
if (((GraphConnection) item).getTargetContainerConnectionFigure() != null) { |
961 |
if (((GraphConnection) item).getTargetContainerConnectionFigure() != null) { |
| 947 |
figure2ItemMap.put(((GraphConnection) item).getTargetContainerConnectionFigure(), item); |
962 |
figure2ItemMap.put(((GraphConnection) item) |
|
|
963 |
.getTargetContainerConnectionFigure(), item); |
| 948 |
} |
964 |
} |
| 949 |
} else if (item.getItemType() == GraphItem.CONTAINER) { |
965 |
} else if (item.getItemType() == GraphItem.CONTAINER) { |
| 950 |
IFigure figure = item.getFigure(); |
966 |
IFigure figure = item.getFigure(); |
| 951 |
figure2ItemMap.put(figure, item); |
967 |
figure2ItemMap.put(figure, item); |
| 952 |
} else { |
968 |
} else { |
| 953 |
throw new RuntimeException("Unknown item type: " + item.getItemType()); |
969 |
throw new RuntimeException("Unknown item type: " |
| 954 |
} |
970 |
+ item.getItemType()); |
| 955 |
} |
|
|
| 956 |
|
| 957 |
/* |
| 958 |
|
| 959 |
|
| 960 |
/** |
| 961 |
* Changes the figure for a particular node |
| 962 |
*/ |
| 963 |
void changeNodeFigure(IFigure oldValue, IFigure newFigure, GraphNode graphItem) { |
| 964 |
if (zestRootLayer.getChildren().contains(oldValue)) { |
| 965 |
zestRootLayer.remove(oldValue); |
| 966 |
figure2ItemMap.remove(oldValue); |
| 967 |
} |
| 968 |
figure2ItemMap.put(newFigure, graphItem); |
| 969 |
zestRootLayer.add(newFigure); |
| 970 |
} |
| 971 |
|
| 972 |
/** |
| 973 |
* Invoke all the constraint adapaters for this constraints |
| 974 |
* |
| 975 |
* @param object |
| 976 |
* @param constraint |
| 977 |
*/ |
| 978 |
void invokeConstraintAdapters(Object object, LayoutConstraint constraint) { |
| 979 |
if (constraintAdapters == null) { |
| 980 |
return; |
| 981 |
} |
971 |
} |
| 982 |
Iterator iterator = this.constraintAdapters.iterator(); |
|
|
| 983 |
while (iterator.hasNext()) { |
| 984 |
ConstraintAdapter constraintAdapter = (ConstraintAdapter) iterator.next(); |
| 985 |
constraintAdapter.populateConstraint(object, constraint); |
| 986 |
} |
| 987 |
} |
| 988 |
|
| 989 |
private void applyLayoutInternal() { |
| 990 |
|
| 991 |
if ((this.getNodes().size() == 0)) { |
| 992 |
return; |
| 993 |
} |
| 994 |
|
| 995 |
int layoutStyle = 0; |
| 996 |
|
| 997 |
if ((nodeStyle & ZestStyles.NODES_NO_LAYOUT_RESIZE) > 0) { |
| 998 |
layoutStyle = LayoutStyles.NO_LAYOUT_NODE_RESIZING; |
| 999 |
} |
| 1000 |
|
| 1001 |
if (layoutAlgorithm == null) { |
| 1002 |
layoutAlgorithm = new TreeLayoutAlgorithm(layoutStyle); |
| 1003 |
} |
| 1004 |
|
| 1005 |
layoutAlgorithm.setStyle(layoutAlgorithm.getStyle() | layoutStyle); |
| 1006 |
|
| 1007 |
// calculate the size for the layout algorithm |
| 1008 |
Dimension d = this.getViewport().getSize(); |
| 1009 |
d.width = d.width - 10; |
| 1010 |
d.height = d.height - 10; |
| 1011 |
|
| 1012 |
if (this.preferredSize.width >= 0) { |
| 1013 |
d.width = preferredSize.width; |
| 1014 |
} |
| 1015 |
if (this.preferredSize.height >= 0) { |
| 1016 |
d.height = preferredSize.height; |
| 1017 |
} |
| 1018 |
|
| 1019 |
if (d.isEmpty()) { |
| 1020 |
return; |
| 1021 |
} |
| 1022 |
LayoutRelationship[] connectionsToLayout = getConnectionsToLayout(nodes); |
| 1023 |
LayoutEntity[] nodesToLayout = getNodesToLayout(getNodes()); |
| 1024 |
|
| 1025 |
try { |
| 1026 |
Animation.markBegin(); |
| 1027 |
layoutAlgorithm.applyLayout(nodesToLayout, connectionsToLayout, 0, 0, d.width, d.height, false, false); |
| 1028 |
Animation.run(ANIMATION_TIME); |
| 1029 |
getLightweightSystem().getUpdateManager().performUpdate(); |
| 1030 |
|
| 1031 |
} catch (InvalidLayoutConfiguration e) { |
| 1032 |
e.printStackTrace(); |
| 1033 |
} |
| 1034 |
|
| 1035 |
} |
| 1036 |
|
| 1037 |
interface MyRunnable extends Runnable { |
| 1038 |
public boolean isVisible(); |
| 1039 |
} |
972 |
} |
| 1040 |
|
973 |
|
| 1041 |
/** |
974 |
/** |
| 1042 |
* Adds a reveal listener to the view. Note: A reveal listener will only |
975 |
* Schedules a layout to be performed after the view is revealed (or |
| 1043 |
* every be called ONCE!!! even if a view comes and goes. There is no remove |
976 |
* immediately, if the view is already revealed). |
| 1044 |
* reveal listener. This is used to defer some events until after the view |
|
|
| 1045 |
* is revealed. |
| 1046 |
* |
977 |
* |
| 1047 |
* @param revealListener |
978 |
* @param clean |
| 1048 |
*/ |
979 |
*/ |
| 1049 |
private void addRevealListener(final RevealListener revealListener) { |
980 |
private void scheduleLayoutOnReveal(final boolean clean) { |
| 1050 |
|
|
|
| 1051 |
MyRunnable myRunnable = new MyRunnable() { |
| 1052 |
boolean isVisible; |
| 1053 |
|
| 1054 |
public boolean isVisible() { |
| 1055 |
return this.isVisible; |
| 1056 |
} |
| 1057 |
|
981 |
|
|
|
982 |
final boolean[] isVisibleSync = new boolean[1]; |
| 983 |
Display.getDefault().syncExec(new Runnable() { |
| 1058 |
public void run() { |
984 |
public void run() { |
| 1059 |
isVisible = Graph.this.isVisible(); |
985 |
isVisibleSync[0] = isVisible(); |
| 1060 |
} |
986 |
} |
|
|
987 |
}); |
| 1061 |
|
988 |
|
| 1062 |
}; |
989 |
if (isVisibleSync[0]) { |
| 1063 |
Display.getDefault().syncExec(myRunnable); |
990 |
applyLayoutInternal(clean); |
| 1064 |
|
|
|
| 1065 |
if (myRunnable.isVisible()) { |
| 1066 |
revealListener.revealed(this); |
| 1067 |
} else { |
991 |
} else { |
| 1068 |
revealListeners.add(revealListener); |
992 |
shouldSheduleLayout = true; |
| 1069 |
} |
993 |
} |
| 1070 |
} |
994 |
} |
| 1071 |
|
995 |
|
|
Lines 1084-1101
Link Here
|
| 1084 |
|
1008 |
|
| 1085 |
zestRootLayer.addLayoutListener(LayoutAnimator.getDefault()); |
1009 |
zestRootLayer.addLayoutListener(LayoutAnimator.getDefault()); |
| 1086 |
fishEyeLayer.addLayoutListener(LayoutAnimator.getDefault()); |
1010 |
fishEyeLayer.addLayoutListener(LayoutAnimator.getDefault()); |
|
|
1011 |
|
| 1012 |
rootlayer.addCoordinateListener(new CoordinateListener() { |
| 1013 |
public void coordinateSystemChanged(IFigure source) { |
| 1014 |
if (preferredSize.width == -1 && preferredSize.height == -1) { |
| 1015 |
getLayoutContext().fireBoundsChangedEvent(); |
| 1016 |
} |
| 1017 |
} |
| 1018 |
}); |
| 1019 |
|
| 1087 |
return rootlayer; |
1020 |
return rootlayer; |
| 1088 |
} |
1021 |
} |
| 1089 |
|
1022 |
|
| 1090 |
/** |
1023 |
/** |
| 1091 |
* This removes the fisheye from the graph. It uses an animation to make the fisheye |
1024 |
* This removes the fisheye from the graph. It uses an animation to make the |
| 1092 |
* shrink, and then it finally clears the fisheye layer. This assumes that there |
1025 |
* fisheye shrink, and then it finally clears the fisheye layer. This |
| 1093 |
* is ever only 1 node on the fisheye layer at any time. |
1026 |
* assumes that there is ever only 1 node on the fisheye layer at any time. |
| 1094 |
* |
1027 |
* |
| 1095 |
* @param fishEyeFigure The fisheye figure |
1028 |
* @param fishEyeFigure |
| 1096 |
* @param regularFigure The regular figure (i.e. the non fisheye version) |
1029 |
* The fisheye figure |
|
|
1030 |
* @param regularFigure |
| 1031 |
* The regular figure (i.e. the non fisheye version) |
| 1097 |
*/ |
1032 |
*/ |
| 1098 |
void removeFishEye(final IFigure fishEyeFigure, final IFigure regularFigure, boolean animate) { |
1033 |
void removeFishEye(final IFigure fishEyeFigure, |
|
|
1034 |
final IFigure regularFigure, boolean animate) { |
| 1099 |
|
1035 |
|
| 1100 |
if (!fishEyeLayer.getChildren().contains(fishEyeFigure)) { |
1036 |
if (!fishEyeLayer.getChildren().contains(fishEyeFigure)) { |
| 1101 |
return; |
1037 |
return; |
|
Lines 1114-1130
Link Here
|
| 1114 |
|
1050 |
|
| 1115 |
fishEyeLayer.setConstraint(fishEyeFigure, bounds); |
1051 |
fishEyeLayer.setConstraint(fishEyeFigure, bounds); |
| 1116 |
|
1052 |
|
|
|
1053 |
for (Iterator iterator = fisheyeListeners.iterator(); iterator |
| 1054 |
.hasNext();) { |
| 1055 |
FisheyeListener listener = (FisheyeListener) iterator.next(); |
| 1056 |
listener.fisheyeRemoved(this, regularFigure, fishEyeFigure); |
| 1057 |
} |
| 1058 |
|
| 1117 |
if (animate) { |
1059 |
if (animate) { |
| 1118 |
Animation.run(FISHEYE_ANIMATION_TIME * 2); |
1060 |
Animation.run(FISHEYE_ANIMATION_TIME * 2); |
| 1119 |
} |
1061 |
} |
| 1120 |
this.getRootLayer().getUpdateManager().performUpdate(); |
1062 |
this.getRootLayer().getUpdateManager().performUpdate(); |
| 1121 |
fishEyeLayer.removeAll(); |
1063 |
fishEyeLayer.removeAll(); |
| 1122 |
this.fisheyedFigure = null; |
|
|
| 1123 |
|
1064 |
|
| 1124 |
} |
1065 |
} |
| 1125 |
|
1066 |
|
| 1126 |
/** |
1067 |
/** |
| 1127 |
* Replaces the old fisheye figure with a new one. |
1068 |
* Replaces the old fisheye figure with a new one. |
|
|
1069 |
* |
| 1128 |
* @param oldFigure |
1070 |
* @param oldFigure |
| 1129 |
* @param newFigure |
1071 |
* @param newFigure |
| 1130 |
*/ |
1072 |
*/ |
|
Lines 1132-1160
Link Here
|
| 1132 |
if (this.fishEyeLayer.getChildren().contains(oldFigure)) { |
1074 |
if (this.fishEyeLayer.getChildren().contains(oldFigure)) { |
| 1133 |
Rectangle bounds = oldFigure.getBounds(); |
1075 |
Rectangle bounds = oldFigure.getBounds(); |
| 1134 |
newFigure.setBounds(bounds); |
1076 |
newFigure.setBounds(bounds); |
| 1135 |
//this.fishEyeLayer.getChildren().remove(oldFigure); |
|
|
| 1136 |
this.fishEyeLayer.remove(oldFigure); |
1077 |
this.fishEyeLayer.remove(oldFigure); |
| 1137 |
this.fishEyeLayer.add(newFigure); |
1078 |
this.fishEyeLayer.add(newFigure); |
| 1138 |
//this.fishEyeLayer.getChildren().add(newFigure); |
1079 |
|
| 1139 |
//this.fishEyeLayer.invalidate(); |
1080 |
for (Iterator iterator = fisheyeListeners.iterator(); iterator |
| 1140 |
//this.fishEyeLayer.repaint(); |
1081 |
.hasNext();) { |
| 1141 |
this.fisheyedFigure = newFigure; |
1082 |
FisheyeListener listener = (FisheyeListener) iterator.next(); |
|
|
1083 |
listener.fisheyeReplaced(this, oldFigure, newFigure); |
| 1084 |
} |
| 1085 |
|
| 1142 |
return true; |
1086 |
return true; |
| 1143 |
} |
1087 |
} |
| 1144 |
return false; |
1088 |
return false; |
| 1145 |
} |
1089 |
} |
| 1146 |
|
1090 |
|
| 1147 |
/** |
1091 |
/** |
| 1148 |
* Add a fisheye version of the node. This works by animating the change from the original node |
1092 |
* Add a fisheye version of the node. This works by animating the change |
| 1149 |
* to the fisheyed one, and then placing the fisheye node on the fisheye layer. |
1093 |
* from the original node to the fisheyed one, and then placing the fisheye |
| 1150 |
* @param startFigure The original node |
1094 |
* node on the fisheye layer. |
| 1151 |
* @param endFigure The fisheye figure |
1095 |
* |
| 1152 |
* @param newBounds The final size of the fisheyed figure |
1096 |
* @param startFigure |
|
|
1097 |
* The original node |
| 1098 |
* @param endFigure |
| 1099 |
* The fisheye figure |
| 1100 |
* @param newBounds |
| 1101 |
* The final size of the fisheyed figure |
| 1153 |
*/ |
1102 |
*/ |
| 1154 |
void fishEye(IFigure startFigure, IFigure endFigure, Rectangle newBounds, boolean animate) { |
1103 |
void fishEye(IFigure startFigure, IFigure endFigure, Rectangle newBounds, |
|
|
1104 |
boolean animate) { |
| 1155 |
|
1105 |
|
| 1156 |
fishEyeLayer.removeAll(); |
1106 |
fishEyeLayer.removeAll(); |
| 1157 |
fisheyedFigure = null; |
1107 |
|
| 1158 |
if (animate) { |
1108 |
if (animate) { |
| 1159 |
Animation.markBegin(); |
1109 |
Animation.markBegin(); |
| 1160 |
} |
1110 |
} |
|
Lines 1167-1173
Link Here
|
| 1167 |
|
1117 |
|
| 1168 |
Rectangle bounds = startFigure.getBounds().getCopy(); |
1118 |
Rectangle bounds = startFigure.getBounds().getCopy(); |
| 1169 |
startFigure.translateToAbsolute(bounds); |
1119 |
startFigure.translateToAbsolute(bounds); |
| 1170 |
//startFigure.translateToRelative(bounds); |
1120 |
// startFigure.translateToRelative(bounds); |
| 1171 |
fishEyeLayer.translateToRelative(bounds); |
1121 |
fishEyeLayer.translateToRelative(bounds); |
| 1172 |
fishEyeLayer.translateFromParent(bounds); |
1122 |
fishEyeLayer.translateFromParent(bounds); |
| 1173 |
|
1123 |
|
|
Lines 1176-1190
Link Here
|
| 1176 |
fishEyeLayer.add(endFigure); |
1126 |
fishEyeLayer.add(endFigure); |
| 1177 |
fishEyeLayer.setConstraint(endFigure, newBounds); |
1127 |
fishEyeLayer.setConstraint(endFigure, newBounds); |
| 1178 |
|
1128 |
|
|
|
1129 |
for (Iterator iterator = fisheyeListeners.iterator(); iterator |
| 1130 |
.hasNext();) { |
| 1131 |
FisheyeListener listener = (FisheyeListener) iterator.next(); |
| 1132 |
listener.fisheyeAdded(this, startFigure, endFigure); |
| 1133 |
} |
| 1134 |
|
| 1179 |
if (animate) { |
1135 |
if (animate) { |
| 1180 |
Animation.run(FISHEYE_ANIMATION_TIME); |
1136 |
Animation.run(FISHEYE_ANIMATION_TIME); |
| 1181 |
} |
1137 |
} |
| 1182 |
this.getRootLayer().getUpdateManager().performUpdate(); |
1138 |
this.getRootLayer().getUpdateManager().performUpdate(); |
| 1183 |
} |
1139 |
} |
| 1184 |
|
1140 |
|
| 1185 |
public Graph getGraph() { |
1141 |
/** |
| 1186 |
// @tag refactor : Is this method really needed |
1142 |
* Adds a listener that will be notified when fisheyed figures change in |
| 1187 |
return this.getGraphModel(); |
1143 |
* this graph. |
|
|
1144 |
* |
| 1145 |
* @param listener |
| 1146 |
* listener to add |
| 1147 |
* @since 2.0 |
| 1148 |
*/ |
| 1149 |
public void addFisheyeListener(FisheyeListener listener) { |
| 1150 |
fisheyeListeners.add(listener); |
| 1151 |
} |
| 1152 |
|
| 1153 |
/** |
| 1154 |
* @since 2.0 |
| 1155 |
*/ |
| 1156 |
public void removeFisheyeListener(FisheyeListener listener) { |
| 1157 |
fisheyeListeners.remove(listener); |
| 1188 |
} |
1158 |
} |
| 1189 |
|
1159 |
|
| 1190 |
public int getItemType() { |
1160 |
public int getItemType() { |
|
Lines 1195-1198
Link Here
|
| 1195 |
return (GraphItem) figure2ItemMap.get(figure); |
1165 |
return (GraphItem) figure2ItemMap.get(figure); |
| 1196 |
} |
1166 |
} |
| 1197 |
|
1167 |
|
|
|
1168 |
/** |
| 1169 |
* @since 2.0 |
| 1170 |
*/ |
| 1171 |
public void setExpanded(GraphNode node, boolean expanded) { |
| 1172 |
layoutContext.setExpanded(node.getLayout(), expanded); |
| 1173 |
rootlayer.invalidate(); |
| 1174 |
} |
| 1175 |
|
| 1176 |
/** |
| 1177 |
* @since 2.0 |
| 1178 |
*/ |
| 1179 |
public boolean canExpand(GraphNode node) { |
| 1180 |
return layoutContext.canExpand(node.getLayout()); |
| 1181 |
} |
| 1182 |
|
| 1183 |
/** |
| 1184 |
* @since 2.0 |
| 1185 |
*/ |
| 1186 |
public boolean canCollapse(GraphNode node) { |
| 1187 |
return layoutContext.canCollapse(node.getLayout()); |
| 1188 |
} |
| 1189 |
|
| 1190 |
public Graph getGraph() { |
| 1191 |
return this; |
| 1192 |
} |
| 1193 |
|
| 1194 |
/** |
| 1195 |
* @since 2.0 |
| 1196 |
*/ |
| 1197 |
public Widget getItem() { |
| 1198 |
return this; |
| 1199 |
} |
| 1200 |
|
| 1201 |
/** |
| 1202 |
* @since 2.0 |
| 1203 |
*/ |
| 1204 |
public DisplayIndependentRectangle getLayoutBounds() { |
| 1205 |
Dimension preferredSize = this.getPreferredSize(); |
| 1206 |
return new DisplayIndependentRectangle(0, 0, preferredSize.width, |
| 1207 |
preferredSize.height); |
| 1208 |
} |
| 1198 |
} |
1209 |
} |