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