View | Details | Raw Unified | Return to bug 283179
Collapse All | Expand All

(-)src/org/eclipse/zest/core/viewers/internal/AbstractStructuredGraphViewer.java (-39 / +6 lines)
Lines 1-11 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC,
2
 * Copyright 2005-2009, CHISEL Group, University of Victoria, Victoria, BC,
3
 * Canada. All rights reserved. This program and the accompanying materials are
3
 * Canada. All rights reserved. This program and the accompanying materials are
4
 * made 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:
9
 *     The Chisel Group, University of Victoria
10
 *     Mateusz Matela <mateusz.matela@gmail.com> - Adapt Zest to changes in layout - https://bugs.eclipse.org/bugs/show_bug.cgi?id=283179
9
 ******************************************************************************/
11
 ******************************************************************************/
10
package org.eclipse.zest.core.viewers.internal;
12
package org.eclipse.zest.core.viewers.internal;
11
13
Lines 26-42 Link Here
26
import org.eclipse.zest.core.viewers.AbstractZoomableViewer;
28
import org.eclipse.zest.core.viewers.AbstractZoomableViewer;
27
import org.eclipse.zest.core.viewers.IGraphContentProvider;
29
import org.eclipse.zest.core.viewers.IGraphContentProvider;
28
import org.eclipse.zest.core.widgets.CGraphNode;
30
import org.eclipse.zest.core.widgets.CGraphNode;
29
import org.eclipse.zest.core.widgets.ConstraintAdapter;
30
import org.eclipse.zest.core.widgets.Graph;
31
import org.eclipse.zest.core.widgets.Graph;
31
import org.eclipse.zest.core.widgets.GraphConnection;
32
import org.eclipse.zest.core.widgets.GraphConnection;
32
import org.eclipse.zest.core.widgets.GraphContainer;
33
import org.eclipse.zest.core.widgets.GraphContainer;
33
import org.eclipse.zest.core.widgets.GraphItem;
34
import org.eclipse.zest.core.widgets.GraphItem;
34
import org.eclipse.zest.core.widgets.GraphNode;
35
import org.eclipse.zest.core.widgets.GraphNode;
35
import org.eclipse.zest.core.widgets.IContainer;
36
import org.eclipse.zest.core.widgets.ZestStyles;
36
import org.eclipse.zest.core.widgets.ZestStyles;
37
import org.eclipse.zest.layouts.LayoutAlgorithm;
37
import org.eclipse.zest.layouts.LayoutAlgorithm;
38
38
39
/*
39
/**
40
 * Abstraction of graph viewers to implement functionality used by all of them.
40
 * Abstraction of graph viewers to implement functionality used by all of them.
41
 * Not intended to be implemented by clients. Use one of the provided children
41
 * Not intended to be implemented by clients. Use one of the provided children
42
 * instead.
42
 * instead.
Lines 65-75 Link Here
65
	private HashMap connectionsMap = new HashMap();
65
	private HashMap connectionsMap = new HashMap();
66
66
67
	/**
67
	/**
68
	 * The constraint adatpers
69
	 */
70
	private List constraintAdapters = new ArrayList();
71
72
	/**
73
	 * A simple graph comparator that orders graph elements based on thier type
68
	 * A simple graph comparator that orders graph elements based on thier type
74
	 * (connection or node), and their unique object identification.
69
	 * (connection or node), and their unique object identification.
75
	 */
70
	 */
Lines 179-202 Link Here
179
	}
174
	}
180
175
181
	/**
176
	/**
182
	 * Adds a new constraint adapter to the list of constraints
183
	 * 
184
	 * @param constraintAdapter
185
	 */
186
	public void addConstraintAdapter(ConstraintAdapter constraintAdapter) {
187
		this.constraintAdapters.add(constraintAdapter);
188
	}
189
190
	/**
191
	 * Gets all the constraint adapters currently on the viewer
192
	 * 
193
	 * @return
194
	 */
195
	public List getConstraintAdapters() {
196
		return this.constraintAdapters;
197
	}
198
199
	/**
200
	 * Sets the layout algorithm for this viewer. Subclasses may place
177
	 * Sets the layout algorithm for this viewer. Subclasses may place
201
	 * restrictions on the algorithms that it accepts.
178
	 * restrictions on the algorithms that it accepts.
202
	 * 
179
	 * 
Lines 246-252 Link Here
246
		return node;
223
		return node;
247
	}
224
	}
248
225
249
	GraphNode addGraphModelNode(IContainer container, Object element) {
226
	GraphNode addGraphModelNode(GraphContainer container, Object element) {
250
		GraphNode node = this.getGraphModelNode(element);
227
		GraphNode node = this.getGraphModelNode(element);
251
		if (node == null) {
228
		if (node == null) {
252
			node = new GraphNode(container, SWT.NONE);
229
			node = new GraphNode(container, SWT.NONE);
Lines 646-655 Link Here
646
		GraphConnection relationship = (GraphConnection) connectionsMap.get(connection);
623
		GraphConnection relationship = (GraphConnection) connectionsMap.get(connection);
647
624
648
		if (relationship != null) {
625
		if (relationship != null) {
649
			// remove the relationship from the layout algorithm
650
			if (getLayoutAlgorithm() != null) {
651
				getLayoutAlgorithm().removeRelationship(relationship.getLayoutRelationship());
652
			}
653
			// remove the relationship from the model
626
			// remove the relationship from the model
654
			relationship.dispose();
627
			relationship.dispose();
655
		}
628
		}
Lines 679-690 Link Here
679
		GraphNode node = (GraphNode) nodesMap.get(element);
652
		GraphNode node = (GraphNode) nodesMap.get(element);
680
653
681
		if (node != null) {
654
		if (node != null) {
682
			// remove the node from the layout algorithm and all the connections
683
			if (getLayoutAlgorithm() != null) {
684
				getLayoutAlgorithm().removeEntity(node.getLayoutEntity());
685
				getLayoutAlgorithm().removeRelationships(node.getSourceConnections());
686
				getLayoutAlgorithm().removeRelationships(node.getTargetConnections());
687
			}
688
			// remove the node and it's connections from the model
655
			// remove the node and it's connections from the model
689
			node.dispose();
656
			node.dispose();
690
		}
657
		}
(-)src/org/eclipse/zest/core/viewers/internal/AbstractStylingModelFactory.java (-16 / +8 lines)
Lines 1-15 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC,
2
 * Copyright 2005-2009, CHISEL Group, University of Victoria, Victoria, BC,
3
 * Canada. All rights reserved. This program and the accompanying materials are
3
 * Canada. All rights reserved. This program and the accompanying materials are
4
 * made 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:
9
 *     The Chisel Group, University of Victoria
10
 *     Mateusz Matela <mateusz.matela@gmail.com> - Adapt Zest to changes in layout - https://bugs.eclipse.org/bugs/show_bug.cgi?id=283179
9
 ******************************************************************************/
11
 ******************************************************************************/
10
package org.eclipse.zest.core.viewers.internal;
12
package org.eclipse.zest.core.viewers.internal;
11
13
12
import java.util.ArrayList;
13
import java.util.HashMap;
14
import java.util.HashMap;
14
import java.util.Iterator;
15
import java.util.Iterator;
15
import java.util.LinkedList;
16
import java.util.LinkedList;
Lines 26-36 Link Here
26
import org.eclipse.zest.core.viewers.INestedContentProvider;
27
import org.eclipse.zest.core.viewers.INestedContentProvider;
27
import org.eclipse.zest.core.widgets.Graph;
28
import org.eclipse.zest.core.widgets.Graph;
28
import org.eclipse.zest.core.widgets.GraphConnection;
29
import org.eclipse.zest.core.widgets.GraphConnection;
30
import org.eclipse.zest.core.widgets.GraphContainer;
29
import org.eclipse.zest.core.widgets.GraphItem;
31
import org.eclipse.zest.core.widgets.GraphItem;
30
import org.eclipse.zest.core.widgets.GraphNode;
32
import org.eclipse.zest.core.widgets.GraphNode;
31
import org.eclipse.zest.core.widgets.IContainer;
32
33
33
/*
34
/**
34
 * Base class that can be used for model factories. Offers facilities to style
35
 * Base class that can be used for model factories. Offers facilities to style
35
 * the items that have been created by the factory.
36
 * the items that have been created by the factory.
36
 * 
37
 * 
Lines 42-48 Link Here
42
	private AbstractStructuredGraphViewer viewer;
43
	private AbstractStructuredGraphViewer viewer;
43
	private int connectionStyle;
44
	private int connectionStyle;
44
	private int nodeStyle;
45
	private int nodeStyle;
45
	private List /* ConstraintAdapater */constraintAdapters = new ArrayList();
46
46
47
	/**
47
	/**
48
	 * 
48
	 * 
Lines 51-59 Link Here
51
		this.viewer = viewer;
51
		this.viewer = viewer;
52
		this.connectionStyle = SWT.NONE;
52
		this.connectionStyle = SWT.NONE;
53
		this.nodeStyle = SWT.NONE;
53
		this.nodeStyle = SWT.NONE;
54
		if (viewer instanceof AbstractStructuredGraphViewer) {
55
			this.constraintAdapters = (viewer).getConstraintAdapters();
56
		}
57
	}
54
	}
58
55
59
	public void styleConnection(GraphConnection conn) {
56
	public void styleConnection(GraphConnection conn) {
Lines 208-217 Link Here
208
					return node;
205
					return node;
209
				}
206
				}
210
				for (int i = 0; i < childNodes.length; i++) {
207
				for (int i = 0; i < childNodes.length; i++) {
211
					GraphNode childNode = viewer.addGraphModelNode((IContainer) node, childNodes[i]);
208
					GraphNode childNode = viewer.addGraphModelNode((GraphContainer) node, childNodes[i]);
212
					styleItem(childNode);
209
					styleItem(childNode);
213
				}
210
				}
214
				((IContainer) node).applyLayout();
211
				((GraphContainer) node).applyLayout();
215
				return node;
212
				return node;
216
			}
213
			}
217
		}
214
		}
Lines 243-252 Link Here
243
		this.nodeStyle = style;
240
		this.nodeStyle = style;
244
	}
241
	}
245
242
246
	public List /* ConstraintAdapter */getConstraintAdapters() {
247
		return this.constraintAdapters;
248
	}
249
250
	/**
243
	/**
251
	 * @return the nodeStyle
244
	 * @return the nodeStyle
252
	 */
245
	 */
Lines 345-351 Link Here
345
		clearGraph(model);
338
		clearGraph(model);
346
		model.setConnectionStyle(getConnectionStyle());
339
		model.setConnectionStyle(getConnectionStyle());
347
		model.setNodeStyle(getNodeStyle());
340
		model.setNodeStyle(getNodeStyle());
348
		model.setConstraintAdapters(getConstraintAdapters());
349
	}
341
	}
350
342
351
	/**
343
	/**
(-)src/org/eclipse/zest/core/widgets/GraphNode.java (-282 / +88 lines)
Lines 1-12 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:
9
 *     The Chisel Group, University of Victoria
10
 *     Mateusz Matela <mateusz.matela@gmail.com> - Adapt Zest to changes in layout - https://bugs.eclipse.org/bugs/show_bug.cgi?id=283179
9
 ******************************************************************************/
11
 ******************************************************************************/
12
10
package org.eclipse.zest.core.widgets;
13
package org.eclipse.zest.core.widgets;
11
14
12
import java.util.ArrayList;
15
import java.util.ArrayList;
Lines 21-37 Link Here
21
import org.eclipse.draw2d.geometry.Point;
24
import org.eclipse.draw2d.geometry.Point;
22
import org.eclipse.draw2d.geometry.PrecisionPoint;
25
import org.eclipse.draw2d.geometry.PrecisionPoint;
23
import org.eclipse.draw2d.geometry.Rectangle;
26
import org.eclipse.draw2d.geometry.Rectangle;
24
import org.eclipse.swt.SWT;
25
import org.eclipse.swt.graphics.Color;
27
import org.eclipse.swt.graphics.Color;
26
import org.eclipse.swt.graphics.Font;
28
import org.eclipse.swt.graphics.Font;
27
import org.eclipse.swt.graphics.FontData;
28
import org.eclipse.swt.graphics.Image;
29
import org.eclipse.swt.graphics.Image;
29
import org.eclipse.swt.widgets.Display;
30
import org.eclipse.swt.widgets.Display;
31
import org.eclipse.zest.core.widgets.ZestStyles;
30
import org.eclipse.zest.core.widgets.internal.GraphLabel;
32
import org.eclipse.zest.core.widgets.internal.GraphLabel;
31
import org.eclipse.zest.layouts.LayoutEntity;
32
import org.eclipse.zest.layouts.constraints.LayoutConstraint;
33
33
34
/*
34
/**
35
 * Simple node class which has the following properties: color, size, location,
35
 * Simple node class which has the following properties: color, size, location,
36
 * and a label. It also has a list of connections and anchors.
36
 * and a label. It also has a list of connections and anchors.
37
 * 
37
 * 
Lines 44-51 Link Here
44
public class GraphNode extends GraphItem {
44
public class GraphNode extends GraphItem {
45
	public static final int HIGHLIGHT_NONE = 0;
45
	public static final int HIGHLIGHT_NONE = 0;
46
	public static final int HIGHLIGHT_ON = 1;
46
	public static final int HIGHLIGHT_ON = 1;
47
	// @tag ADJACENT : Removed highlight adjacent
48
	//public static final int HIGHLIGHT_ADJACENT = 2;
49
47
50
	private int nodeStyle;
48
	private int nodeStyle;
51
49
Lines 55-62 Link Here
55
	private Color foreColor;
53
	private Color foreColor;
56
	private Color backColor;
54
	private Color backColor;
57
	private Color highlightColor;
55
	private Color highlightColor;
58
	// @tag ADJACENT : Removed highlight adjacent
59
	//private Color highlightAdjacentColor;
60
	private Color borderColor;
56
	private Color borderColor;
61
	private Color borderHighlightColor;
57
	private Color borderHighlightColor;
62
	private int borderWidth;
58
	private int borderWidth;
Lines 65-74 Link Here
65
	private Font font;
61
	private Font font;
66
	private boolean cacheLabel;
62
	private boolean cacheLabel;
67
	private boolean visible = true;
63
	private boolean visible = true;
68
	private LayoutEntity layoutEntity;
69
64
70
	protected Graph graph;
65
	protected Graph graph;
71
	protected IContainer parent;
66
	protected NodeContainerAdapter parent;
72
67
73
	/** The internal node. */
68
	/** The internal node. */
74
	protected Object internalNode;
69
	protected Object internalNode;
Lines 80-120 Link Here
80
	private boolean isDisposed = false;
75
	private boolean isDisposed = false;
81
	private boolean hasCustomTooltip;
76
	private boolean hasCustomTooltip;
82
77
83
	public GraphNode(IContainer graphModel, int style) {
78
	public GraphNode(Graph graphModel, int style) {
79
		this(graphModel, style, null);
80
	}
81
82
	public GraphNode(Graph graphModel, int style, Object data) {
83
		this(graphModel, style, "" /* text */, null /* image */, data);
84
	}
85
86
	public GraphNode(Graph graphModel, int style, String text) {
87
		this(graphModel, style, text, null);
88
	}
89
90
	public GraphNode(Graph graphModel, int style, String text, Object data) {
91
		this(graphModel, style, text, null /* image */, data);
92
	}
93
94
	public GraphNode(Graph graphModel, int style, String text, Image image) {
95
		this(graphModel, style, text, image, null);
96
	}
97
98
	public GraphNode(Graph graphModel, int style, String text, Image image, Object data) {
99
		this(NodeContainerAdapter.get(graphModel), style, text, image, data);
100
	}
101
102
	public GraphNode(GraphContainer graphModel, int style) {
84
		this(graphModel, style, null);
103
		this(graphModel, style, null);
85
	}
104
	}
86
105
87
	public GraphNode(IContainer graphModel, int style, Object data) {
106
	public GraphNode(GraphContainer graphModel, int style, Object data) {
88
		this(graphModel.getGraph(), style, "" /*text*/, null /*image*/, data);
107
		this(graphModel, style, "" /* text */, null /* image */, data);
89
	}
108
	}
90
109
91
	public GraphNode(IContainer graphModel, int style, String text) {
110
	public GraphNode(GraphContainer graphModel, int style, String text) {
92
		this(graphModel, style, text, null);
111
		this(graphModel, style, text, null);
93
	}
112
	}
94
113
95
	public GraphNode(IContainer graphModel, int style, String text, Object data) {
114
	public GraphNode(GraphContainer graphModel, int style, String text, Object data) {
96
		this(graphModel.getGraph(), style, text, null /*image*/, data);
115
		this(graphModel, style, text, null /* image */, data);
97
	}
116
	}
98
117
99
	public GraphNode(IContainer graphModel, int style, String text, Image image) {
118
	public GraphNode(GraphContainer graphModel, int style, String text, Image image) {
100
		this(graphModel, style, text, image, null);
119
		this(graphModel, style, text, image, null);
101
	}
120
	}
102
121
103
	public GraphNode(IContainer graphModel, int style, String text, Image image, Object data) {
122
	public GraphNode(GraphContainer graphModel, int style, String text, Image image, Object data) {
123
		this(NodeContainerAdapter.get(graphModel), style, text, image, data);
124
	}
125
126
	private GraphNode(NodeContainerAdapter graphModel, int style, String text, Image image, Object data) {
104
		super(graphModel.getGraph(), style, data);
127
		super(graphModel.getGraph(), style, data);
105
		initModel(graphModel, text, image);
128
		initModel(graphModel, text, image);
106
		if (nodeFigure == null) {
129
		if (nodeFigure == null) {
107
			initFigure();
130
			initFigure();
108
		}
131
		}
109
132
110
		// This is a hack because JAVA sucks!
133
		this.parent.addNode(this);
111
		// I don't want to expose addNode so I can't put it in the
112
		// IContainer interface.  
113
		if (this.parent.getItemType() == GRAPH) {
114
			((Graph) this.parent).addNode(this);
115
		} else if (this.parent.getItemType() == CONTAINER) {
116
			((GraphContainer) this.parent).addNode(this);
117
		}
118
		this.parent.getGraph().registerItem(this);
134
		this.parent.getGraph().registerItem(this);
119
	}
135
	}
120
136
Lines 124-150 Link Here
124
140
125
	static int count = 0;
141
	static int count = 0;
126
142
127
	protected void initModel(IContainer parent, String text, Image image) {
143
	protected void initModel(NodeContainerAdapter graphModel, String text, Image image) {
128
		this.nodeStyle |= parent.getGraph().getNodeStyle();
144
		this.nodeStyle |= graphModel.getGraph().getNodeStyle();
129
		this.parent = parent;
145
		this.parent = graphModel;
130
		this.sourceConnections = new ArrayList();
146
		this.sourceConnections = new ArrayList();
131
		this.targetConnections = new ArrayList();
147
		this.targetConnections = new ArrayList();
132
		this.foreColor = parent.getGraph().DARK_BLUE;
148
		this.foreColor = graphModel.getGraph().DARK_BLUE;
133
		this.backColor = parent.getGraph().LIGHT_BLUE;
149
		this.backColor = graphModel.getGraph().LIGHT_BLUE;
134
		this.highlightColor = parent.getGraph().HIGHLIGHT_COLOR;
150
		this.highlightColor = graphModel.getGraph().HIGHLIGHT_COLOR;
135
		// @tag ADJACENT : Removed highlight adjacent
136
		//this.highlightAdjacentColor = ColorConstants.orange;
137
		this.nodeStyle = SWT.NONE;
138
		this.borderColor = ColorConstants.lightGray;
151
		this.borderColor = ColorConstants.lightGray;
139
		this.borderHighlightColor = ColorConstants.blue;
152
		this.borderHighlightColor = ColorConstants.blue;
140
		this.borderWidth = 1;
153
		this.borderWidth = 1;
141
		this.currentLocation = new PrecisionPoint(0, 0);
154
		this.currentLocation = new PrecisionPoint(0, 0);
142
		this.size = new Dimension(-1, -1);
155
		this.size = new Dimension(-1, -1);
143
		this.font = Display.getDefault().getSystemFont();
156
		this.font = Display.getDefault().getSystemFont();
144
		this.graph = parent.getGraph();
157
		this.graph = graphModel.getGraph();
145
		this.cacheLabel = false;
158
		this.cacheLabel = false;
146
		this.setText(text);
159
		this.setText(text);
147
		this.layoutEntity = new LayoutGraphNode();
148
		if (image != null) {
160
		if (image != null) {
149
			this.setImage(image);
161
			this.setImage(image);
150
		}
162
		}
Lines 162-171 Link Here
162
		return "GraphModelNode: " + getText();
174
		return "GraphModelNode: " + getText();
163
	}
175
	}
164
176
165
	public LayoutEntity getLayoutEntity() {
166
		return layoutEntity;
167
	}
168
169
	/*
177
	/*
170
	 * (non-Javadoc)
178
	 * (non-Javadoc)
171
	 * 
179
	 * 
Lines 266-274 Link Here
266
	 * Sets the current location for this node.
274
	 * Sets the current location for this node.
267
	 */
275
	 */
268
	public void setLocation(double x, double y) {
276
	public void setLocation(double x, double y) {
269
		currentLocation.x = (int) x;
277
		if (currentLocation.x != x || currentLocation.y != y) {
270
		currentLocation.y = (int) y;
278
			currentLocation.x = (int) x;
271
		refreshLocation();
279
			currentLocation.y = (int) y;
280
			refreshLocation();
281
		}
272
	}
282
	}
273
283
274
	/**
284
	/**
Lines 374-401 Link Here
374
	}
384
	}
375
385
376
	/**
386
	/**
377
	 * Get the highlight adjacent colour for this node. This is the colour that
378
	 * adjacent nodes will get
379
	 */
380
	// @tag ADJACENT : Removed highlight adjacent
381
	/*
382
	public Color getHighlightAdjacentColor() {
383
		return highlightAdjacentColor;
384
	}
385
	*/
386
387
	/**
388
	 * Set the highlight adjacent colour for this node. This is the colour that
389
	 * adjacent node will get.
390
	 */
391
	// @tag ADJACENT : Removed highlight adjacent
392
	/*
393
	public void setHighlightAdjacentColor(Color c) {
394
		this.highlightAdjacentColor = c;
395
	}
396
	*/
397
398
	/**
399
	 * Highlights the node changing the background color and border color. The
387
	 * Highlights the node changing the background color and border color. The
400
	 * source and destination connections are also highlighted, and the adjacent
388
	 * source and destination connections are also highlighted, and the adjacent
401
	 * nodes are highlighted too in a different color.
389
	 * nodes are highlighted too in a different color.
Lines 404-429 Link Here
404
		if (highlighted == HIGHLIGHT_ON) {
392
		if (highlighted == HIGHLIGHT_ON) {
405
			return;
393
			return;
406
		}
394
		}
407
		// @tag ADJACENT : Removed highlight adjacent
395
		parent.highlightNode(this);
408
		/*
409
		if (ZestStyles.checkStyle(getNodeStyle(), ZestStyles.NODES_HIGHLIGHT_ADJACENT)) {
410
			for (Iterator iter = sourceConnections.iterator(); iter.hasNext();) {
411
				GraphConnection conn = (GraphConnection) iter.next();
412
				conn.highlight();
413
				conn.getDestination().highlightAdjacent();
414
			}
415
			for (Iterator iter = targetConnections.iterator(); iter.hasNext();) {
416
				GraphConnection conn = (GraphConnection) iter.next();
417
				conn.highlight();
418
				conn.getSource().highlightAdjacent();
419
			}
420
		}
421
		*/
422
		if (parent.getItemType() == GraphItem.CONTAINER) {
423
			((GraphContainer) parent).highlightNode(this);
424
		} else {
425
			((Graph) parent).highlightNode(this);
426
		}
427
		highlighted = HIGHLIGHT_ON;
396
		highlighted = HIGHLIGHT_ON;
428
		updateFigureForModel(getNodeFigure());
397
		updateFigureForModel(getNodeFigure());
429
	}
398
	}
Lines 433-472 Link Here
433
	 */
402
	 */
434
	public void unhighlight() {
403
	public void unhighlight() {
435
404
436
		// @tag ADJACENT : Removed highlight adjacent
437
		//boolean highlightedAdjacently = (highlighted == HIGHLIGHT_ADJACENT);
438
		if (highlighted == HIGHLIGHT_NONE) {
405
		if (highlighted == HIGHLIGHT_NONE) {
439
			return;
406
			return;
440
		}
407
		}
441
		// @tag ADJACENT : Removed highlight adjacent
408
442
		/*
409
		parent.unhighlightNode(this);
443
		if (!highlightedAdjacently) {
410
444
			// IF we are highlighted as an adjacent node, we don't need to deal
445
			// with our connections.
446
			if (ZestStyles.checkStyle(getNodeStyle(), ZestStyles.NODES_HIGHLIGHT_ADJACENT)) {
447
				// unhighlight the adjacent edges
448
				for (Iterator iter = sourceConnections.iterator(); iter.hasNext();) {
449
					GraphConnection conn = (GraphConnection) iter.next();
450
					conn.unhighlight();
451
					if (conn.getDestination() != this) {
452
						conn.getDestination().unhighlight();
453
					}
454
				}
455
				for (Iterator iter = targetConnections.iterator(); iter.hasNext();) {
456
					GraphConnection conn = (GraphConnection) iter.next();
457
					conn.unhighlight();
458
					if (conn.getSource() != this) {
459
						conn.getSource().unhighlight();
460
					}
461
				}
462
			}
463
		}
464
		*/
465
		if (parent.getItemType() == GraphItem.CONTAINER) {
466
			((GraphContainer) parent).unhighlightNode(this);
467
		} else {
468
			((Graph) parent).unhighlightNode(this);
469
		}
470
		highlighted = HIGHLIGHT_NONE;
411
		highlighted = HIGHLIGHT_NONE;
471
		updateFigureForModel(nodeFigure);
412
		updateFigureForModel(nodeFigure);
472
413
Lines 480-544 Link Here
480
		if (nodeFigure == null || nodeFigure.getParent() == null) {
421
		if (nodeFigure == null || nodeFigure.getParent() == null) {
481
			return; // node figure has not been created yet
422
			return; // node figure has not been created yet
482
		}
423
		}
483
		//nodeFigure.setBounds(bounds);
484
		nodeFigure.getParent().setConstraint(nodeFigure, bounds);
424
		nodeFigure.getParent().setConstraint(nodeFigure, bounds);
485
	}
425
	}
486
426
487
	/**
488
	 * Highlights this node using the adjacent highlight color. This only does
489
	 * something if highlighAdjacentNodes is set to true and if the node isn't
490
	 * already highlighted.
491
	 * 
492
	 * @see #setHighlightAdjacentNodes(boolean)
493
	 */
494
	// @tag ADJACENT : removed highlight adjacent
495
	/*
496
	public void highlightAdjacent() {
497
		if (highlighted > 0) {
498
			return;
499
		}
500
		highlighted = HIGHLIGHT_ADJACENT;
501
		updateFigureForModel(nodeFigure);
502
		if (parent.getItemType() == GraphItem.CONTAINER) {
503
			((GraphContainer) parent).highlightNode(this);
504
		} else {
505
			((Graph) parent).highlightNode(this);
506
		}
507
	}
508
	*/
509
510
	/**
511
	 * Returns if the nodes adjacent to this node will be highlighted when this
512
	 * node is selected.
513
	 * 
514
	 * @return GraphModelNode
515
	 */
516
	// @tag ADJACENT : Removed highlight adjacent
517
	/*
518
	public boolean isHighlightAdjacentNodes() {
519
		return ZestStyles.checkStyle(nodeStyle, ZestStyles.NODES_HIGHLIGHT_ADJACENT);
520
	}
521
	*/
522
523
	/**
524
	 * Sets if the adjacent nodes to this one should be highlighted when this
525
	 * node is selected.
526
	 * 
527
	 * @param highlightAdjacentNodes
528
	 *            The highlightAdjacentNodes to set.
529
	 */
530
	// @tag ADJACENT : Removed highlight adjacent
531
	/*
532
	public void setHighlightAdjacentNodes(boolean highlightAdjacentNodes) {
533
		if (!highlightAdjacentNodes) {
534
			this.nodeStyle |= ZestStyles.NODES_HIGHLIGHT_ADJACENT;
535
			this.nodeStyle ^= ZestStyles.NODES_HIGHLIGHT_ADJACENT;
536
			return;
537
		}
538
		this.nodeStyle |= ZestStyles.NODES_HIGHLIGHT_ADJACENT;
539
	}
540
	*/
541
542
	public Color getBorderColor() {
427
	public Color getBorderColor() {
543
		return borderColor;
428
		return borderColor;
544
	}
429
	}
Lines 645-671 Link Here
645
		this.cacheLabel = cacheLabel;
530
		this.cacheLabel = cacheLabel;
646
	}
531
	}
647
532
648
	public IFigure getNodeFigure() {
533
	IFigure getNodeFigure() {
649
		return this.nodeFigure;
534
		return this.nodeFigure;
650
	}
535
	}
651
536
652
	public void setVisible(boolean visible) {
537
	public void setVisible(boolean visible) {
653
		// graph.addRemoveFigure(this, visible);
654
		this.visible = visible;
538
		this.visible = visible;
655
		this.getFigure().setVisible(visible);
539
		this.getFigure().setVisible(visible);
656
		List sConnections = (this).getSourceConnections();
540
		for (Iterator iterator2 = sourceConnections.iterator(); iterator2.hasNext();) {
657
		List tConnections = (this).getTargetConnections();
658
		for (Iterator iterator2 = sConnections.iterator(); iterator2.hasNext();) {
659
			GraphConnection connection = (GraphConnection) iterator2.next();
541
			GraphConnection connection = (GraphConnection) iterator2.next();
660
			connection.setVisible(visible);
542
			connection.setVisible(visible);
661
		}
543
		}
662
544
663
		for (Iterator iterator2 = tConnections.iterator(); iterator2.hasNext();) {
545
		for (Iterator iterator2 = targetConnections.iterator(); iterator2.hasNext();) {
664
			GraphConnection connection = (GraphConnection) iterator2.next();
546
			GraphConnection connection = (GraphConnection) iterator2.next();
665
			connection.setVisible(visible);
547
			connection.setVisible(visible);
666
		}
548
		}
667
	}
549
	}
668
550
551
	public boolean isVisible() {
552
		return visible;
553
	}
554
669
	public int getStyle() {
555
	public int getStyle() {
670
		return super.getStyle() | this.getNodeStyle();
556
		return super.getStyle() | this.getNodeStyle();
671
	}
557
	}
Lines 675-681 Link Here
675
	 **************************************************************************/
561
	 **************************************************************************/
676
562
677
	private IFigure fishEyeFigure = null;
563
	private IFigure fishEyeFigure = null;
678
	private Font fishEyeFont = null;
679
	private boolean isFisheyeEnabled;
564
	private boolean isFisheyeEnabled;
680
565
681
	protected IFigure fishEye(boolean enable, boolean animate) {
566
	protected IFigure fishEye(boolean enable, boolean animate) {
Lines 699-706 Link Here
699
			Dimension newSize = fishEyeFigure.getPreferredSize();
584
			Dimension newSize = fishEyeFigure.getPreferredSize();
700
			Rectangle currentSize = rectangle.getCopy();
585
			Rectangle currentSize = rectangle.getCopy();
701
			nodeFigure.translateToAbsolute(currentSize);
586
			nodeFigure.translateToAbsolute(currentSize);
702
			int expandedH = (newSize.height - currentSize.height) / 2 + 1;
587
			int expandedH = Math.max((newSize.height - currentSize.height) / 2 + 1, 0);
703
			int expandedW = (newSize.width - currentSize.width) / 2 + 1;
588
			int expandedW = Math.max((newSize.width - currentSize.width) / 2 + 1, 0);
704
			Dimension expandAmount = new Dimension(expandedW, expandedH);
589
			Dimension expandAmount = new Dimension(expandedW, expandedH);
705
			nodeFigure.translateToAbsolute(rectangle);
590
			nodeFigure.translateToAbsolute(rectangle);
706
			rectangle.expand(new Insets(expandAmount.height, expandAmount.width, expandAmount.height, expandAmount.width));
591
			rectangle.expand(new Insets(expandAmount.height, expandAmount.width, expandAmount.height, expandAmount.width));
Lines 708-718 Link Here
708
				return null;
593
				return null;
709
			}
594
			}
710
595
711
			FontData fontData = Display.getCurrent().getSystemFont().getFontData()[0];
712
			fontData.height = 12;
713
			fishEyeFont = new Font(Display.getCurrent(), fontData);
714
			fishEyeFigure.setFont(fishEyeFont);
715
716
			//Add the fisheye
596
			//Add the fisheye
717
			this.getGraphModel().fishEye(nodeFigure, fishEyeFigure, rectangle, true);
597
			this.getGraphModel().fishEye(nodeFigure, fishEyeFigure, rectangle, true);
718
			if (fishEyeFigure != null) {
598
			if (fishEyeFigure != null) {
Lines 723-738 Link Here
723
		} else {
603
		} else {
724
			// Remove the fisheye and dispose the font
604
			// Remove the fisheye and dispose the font
725
			this.getGraphModel().removeFishEye(fishEyeFigure, nodeFigure, animate);
605
			this.getGraphModel().removeFishEye(fishEyeFigure, nodeFigure, animate);
726
			if (fishEyeFont != null) {
727
				this.fishEyeFont.dispose();
728
				this.fishEyeFont = null;
729
			}
730
			isFisheyeEnabled = false;
606
			isFisheyeEnabled = false;
731
			return null;
607
			return null;
732
		}
608
		}
733
	}
609
	}
734
610
735
	IContainer getParent() {
611
	NodeContainerAdapter getParent() {
736
		return parent;
612
		return parent;
737
	}
613
	}
738
614
Lines 740-749 Link Here
740
		return highlighted > 0;
616
		return highlighted > 0;
741
	}
617
	}
742
618
743
	void invokeLayoutListeners(LayoutConstraint constraint) {
744
		graph.invokeConstraintAdapters(this, constraint);
745
	}
746
747
	protected void updateFigureForModel(IFigure currentFigure) {
619
	protected void updateFigureForModel(IFigure currentFigure) {
748
		if (currentFigure == null) {
620
		if (currentFigure == null) {
749
			return;
621
			return;
Lines 810-836 Link Here
810
		boolean cacheLabel = this.cacheLabel();
682
		boolean cacheLabel = this.cacheLabel();
811
		GraphLabel label = new GraphLabel(node.getText(), node.getImage(), cacheLabel);
683
		GraphLabel label = new GraphLabel(node.getText(), node.getImage(), cacheLabel);
812
684
813
		if (!checkStyle(ZestStyles.NODES_HIDE_TEXT)) {
814
			label.setText(this.getText());
815
		}
816
		label.setIcon(getImage());
817
818
		// @tag TODO: Add border and foreground colours to highlight
819
		// (this.borderColor)
820
		if (highlighted == HIGHLIGHT_ON) {
685
		if (highlighted == HIGHLIGHT_ON) {
821
			label.setForegroundColor(getForegroundColor());
686
			label.setForegroundColor(getForegroundColor());
822
			label.setBackgroundColor(getHighlightColor());
687
			label.setBackgroundColor(getHighlightColor());
688
			label.setBorderColor(getBorderHighlightColor());
823
		} else {
689
		} else {
824
			label.setForegroundColor(getForegroundColor());
690
			label.setForegroundColor(getForegroundColor());
825
			label.setBackgroundColor(getBackgroundColor());
691
			label.setBackgroundColor(getBackgroundColor());
692
			label.setBorderColor(getBorderColor());
826
		}
693
		}
827
694
695
		label.setBorderWidth(getBorderWidth());
828
		label.setFont(getFont());
696
		label.setFont(getFont());
829
		return label;
830
	}
831
697
832
	public boolean isVisible() {
698
		return label;
833
		return visible;
834
	}
699
	}
835
700
836
	void addSourceConnection(GraphConnection connection) {
701
	void addSourceConnection(GraphConnection connection) {
Lines 873-947 Link Here
873
		return NODE;
738
		return NODE;
874
	}
739
	}
875
740
876
	class LayoutGraphNode implements LayoutEntity {
877
		Object layoutInformation = null;
878
879
		public double getHeightInLayout() {
880
			return getSize().height;
881
		}
882
883
		public Object getLayoutInformation() {
884
			return layoutInformation;
885
		}
886
887
		public String toString() {
888
			return getText();
889
		}
890
891
		public double getWidthInLayout() {
892
			return getSize().width;
893
		}
894
895
		public double getXInLayout() {
896
			return getLocation().x;
897
		}
898
899
		public double getYInLayout() {
900
			return getLocation().y;
901
		}
902
903
		public void populateLayoutConstraint(LayoutConstraint constraint) {
904
			invokeLayoutListeners(constraint);
905
		}
906
907
		public void setLayoutInformation(Object internalEntity) {
908
			this.layoutInformation = internalEntity;
909
910
		}
911
912
		public void setLocationInLayout(double x, double y) {
913
			setLocation(x, y);
914
		}
915
916
		public void setSizeInLayout(double width, double height) {
917
			setSize(width, height);
918
		}
919
920
		/**
921
		 * Compares two nodes.
922
		 */
923
		public int compareTo(Object otherNode) {
924
			int rv = 0;
925
			if (otherNode instanceof GraphNode) {
926
				GraphNode node = (GraphNode) otherNode;
927
				if (getText() != null) {
928
					rv = getText().compareTo(node.getText());
929
				}
930
			}
931
			return rv;
932
		}
933
934
		public Object getGraphData() {
935
			return GraphNode.this;
936
		}
937
938
		public void setGraphData(Object o) {
939
			// TODO Auto-generated method stub
940
941
		}
942
943
	}
944
945
	IFigure getFigure() {
741
	IFigure getFigure() {
946
		if (this.nodeFigure == null) {
742
		if (this.nodeFigure == null) {
947
			initFigure();
743
			initFigure();
Lines 949-955 Link Here
949
		return this.getNodeFigure();
745
		return this.getNodeFigure();
950
	}
746
	}
951
747
952
	void paint() {
748
	private InternalNodeLayout layout;
749
750
	InternalNodeLayout getLayout() {
751
		if (layout == null) {
752
			layout = new InternalNodeLayout(this);
753
		}
754
		return layout;
755
	}
953
756
757
	void applyLayoutChanges() {
758
		if (layout != null)
759
			layout.applyLayout();
954
	}
760
	}
955
}
761
}
(-)src/org/eclipse/zest/core/widgets/Graph.java (-328 / +117 lines)
Lines 1-18 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:
9
 *     The Chisel Group, University of Victoria
10
 *     Mateusz Matela <mateusz.matela@gmail.com> - ongoing development
9
 ******************************************************************************/
11
 ******************************************************************************/
12
10
package org.eclipse.zest.core.widgets;
13
package org.eclipse.zest.core.widgets;
11
14
12
import java.util.ArrayList;
15
import java.util.ArrayList;
13
import java.util.HashMap;
16
import java.util.HashMap;
14
import java.util.Iterator;
17
import java.util.Iterator;
15
import java.util.LinkedList;
16
import java.util.List;
18
import java.util.List;
17
19
18
import org.eclipse.draw2d.Animation;
20
import org.eclipse.draw2d.Animation;
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-69 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;
48
import org.eclipse.zest.core.widgets.internal.ContainerFigure;
51
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;
52
import org.eclipse.zest.core.widgets.internal.ZestRootLayer;
51
import org.eclipse.zest.layouts.InvalidLayoutConfiguration;
52
import org.eclipse.zest.layouts.LayoutAlgorithm;
53
import org.eclipse.zest.layouts.LayoutAlgorithm;
53
import org.eclipse.zest.layouts.LayoutEntity;
54
import org.eclipse.zest.layouts.LayoutRelationship;
55
import org.eclipse.zest.layouts.LayoutStyles;
56
import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm;
57
import org.eclipse.zest.layouts.constraints.LayoutConstraint;
58
54
59
/*
55
public class Graph extends FigureCanvas {
60
 * Holds the nodes and connections for the graph.
61
 * 
62
 * @author Chris Callendar
63
 * 
64
 * @author Ian Bull
65
 */
66
public class Graph extends FigureCanvas implements IContainer {
67
56
68
	// CLASS CONSTANTS
57
	// CLASS CONSTANTS
69
	public static final int ANIMATION_TIME = 500;
58
	public static final int ANIMATION_TIME = 500;
Lines 94-107 Link Here
94
	/** This maps all visible nodes to their model element. */
83
	/** This maps all visible nodes to their model element. */
95
	private HashMap figure2ItemMap = null;
84
	private HashMap figure2ItemMap = null;
96
85
97
	/** Maps user nodes to internal nodes */
98
	private int connectionStyle;
86
	private int connectionStyle;
99
	private int nodeStyle;
87
	private int nodeStyle;
100
	private List constraintAdapters;
101
	private List revealListeners = null;
102
103
	private ScalableFreeformLayeredPane fishEyeLayer = null;
88
	private ScalableFreeformLayeredPane fishEyeLayer = null;
104
	LayoutAlgorithm layoutAlgorithm = null;
89
	private LayoutAlgorithm layoutAlgorithm = null;
90
	private InternalLayoutContext layoutContext = null;
91
	private volatile boolean isLayoutScheduled;
105
	private Dimension preferredSize = null;
92
	private Dimension preferredSize = null;
106
	int style = 0;
93
	int style = 0;
107
94
Lines 120-131 Link Here
120
		this.style = style;
107
		this.style = style;
121
		this.setBackground(ColorConstants.white);
108
		this.setBackground(ColorConstants.white);
122
109
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());
110
		this.setViewport(new FreeformViewport());
130
111
131
		this.getVerticalBar().addSelectionListener(new SelectionAdapter() {
112
		this.getVerticalBar().addSelectionListener(new SelectionAdapter() {
Lines 164-170 Link Here
164
		});
145
		});
165
146
166
		this.setContents(createLayers());
147
		this.setContents(createLayers());
167
		DragSupport dragSupport = new DragSupport(this);
148
		DragSupport dragSupport = new DragSupport();
168
		this.getLightweightSystem().getRootFigure().addMouseListener(dragSupport);
149
		this.getLightweightSystem().getRootFigure().addMouseListener(dragSupport);
169
		this.getLightweightSystem().getRootFigure().addMouseMotionListener(dragSupport);
150
		this.getLightweightSystem().getRootFigure().addMouseMotionListener(dragSupport);
170
151
Lines 173-208 Link Here
173
		this.connectionStyle = ZestStyles.NONE;
154
		this.connectionStyle = ZestStyles.NONE;
174
		this.nodeStyle = ZestStyles.NONE;
155
		this.nodeStyle = ZestStyles.NONE;
175
		this.connections = new ArrayList();
156
		this.connections = new ArrayList();
176
		this.constraintAdapters = new ArrayList();
177
		this.selectedItems = new ArrayList();
157
		this.selectedItems = new ArrayList();
178
		this.selectionListeners = new ArrayList();
158
		this.selectionListeners = new ArrayList();
179
		this.figure2ItemMap = new HashMap();
159
		this.figure2ItemMap = new HashMap();
180
160
181
		revealListeners = new ArrayList(1);
182
		this.addPaintListener(new PaintListener() {
161
		this.addPaintListener(new PaintListener() {
183
			public void paintControl(PaintEvent e) {
162
			public void paintControl(PaintEvent e) {
184
				if (!revealListeners.isEmpty()) {
163
				if (isLayoutScheduled) {
185
					// Go through the reveal list and let everyone know that the
164
					applyLayoutInternal();
186
					// view is now available. Remove the listeners so they are
165
					isLayoutScheduled = 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
				}
166
				}
196
				/*
197
				Iterator iterator = getNodes().iterator();
198
				while (iterator.hasNext()) {
199
					GraphNode node = (GraphNode) iterator.next();
200
					node.paint();
201
				}
202
				*/
203
			}
167
			}
204
		});
168
		});
205
169
170
		this.addControlListener(new ControlListener() {
171
172
			public void controlResized(ControlEvent e) {
173
				if (preferredSize.width == -1 || preferredSize.height == -1) {
174
					getLayoutContext().fireBoundsChangedEvent();
175
				}
176
			}
177
178
			public void controlMoved(ControlEvent e) {
179
				// do nothing
180
			}
181
		});
206
	}
182
	}
207
183
208
	/**
184
	/**
Lines 235-257 Link Here
235
	}
211
	}
236
212
237
	/**
213
	/**
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
214
	 * Gets the root layer for this graph
256
	 * 
215
	 * 
257
	 * @return
216
	 * @return
Lines 326-331 Link Here
326
				}
285
				}
327
			}
286
			}
328
		}
287
		}
288
		// TODO shouldn't this method fire a selection event?
329
	}
289
	}
330
290
331
	public void selectAll() {
291
	public void selectAll() {
Lines 334-339 Link Here
334
			selectedItems.add(nodes.get(i));
294
			selectedItems.add(nodes.get(i));
335
			((GraphNode) nodes.get(i)).highlight();
295
			((GraphNode) nodes.get(i)).highlight();
336
		}
296
		}
297
		// TODO shouldn't this method fire a selection event?
337
	}
298
	}
338
299
339
	/**
300
	/**
Lines 354-368 Link Here
354
		return "GraphModel {" + nodes.size() + " nodes, " + connections.size() + " connections}";
315
		return "GraphModel {" + nodes.size() + " nodes, " + connections.size() + " connections}";
355
	}
316
	}
356
317
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
	}
365
366
	/**
318
	/**
367
	 * Dispose of the nodes and edges when the graph is disposed.
319
	 * Dispose of the nodes and edges when the graph is disposed.
368
	 */
320
	 */
Lines 389-407 Link Here
389
	}
341
	}
390
342
391
	/**
343
	/**
392
	 * Runs the layout on this graph. It uses the reveal listner to run the
344
	 * 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
345
	 * deferred until after the view is available.
394
	 * after the view is available.
395
	 */
346
	 */
396
	public void applyLayout() {
347
	public void applyLayout() {
397
		this.addRevealListener(new RevealListener() {
348
		scheduleLayoutOnReveal();
398
			public void revealed(Control c) {
349
	}
399
				Display.getDefault().asyncExec(new Runnable() {
400
350
401
					public void run() {
351
	private void applyLayoutInternal() {
402
						applyLayoutInternal();
352
		if (layoutAlgorithm == null) {
403
					}
353
			return;
404
				});
354
		}
355
		Display.getDefault().asyncExec(new Runnable() {
356
			public void run() {
357
				Animation.markBegin();
358
				layoutAlgorithm.applyLayout();
359
				layoutContext.flushChanges(false);
360
				Animation.run(ANIMATION_TIME);
361
				getLightweightSystem().getUpdateManager().performUpdate();
405
			}
362
			}
406
		});
363
		});
407
	}
364
	}
Lines 415-427 Link Here
415
	 */
372
	 */
416
	public void setPreferredSize(int width, int height) {
373
	public void setPreferredSize(int width, int height) {
417
		this.preferredSize = new Dimension(width, height);
374
		this.preferredSize = new Dimension(width, height);
375
		getLayoutContext().fireBoundsChangedEvent();
376
	}
377
378
	/**
379
	 * 
380
	 * @return the preferred size of the layout area.
381
	 */
382
	public Dimension getPreferredSize() {
383
		if (preferredSize.width < 0 || preferredSize.height < 0) {
384
			org.eclipse.swt.graphics.Point size = getSize();
385
			return new Dimension(size.x, size.y);
386
		}
387
		return preferredSize;
388
	}
389
390
	InternalLayoutContext getLayoutContext() {
391
		if (layoutContext == null) {
392
			layoutContext = new InternalLayoutContext(this);
393
		}
394
		return layoutContext;
418
	}
395
	}
419
396
420
	/**
397
	/**
421
	 * @param algorithm
398
	 * @param algorithm
422
	 */
399
	 */
423
	public void setLayoutAlgorithm(LayoutAlgorithm algorithm, boolean applyLayout) {
400
	public void setLayoutAlgorithm(LayoutAlgorithm algorithm, boolean applyLayout) {
401
		if (this.layoutAlgorithm != null) {
402
			this.layoutAlgorithm.setLayoutContext(null);
403
		}
424
		this.layoutAlgorithm = algorithm;
404
		this.layoutAlgorithm = algorithm;
405
		this.layoutAlgorithm.setLayoutContext(getLayoutContext());
425
		if (applyLayout) {
406
		if (applyLayout) {
426
			applyLayout();
407
			applyLayout();
427
		}
408
		}
Lines 432-437 Link Here
432
	}
413
	}
433
414
434
	/**
415
	/**
416
	 * Adds a filter used for hiding elements from layout algorithm.
417
	 * 
418
	 * NOTE: If a node or subgraph if filtered out, all connections adjacent to
419
	 * it should also be filtered out. Otherwise layout algorithm may behave in
420
	 * an unexpected way.
421
	 * 
422
	 * @param filter
423
	 *            filter to add
424
	 */
425
	public void addLayoutFilter(LayoutFilter filter) {
426
		getLayoutContext().addFilter(filter);
427
	}
428
429
	/**
430
	 * Removes given layout filter. If it had not been added to this graph, this
431
	 * method does nothing.
432
	 * 
433
	 * @param filter
434
	 *            filter to remove
435
	 */
436
	public void removeLayoutFilter(LayoutFilter filter) {
437
		getLayoutContext().removeFilter(filter);
438
	}
439
440
	/**
435
	 * Finds a figure at the location X, Y in the graph
441
	 * Finds a figure at the location X, Y in the graph
436
	 * 
442
	 * 
437
	 * This point should be translated to relative before calling findFigureAt
443
	 * This point should be translated to relative before calling findFigureAt
Lines 472-493 Link Here
472
478
473
	}
479
	}
474
480
475
	// /////////////////////////////////////////////////////////////////////////////////
481
	private class DragSupport implements MouseMotionListener, org.eclipse.draw2d.MouseListener {
476
	// PRIVATE METHODS. These are NON API
482
477
	// /////////////////////////////////////////////////////////////////////////////////
478
	class DragSupport implements MouseMotionListener, org.eclipse.draw2d.MouseListener {
479
		/**
480
		 * 
481
		 */
482
		Graph graph = null;
483
		Point lastLocation = null;
483
		Point lastLocation = null;
484
		GraphItem fisheyedItem = null;
484
		GraphItem fisheyedItem = null;
485
		boolean isDragging = false;
485
		boolean isDragging = false;
486
486
487
		DragSupport(Graph graph) {
488
			this.graph = graph;
489
		}
490
491
		public void mouseDragged(org.eclipse.draw2d.MouseEvent me) {
487
		public void mouseDragged(org.eclipse.draw2d.MouseEvent me) {
492
			if (!isDragging) {
488
			if (!isDragging) {
493
				return;
489
				return;
Lines 514-525 Link Here
514
							node.setLocation(node.getLocation().x + delta.x, node.getLocation().y + delta.y);
510
							node.setLocation(node.getLocation().x + delta.x, node.getLocation().y + delta.y);
515
511
516
						}
512
						}
517
						/*
518
						else if (item.getItemType() == GraphItem.CONTAINER) {
519
							GraphContainer container = (GraphContainer) item;
520
							container.setLocation(container.getLocation().x + delta.x, container.getLocation().y + delta.y);
521
						}
522
						*/
523
					} else {
513
					} else {
524
						// There is no movement for connection
514
						// There is no movement for connection
525
					}
515
					}
Lines 537-548 Link Here
537
					Point point = new Point(fisheyedFigure.getBounds().x + delta.x, fisheyedFigure.getBounds().y + delta.y);
527
					Point point = new Point(fisheyedFigure.getBounds().x + delta.x, fisheyedFigure.getBounds().y + delta.y);
538
					fishEyeLayer.setConstraint(fisheyedFigure, new Rectangle(point, fisheyedFigure.getSize()));
528
					fishEyeLayer.setConstraint(fisheyedFigure, new Rectangle(point, fisheyedFigure.getSize()));
539
					fishEyeLayer.getUpdateManager().performUpdate();
529
					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
				}
530
				}
543
			}
531
			}
544
			lastLocation = tempPoint;
532
			lastLocation = tempPoint;
545
			//oldLocation = mousePoint;
546
		}
533
		}
547
534
548
		public void mouseEntered(org.eclipse.draw2d.MouseEvent me) {
535
		public void mouseEntered(org.eclipse.draw2d.MouseEvent me) {
Lines 638-644 Link Here
638
				}
625
				}
639
				// If the figure under the mouse is the canvas, and CTRL is not being held down, then select
626
				// If the figure under the mouse is the canvas, and CTRL is not being held down, then select
640
				// nothing
627
				// nothing
641
				if (figureUnderMouse == null || figureUnderMouse == graph) {
628
				if (figureUnderMouse == null || figureUnderMouse == Graph.this) {
642
					if (me.getState() != org.eclipse.draw2d.MouseEvent.CONTROL) {
629
					if (me.getState() != org.eclipse.draw2d.MouseEvent.CONTROL) {
643
						clearSelection();
630
						clearSelection();
644
						if (hasSelection) {
631
						if (hasSelection) {
Lines 763-792 Link Here
763
	}
750
	}
764
751
765
	/**
752
	/**
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
753
	 * Moves the node off the node feedback layer
791
	 * 
754
	 * 
792
	 * @param node
755
	 * @param node
Lines 810-865 Link Here
810
		return connsArray;
773
		return connsArray;
811
	}
774
	}
812
775
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) {
776
	void removeConnection(GraphConnection connection) {
864
		IFigure figure = connection.getConnectionFigure();
777
		IFigure figure = connection.getConnectionFigure();
865
		PolylineConnection sourceContainerConnectionFigure = connection.getSourceContainerConnectionFigure();
778
		PolylineConnection sourceContainerConnectionFigure = connection.getSourceContainerConnectionFigure();
Lines 873-878 Link Here
873
		if (targetContainerConnectionFigure != null) {
786
		if (targetContainerConnectionFigure != null) {
874
			figure2ItemMap.remove(targetContainerConnectionFigure);
787
			figure2ItemMap.remove(targetContainerConnectionFigure);
875
		}
788
		}
789
		getLayoutContext().fireConnectionRemovedEvent(connection.getLayout());
876
	}
790
	}
877
791
878
	void removeNode(GraphNode node) {
792
	void removeNode(GraphNode node) {
Lines 886-891 Link Here
886
		}
800
		}
887
		this.getNodes().remove(node);
801
		this.getNodes().remove(node);
888
		figure2ItemMap.remove(figure);
802
		figure2ItemMap.remove(figure);
803
		getLayoutContext().fireNodeRemovedEvent(node.getLayout());
889
	}
804
	}
890
805
891
	void addConnection(GraphConnection connection, boolean addToEdgeLayer) {
806
	void addConnection(GraphConnection connection, boolean addToEdgeLayer) {
Lines 893-936 Link Here
893
		if (addToEdgeLayer) {
808
		if (addToEdgeLayer) {
894
			zestRootLayer.addConnection(connection.getFigure());
809
			zestRootLayer.addConnection(connection.getFigure());
895
		}
810
		}
811
		getLayoutContext().fireConnectionAddedEvent(connection.getLayout());
896
	}
812
	}
897
813
898
	/*
899
	public void redraw() {
900
901
		Iterator iterator = this.getConnections().iterator();
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) {
814
	void addNode(GraphNode node) {
926
		this.getNodes().add(node);
815
		this.getNodes().add(node);
927
		zestRootLayer.addNode(node.getFigure());
816
		zestRootLayer.addNode(node.getFigure());
817
		getLayoutContext().fireNodeAddedEvent(node.getLayout());
928
	}
818
	}
929
819
930
	void addNode(GraphContainer graphContainer) {
820
	void addFigure(IFigure figure) {
931
		this.getNodes().add(graphContainer);
821
		rootlayer.add(figure);
932
		zestRootLayer.addNode(graphContainer.getFigure());
933
934
	}
822
	}
935
823
936
	void registerItem(GraphItem item) {
824
	void registerItem(GraphItem item) {
Lines 954-1071 Link Here
954
		}
842
		}
955
	}
843
	}
956
844
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
	/**
845
	/**
973
	 * Invoke all the constraint adapaters for this constraints
846
	 * Schedules a layout to be performed after the view is revealed (or
974
	 * 
847
	 * immediately, if the view is already revealed).
975
	 * @param object
976
	 * @param constraint
977
	 */
978
	void invokeConstraintAdapters(Object object, LayoutConstraint constraint) {
979
		if (constraintAdapters == null) {
980
			return;
981
		}
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
	}
1040
1041
	/**
1042
	 * Adds a reveal listener to the view. Note: A reveal listener will only
1043
	 * every be called ONCE!!! even if a view comes and goes. There is no remove
1044
	 * reveal listener. This is used to defer some events until after the view
1045
	 * is revealed.
1046
	 * 
848
	 * 
1047
	 * @param revealListener
849
	 * @param revealListener
1048
	 */
850
	 */
1049
	private void addRevealListener(final RevealListener revealListener) {
851
	private void scheduleLayoutOnReveal() {
1050
1051
		MyRunnable myRunnable = new MyRunnable() {
1052
			boolean isVisible;
1053
1054
			public boolean isVisible() {
1055
				return this.isVisible;
1056
			}
1057
852
853
		final boolean[] isVisibleSync = new boolean[1];
854
		Display.getDefault().syncExec(new Runnable() {
1058
			public void run() {
855
			public void run() {
1059
				isVisible = Graph.this.isVisible();
856
				isVisibleSync[0] = isVisible();
1060
			}
857
			}
858
		});
1061
859
1062
		};
860
		if (isVisibleSync[0]) {
1063
		Display.getDefault().syncExec(myRunnable);
861
			applyLayoutInternal();
1064
1065
		if (myRunnable.isVisible()) {
1066
			revealListener.revealed(this);
1067
		} else {
862
		} else {
1068
			revealListeners.add(revealListener);
863
			isLayoutScheduled = true;
1069
		}
864
		}
1070
	}
865
	}
1071
866
Lines 1132-1143 Link Here
1132
		if (this.fishEyeLayer.getChildren().contains(oldFigure)) {
927
		if (this.fishEyeLayer.getChildren().contains(oldFigure)) {
1133
			Rectangle bounds = oldFigure.getBounds();
928
			Rectangle bounds = oldFigure.getBounds();
1134
			newFigure.setBounds(bounds);
929
			newFigure.setBounds(bounds);
1135
			//this.fishEyeLayer.getChildren().remove(oldFigure);
1136
			this.fishEyeLayer.remove(oldFigure);
930
			this.fishEyeLayer.remove(oldFigure);
1137
			this.fishEyeLayer.add(newFigure);
931
			this.fishEyeLayer.add(newFigure);
1138
			//this.fishEyeLayer.getChildren().add(newFigure);
1139
			//this.fishEyeLayer.invalidate();
1140
			//this.fishEyeLayer.repaint();
1141
			this.fisheyedFigure = newFigure;
932
			this.fisheyedFigure = newFigure;
1142
			return true;
933
			return true;
1143
		}
934
		}
Lines 1182-1192 Link Here
1182
		this.getRootLayer().getUpdateManager().performUpdate();
973
		this.getRootLayer().getUpdateManager().performUpdate();
1183
	}
974
	}
1184
975
1185
	public Graph getGraph() {
1186
		// @tag refactor : Is this method really needed
1187
		return this.getGraphModel();
1188
	}
1189
1190
	public int getItemType() {
976
	public int getItemType() {
1191
		return GraphItem.GRAPH;
977
		return GraphItem.GRAPH;
1192
	}
978
	}
Lines 1195-1198 Link Here
1195
		return (GraphItem) figure2ItemMap.get(figure);
981
		return (GraphItem) figure2ItemMap.get(figure);
1196
	}
982
	}
1197
983
984
	public void setExpanded(GraphNode node, boolean expanded) {
985
		layoutContext.setExpanded(node.getLayout(), expanded);
986
	}
1198
}
987
}
(-)src/org/eclipse/zest/core/widgets/GraphContainer.java (-248 / +307 lines)
Lines 1-12 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright 2005-2007, CHISEL Group, University of Victoria, Victoria, BC,
2
 * Copyright 2005-2009, CHISEL Group, University of Victoria, Victoria, BC,
3
 * Canada. All rights reserved. This program and the accompanying materials are
3
 * Canada. All rights reserved. This program and the accompanying materials are
4
 * made 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:
9
 *     The Chisel Group, University of Victoria
10
 *     Mateusz Matela <mateusz.matela@gmail.com> - Adapt Zest to changes in layout - https://bugs.eclipse.org/bugs/show_bug.cgi?id=283179
9
 ******************************************************************************/
11
 ******************************************************************************/
12
10
package org.eclipse.zest.core.widgets;
13
package org.eclipse.zest.core.widgets;
11
14
12
import java.util.ArrayList;
15
import java.util.ArrayList;
Lines 14-74 Link Here
14
import java.util.LinkedList;
17
import java.util.LinkedList;
15
import java.util.List;
18
import java.util.List;
16
19
20
import org.eclipse.draw2d.ActionEvent;
21
import org.eclipse.draw2d.ActionListener;
17
import org.eclipse.draw2d.Animation;
22
import org.eclipse.draw2d.Animation;
23
import org.eclipse.draw2d.Clickable;
18
import org.eclipse.draw2d.ColorConstants;
24
import org.eclipse.draw2d.ColorConstants;
25
import org.eclipse.draw2d.Figure;
19
import org.eclipse.draw2d.FreeformLayout;
26
import org.eclipse.draw2d.FreeformLayout;
20
import org.eclipse.draw2d.FreeformViewport;
27
import org.eclipse.draw2d.FreeformViewport;
28
import org.eclipse.draw2d.Graphics;
21
import org.eclipse.draw2d.IFigure;
29
import org.eclipse.draw2d.IFigure;
30
import org.eclipse.draw2d.Label;
22
import org.eclipse.draw2d.LayoutAnimator;
31
import org.eclipse.draw2d.LayoutAnimator;
23
import org.eclipse.draw2d.LineBorder;
32
import org.eclipse.draw2d.LineBorder;
24
import org.eclipse.draw2d.PolylineConnection;
25
import org.eclipse.draw2d.ScrollPane;
33
import org.eclipse.draw2d.ScrollPane;
34
import org.eclipse.draw2d.ToolbarLayout;
35
import org.eclipse.draw2d.Triangle;
26
import org.eclipse.draw2d.Viewport;
36
import org.eclipse.draw2d.Viewport;
27
import org.eclipse.draw2d.geometry.Dimension;
37
import org.eclipse.draw2d.geometry.Dimension;
28
import org.eclipse.draw2d.geometry.Point;
38
import org.eclipse.draw2d.geometry.Point;
29
import org.eclipse.draw2d.geometry.Rectangle;
39
import org.eclipse.draw2d.geometry.Rectangle;
40
import org.eclipse.swt.events.SelectionEvent;
41
import org.eclipse.swt.events.SelectionListener;
42
import org.eclipse.swt.graphics.Color;
30
import org.eclipse.swt.graphics.Image;
43
import org.eclipse.swt.graphics.Image;
44
import org.eclipse.swt.graphics.RGB;
45
import org.eclipse.swt.widgets.Display;
31
import org.eclipse.zest.core.widgets.internal.AspectRatioFreeformLayer;
46
import org.eclipse.zest.core.widgets.internal.AspectRatioFreeformLayer;
32
import org.eclipse.zest.core.widgets.internal.ContainerFigure;
47
import org.eclipse.zest.core.widgets.internal.ContainerFigure;
33
import org.eclipse.zest.core.widgets.internal.ExpandGraphLabel;
34
import org.eclipse.zest.core.widgets.internal.ZestRootLayer;
48
import org.eclipse.zest.core.widgets.internal.ZestRootLayer;
35
import org.eclipse.zest.layouts.InvalidLayoutConfiguration;
36
import org.eclipse.zest.layouts.LayoutAlgorithm;
49
import org.eclipse.zest.layouts.LayoutAlgorithm;
37
import org.eclipse.zest.layouts.LayoutEntity;
38
import org.eclipse.zest.layouts.LayoutRelationship;
39
import org.eclipse.zest.layouts.LayoutStyles;
40
import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm;
50
import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm;
51
import org.eclipse.zest.layouts.dataStructures.DisplayIndependentRectangle;
41
52
42
/*
53
/**
43
 * A Container than can be added to a Graph. Nodes can be added to this
54
 * A Container that can be added to a Graph. Nodes can be added to this
44
 * container. The container supports collapsing and expanding and has the same
55
 * container. The container supports collapsing and expanding and has the same
45
 * properties as the nodes. Containers cannot have custom figures.
56
 * properties as the nodes. Containers cannot have custom figures.
46
 * 
57
 * 
47
 * @author Ian Bull
58
 * @author Ian Bull
48
 */
59
 */
49
public class GraphContainer extends GraphNode implements IContainer {
60
public class GraphContainer extends GraphNode {
61
62
	public static class ExpandGraphLabel extends Figure implements ActionListener {
63
64
		private boolean isExpanded;
65
		private Expander expander = new Expander();
66
		private Color darkerBackground;
67
68
		class Expander extends Clickable {
69
			private Triangle triangle;
70
71
			public Expander() {
72
				setStyle(Clickable.STYLE_TOGGLE);
73
				triangle = new Triangle();
74
				triangle.setSize(10, 10);
75
				triangle.setBackgroundColor(ColorConstants.black);
76
				triangle.setForegroundColor(ColorConstants.black);
77
				triangle.setFill(true);
78
				triangle.setDirection(Triangle.EAST);
79
				triangle.setLocation(new Point(5, 3));
80
				this.setLayoutManager(new FreeformLayout());
81
				this.add(triangle);
82
				this.setPreferredSize(15, 15);
83
				this.addActionListener(ExpandGraphLabel.this);
84
			}
85
86
			public void open() {
87
				triangle.setDirection(Triangle.SOUTH);
88
			}
89
90
			public void close() {
91
				triangle.setDirection(Triangle.EAST);
92
			}
93
94
		}
95
96
		/**
97
		 * Sets the expander state (the little triangle) to
98
		 * ExpanderGraphLabel.OPEN or ExpanderGraphLabel.CLOSED
99
		 * 
100
		 * @param state
101
		 */
102
		public void setExpandedState(boolean expanded) {
103
			if (expanded) {
104
				expander.open();
105
			} else {
106
				expander.close();
107
			}
108
			this.isExpanded = expanded;
109
		}
110
111
		/*
112
		 * (non-Javadoc)
113
		 * 
114
		 * @see
115
		 * org.eclipse.draw2d.ActionListener#actionPerformed(org.eclipse.draw2d
116
		 * .ActionEvent)
117
		 */
118
		public void actionPerformed(ActionEvent event) {
119
			if (isExpanded) {
120
				container.close(true);
121
			} else {
122
				container.open(true);
123
			}
124
		}
125
126
		private final int arcWidth = 8;
127
		private final Label label;
128
		private final GraphContainer container;
129
		private final ToolbarLayout layout;
130
131
		public ExpandGraphLabel(GraphContainer container, String text, Image image, boolean cacheLabel) {
132
			this.label = new Label(text) {
133
134
				/**
135
				 * <b>This method is overwritten so that the text is not
136
				 * truncated.</b><br>
137
				 * 
138
				 * {@inheritDoc}
139
				 * 
140
				 */
141
				protected void paintFigure(Graphics graphics) {
142
					if (isOpaque()) {
143
						super.paintFigure(graphics);
144
					}
145
					Rectangle bounds = getBounds();
146
					graphics.translate(bounds.x, bounds.y);
147
					if (getIcon() != null) {
148
						graphics.drawImage(getIcon(), getIconLocation());
149
					}
150
					if (!isEnabled()) {
151
						graphics.translate(1, 1);
152
						graphics.setForegroundColor(ColorConstants.buttonLightest);
153
						graphics.drawText(getSubStringText(), getTextLocation());
154
						graphics.translate(-1, -1);
155
						graphics.setForegroundColor(ColorConstants.buttonDarker);
156
					}
157
					graphics.drawText(getText(), getTextLocation());
158
					graphics.translate(-bounds.x, -bounds.y);
159
				}
160
			};
161
			this.setText(text);
162
			this.setImage(image);
163
			this.container = container;
164
			this.setFont(Display.getDefault().getSystemFont());
165
			layout = new ToolbarLayout(true);
166
			layout.setSpacing(5);
167
			layout.setMinorAlignment(ToolbarLayout.ALIGN_CENTER);
168
			this.setLayoutManager(layout);
169
			this.add(this.expander);
170
			this.add(this.label);
171
		}
172
173
		private Color getDarkerBackgroundColor() {
174
			if (darkerBackground == null) {
175
				Color baseColor = getBackgroundColor();
176
				int blue = (int) (baseColor.getBlue() * 0.8 + 0.5);
177
				int red = (int) (baseColor.getRed() * 0.8 + 0.5);
178
				int green = (int) (baseColor.getGreen() * 0.8 + 0.5);
179
				darkerBackground = new Color(Display.getCurrent(), new RGB(red, green, blue));
180
			}
181
			return darkerBackground;
182
		}
183
184
		/*
185
		 * (non-Javadoc)
186
		 * 
187
		 * @see
188
		 * org.eclipse.draw2d.Label#paintFigure(org.eclipse.draw2d.Graphics)
189
		 */
190
		public void paint(Graphics graphics) {
191
192
			graphics.setForegroundColor(getDarkerBackgroundColor());
193
			graphics.setBackgroundColor(getBackgroundColor());
194
195
			graphics.pushState();
196
197
			// fill in the background
198
			Rectangle bounds = getBounds().getCopy();
199
			Rectangle r = bounds.getCopy();
200
			r.y += arcWidth / 2;
201
			r.height -= arcWidth;
202
203
			Rectangle top = bounds.getCopy();
204
			top.height /= 2;
205
			graphics.setForegroundColor(getBackgroundColor());
206
			graphics.setBackgroundColor(getBackgroundColor());
207
			graphics.fillRoundRectangle(top, arcWidth, arcWidth);
208
209
			top.y = top.y + top.height;
210
			graphics.setForegroundColor(darkerBackground);
211
			graphics.setBackgroundColor(darkerBackground);
212
			graphics.fillRoundRectangle(top, arcWidth, arcWidth);
213
214
			graphics.setBackgroundColor(darkerBackground);
215
			graphics.setForegroundColor(getBackgroundColor());
216
			graphics.fillGradient(r, true);
217
218
			super.paint(graphics);
219
			graphics.popState();
220
			graphics.setForegroundColor(darkerBackground);
221
			graphics.setBackgroundColor(darkerBackground);
222
			// paint the border
223
			bounds.setSize(bounds.width - 1, bounds.height - 1);
224
			graphics.drawRoundRectangle(bounds, arcWidth, arcWidth);
225
		}
226
227
		public void setBackgroundColor(Color bg) {
228
			super.setBackgroundColor(bg);
229
			if (darkerBackground != null) {
230
				darkerBackground.dispose();
231
			}
232
			darkerBackground = null;
233
		}
234
235
		public void setTextT(String string) {
236
			this.setPreferredSize(null);
237
			this.label.setText(string);
238
			this.add(label);
239
			this.layout.layout(this);
240
			this.invalidate();
241
			this.revalidate();
242
			this.validate();
243
		}
244
245
		public void setText(String string) {
246
			this.label.setText(string);
247
		}
248
249
		public void setImage(Image image) {
250
			this.label.setIcon(image);
251
		}
252
253
		public void setFocus() {
254
			expander.requestFocus();
255
		}
256
257
	}
50
258
51
	//private static final double CONTAINER_SCALE = 0.75;
259
	static final double SCALED_WIDTH = 300;
52
	private static final double scaledWidth = 300;
260
	static final double SCALED_HEIGHT = 200;
53
	private static final double scaledHeight = 200;
54
	private static final int CONTAINER_HEIGHT = 200;
261
	private static final int CONTAINER_HEIGHT = 200;
55
	private static final int MIN_WIDTH = 250;
262
	private static final int MIN_WIDTH = 250;
263
	private static final int MIN_HEIGHT = 30;
56
	private static final int ANIMATION_TIME = 100;
264
	private static final int ANIMATION_TIME = 100;
57
	private static final int SUBLAYER_OFFSET = 2;
265
	private static final int SUBLAYER_OFFSET = 2;
58
266
267
	private static SelectionListener selectionListener;
268
59
	private ExpandGraphLabel expandGraphLabel;
269
	private ExpandGraphLabel expandGraphLabel;
60
270
61
	//private FreeformLayer container;
62
	//private FreeformLayer edgeLayer;
63
	private List childNodes = null;
271
	private List childNodes = null;
64
	private int childAreaHeight = CONTAINER_HEIGHT;
272
	private int childAreaHeight = CONTAINER_HEIGHT;
65
273
66
	public ZestRootLayer zestLayer;
274
	private ZestRootLayer zestLayer;
67
	private ScrollPane scrollPane;
275
	private ScrollPane scrollPane;
68
	private LayoutAlgorithm layoutAlgorithm;
276
	private LayoutAlgorithm layoutAlgorithm;
69
	private boolean isExpanded = false;
277
	private boolean isExpanded = false;
70
	//private ScalableFreeformLayeredPane scalledLayer;
71
	private AspectRatioFreeformLayer scalledLayer;
278
	private AspectRatioFreeformLayer scalledLayer;
279
	private InternalLayoutContext layoutContext;
72
280
73
	/**
281
	/**
74
	 * Creates a new GraphContainer.  A GraphContainer may contain nodes,
282
	 * Creates a new GraphContainer.  A GraphContainer may contain nodes,
Lines 76-96 Link Here
76
	 * @param graph The graph that the container is being added to
284
	 * @param graph The graph that the container is being added to
77
	 * @param style 
285
	 * @param style 
78
	 */
286
	 */
79
	public GraphContainer(IContainer graph, int style) {
287
	public GraphContainer(Graph graph, int style) {
80
		this(graph, style, "");
288
		this(graph, style, "");
289
	}
290
291
	public GraphContainer(Graph graph, int style, String text) {
292
		this(graph, style, text, null);
293
	}
81
294
295
	public GraphContainer(Graph graph, int style, String text, Image image) {
296
		this(NodeContainerAdapter.get(graph), style, text, image);
82
	}
297
	}
83
298
84
	public GraphContainer(IContainer graph, int style, String text) {
299
	public GraphContainer(GraphContainer graph, int style) {
300
		this(graph, style, "");
301
	}
302
303
	public GraphContainer(GraphContainer graph, int style, String text) {
85
		this(graph, style, text, null);
304
		this(graph, style, text, null);
305
	}
86
306
307
	public GraphContainer(GraphContainer graph, int style, String text, Image image) {
308
		this(NodeContainerAdapter.get(graph), style, text, image);
87
	}
309
	}
88
310
89
	public GraphContainer(IContainer graph, int style, String text, Image image) {
311
	public GraphContainer(NodeContainerAdapter graph, int style, String text, Image image) {
90
		super(graph, style, text, image);
312
		super(graph.getGraph(), style, text, image);
91
		initModel(graph, text, image);
313
		initModel(graph, text, image);
92
		close(false);
314
		close(false);
93
		childNodes = new ArrayList();
315
		childNodes = new ArrayList();
316
		registerToParent(graph);
94
	}
317
	}
95
318
96
	/**
319
	/**
Lines 100-119 Link Here
100
		throw new RuntimeException("Operation not supported:  Containers cannot have custom figures");
323
		throw new RuntimeException("Operation not supported:  Containers cannot have custom figures");
101
	}
324
	}
102
325
103
	/*
104
	 * (non-Javadoc)
105
	 * @see org.eclipse.mylar.zest.core.widgets.GraphItem#getItemType()
106
	public int getItemType() {
107
		return GraphItem.CONTAINER;
108
	}
109
110
	/**
111
	 * Gets the figure for this container.
112
	 */
113
	public IFigure getNodeFigure() {
114
		return this.nodeFigure;
115
	}
116
117
	/**
326
	/**
118
	 * Close this node.
327
	 * Close this node.
119
	 * @param animate
328
	 * @param animate
Lines 124-139 Link Here
124
		}
333
		}
125
		isExpanded = false;
334
		isExpanded = false;
126
335
127
		expandGraphLabel.setExpandedState(ExpandGraphLabel.CLOSED);
336
		expandGraphLabel.setExpandedState(false);
128
		Rectangle newBounds = scrollPane.getBounds().getCopy();
337
		Rectangle newBounds = scrollPane.getBounds().getCopy();
129
		newBounds.height = 0;
338
		newBounds.height = 0;
130
339
131
		//this.nodeFigure.setConstraint(scrollPane, newBounds);
132
		//this.nodeFigure.revalidate();
133
		scrollPane.setSize(scrollPane.getSize().width, 0);
340
		scrollPane.setSize(scrollPane.getSize().width, 0);
134
		updateFigureForModel(this.zestLayer);
341
		updateFigureForModel(this.zestLayer);
135
		scrollPane.setVisible(false);
342
		scrollPane.setVisible(false);
136
		//setSize(expandGraphLabel.getSize().width, expandGraphLabel.getSize().height);
137
		List children = this.zestLayer.getChildren();
343
		List children = this.zestLayer.getChildren();
138
		for (Iterator iterator = children.iterator(); iterator.hasNext();) {
344
		for (Iterator iterator = children.iterator(); iterator.hasNext();) {
139
			IFigure child = (IFigure) iterator.next();
345
			IFigure child = (IFigure) iterator.next();
Lines 145-151 Link Here
145
		if (animate) {
351
		if (animate) {
146
			Animation.run(ANIMATION_TIME);
352
			Animation.run(ANIMATION_TIME);
147
		}
353
		}
148
		//this.nodeFigure.getUpdateManager().performUpdate();
149
		updateFigureForModel(nodeFigure);
354
		updateFigureForModel(nodeFigure);
150
	}
355
	}
151
356
Lines 235-241 Link Here
235
	private void moveNodesUp(Rectangle containerBounds, GraphNode graphContainer) {
440
	private void moveNodesUp(Rectangle containerBounds, GraphNode graphContainer) {
236
441
237
		// Get all nodes below this container, in order
442
		// Get all nodes below this container, in order
238
		List orderedNodesBelowY = getOrderedNodesBelowY(parent.getNodes(), containerBounds.y, graphContainer);
443
		List orderedNodesBelowY = getOrderedNodesBelowY(parent.getGraph().getNodes(), containerBounds.y, graphContainer);
239
		int leftSide = containerBounds.x;
444
		int leftSide = containerBounds.x;
240
		int rightSide = containerBounds.x + containerBounds.width;
445
		int rightSide = containerBounds.x + containerBounds.width;
241
		List nodesToConsider = new LinkedList();
446
		List nodesToConsider = new LinkedList();
Lines 292-302 Link Here
292
		}
497
		}
293
		isExpanded = true;
498
		isExpanded = true;
294
499
295
		expandGraphLabel.setExpandedState(ExpandGraphLabel.OPEN);
500
		expandGraphLabel.setExpandedState(true);
296
501
297
		scrollPane.setSize(computeChildArea());
502
		scrollPane.setSize(computeChildArea());
298
		scrollPane.setVisible(true);
503
		scrollPane.setVisible(true);
299
		//setSize(expandGraphLabel.getSize().width, expandGraphLabel.getSize().height + expandedHeight - SUBLAYER_OFFSET);
300
504
301
		List children = this.zestLayer.getChildren();
505
		List children = this.zestLayer.getChildren();
302
		for (Iterator iterator = children.iterator(); iterator.hasNext();) {
506
		for (Iterator iterator = children.iterator(); iterator.hasNext();) {
Lines 308-323 Link Here
308
		updateFigureForModel(nodeFigure);
512
		updateFigureForModel(nodeFigure);
309
513
310
		Rectangle containerBounds = new Rectangle(this.getLocation(), new Dimension(this.getSize().width, CONTAINER_HEIGHT + this.expandGraphLabel.getSize().height));
514
		Rectangle containerBounds = new Rectangle(this.getLocation(), new Dimension(this.getSize().width, CONTAINER_HEIGHT + this.expandGraphLabel.getSize().height));
311
		//moveIntersectedNodes(containerBounds, this);
312
		moveNodesDown(containerBounds, this);
515
		moveNodesDown(containerBounds, this);
313
		moveNodesUp(containerBounds, this);
516
		moveNodesUp(containerBounds, this);
314
		//pack(graph);
315
		if (animate) {
517
		if (animate) {
316
			Animation.run(ANIMATION_TIME);
518
			Animation.run(ANIMATION_TIME);
317
		}
519
		}
318
		this.getFigure().getUpdateManager().performValidation();
520
		this.getFigure().getUpdateManager().performValidation();
319
		//this.nodeFigure.getUpdateManager().performUpdate();
320
321
	}
521
	}
322
522
323
	/**
523
	/**
Lines 328-334 Link Here
328
	private void moveNodesDown(Rectangle containerBounds, GraphContainer graphContainer) {
528
	private void moveNodesDown(Rectangle containerBounds, GraphContainer graphContainer) {
329
529
330
		// Find all nodes below here
530
		// Find all nodes below here
331
		List nodesBelowHere = getOrderedNodesBelowY(parent.getNodes(), containerBounds.y, graphContainer);
531
		List nodesBelowHere = getOrderedNodesBelowY(parent.getGraph().getNodes(), containerBounds.y, graphContainer);
332
		Iterator nodesBelowHereIterator = nodesBelowHere.iterator();
532
		Iterator nodesBelowHereIterator = nodesBelowHere.iterator();
333
		List nodesToMove = new LinkedList();
533
		List nodesToMove = new LinkedList();
334
		int left = containerBounds.x;
534
		int left = containerBounds.x;
Lines 349-391 Link Here
349
549
350
	}
550
	}
351
551
352
	void highlightNode(GraphNode node) {
353
354
	}
355
356
	void highlightEdge(GraphConnection connection) {
357
	}
358
359
	void highlightNode(GraphContainer container) {
360
361
	}
362
363
	void unhighlightNode(GraphNode node) {
364
365
	}
366
367
	void unhighlightNode(GraphContainer container) {
368
369
	}
370
371
//	/**
372
//	 * Gets a list of nodes below the given node
373
//	 * @param node
374
//	 * @return
375
//	 */
376
//	private List getNodesBelow(int y, List nodes) {
377
//		Iterator allNodes = nodes.iterator();
378
//		LinkedList result = new LinkedList();
379
//		while (allNodes.hasNext()) {
380
//			GraphNode nextNode = (GraphNode) allNodes.next();
381
//			int top = nextNode.getLocation().y;
382
//			if (top > y) {
383
//				result.add(nextNode);
384
//			}
385
//		}
386
//		return result;
387
//	}
388
389
	/**
552
	/**
390
	 * Checks all the nodes in the list of nodesToCheck to see if they intersect with the bounds set
553
	 * Checks all the nodes in the list of nodesToCheck to see if they intersect with the bounds set
391
	 * @param node
554
	 * @param node
Lines 439-561 Link Here
439
		}
602
		}
440
	}
603
	}
441
604
442
//	/**
443
//	 * This finds the highest Y Value of a set of nodes.
444
//	 * @param nodes
445
//	 * @return
446
//	 */
447
//	private int findSmallestYValue(List nodes) {
448
//		Iterator iterator = nodes.iterator();
449
//		int lowestNode /*highest on the screen*/= Integer.MAX_VALUE - 100; // Subtract 100 so we don't overflow
450
//		while (iterator.hasNext()) {
451
//			GraphNode node = (GraphNode) iterator.next();
452
//			int y = node.getLocation().y;
453
//			lowestNode = Math.min(lowestNode, y);
454
//		}
455
//		return lowestNode;
456
//	}
457
458
//	/**
459
//	 * Clears the nodes that the container intersects as it expands
460
//	 * @param containerBounds
461
//	 * @param graphContainer
462
//	 */
463
//	private void moveIntersectedNodes(Rectangle containerBounds, GraphNode graphContainer) {
464
//
465
//		List nodesBelowHere = getNodesBelow(this.getLocation().y, graphContainer.getGraphModel().getNodes());
466
//		List intersectingNodes = intersectingNodes(containerBounds, nodesBelowHere, graphContainer);
467
//		int delta = getMaxMovement(containerBounds, intersectingNodes);
468
//		shiftNodesDown(intersectingNodes, delta);
469
//
470
//		int lowestNode /*highest on the screen*/= findSmallestYValue(intersectingNodes);
471
//		nodesBelowHere = getNodesBelow(lowestNode, nodesBelowHere);
472
//
473
//		while (nodesBelowHere.size() > 0) {
474
//			Iterator intersectingNodeIterator = intersectingNodes.iterator();
475
//			List nodesMovedInLastIteration = new LinkedList();
476
//			while (intersectingNodeIterator.hasNext()) {
477
//				GraphNode node = (GraphNode) intersectingNodeIterator.next();
478
//				intersectingNodes = intersectingNodes(node.getBounds(), nodesBelowHere, node);
479
//				delta = getMaxMovement(node.getBounds(), intersectingNodes);
480
//				if (delta > 0) {
481
//					shiftNodesDown(intersectingNodes, delta);
482
//					nodesMovedInLastIteration.addAll(intersectingNodes);
483
//				}
484
//			}
485
//			lowestNode /*highest on the screen*/= findSmallestYValue(nodesMovedInLastIteration);
486
//			nodesBelowHere = getNodesBelow(lowestNode, nodesBelowHere);
487
//			intersectingNodes = nodesMovedInLastIteration;
488
//		}
489
//	}
490
491
	/**
605
	/**
492
	 * Gets the graph that this container has been added to.
606
	 * Gets the graph that this container has been added to.
493
	 */
607
	 */
494
	public Graph getGraph() {
608
	public Graph getGraph() {
495
		return this.graph.getGraph();
609
		return this.graph;
496
	}
610
	}
497
611
498
	public int getItemType() {
612
	public int getItemType() {
499
		return CONTAINER;
613
		return CONTAINER;
500
	}
614
	}
501
615
502
	/**
503
	 * 
504
	 */
505
	public void setLayoutAlgorithm(LayoutAlgorithm algorithm, boolean applyLayout) {
616
	public void setLayoutAlgorithm(LayoutAlgorithm algorithm, boolean applyLayout) {
617
		if (this.layoutAlgorithm != null) {
618
			this.layoutAlgorithm.setLayoutContext(null);
619
		}
620
506
		this.layoutAlgorithm = algorithm;
621
		this.layoutAlgorithm = algorithm;
622
		this.layoutAlgorithm.setLayoutContext(getLayoutContext());
507
		if (applyLayout) {
623
		if (applyLayout) {
508
			applyLayout();
624
			applyLayout();
509
		}
625
		}
510
511
	}
626
	}
512
627
513
	public void applyLayout() {
628
	InternalLayoutContext getLayoutContext() {
514
		if ((this.getNodes().size() == 0)) {
629
		if (layoutContext == null) {
515
			return;
630
			layoutContext = new InternalLayoutContext(this);
516
		}
631
		}
632
		return layoutContext;
633
	}
517
634
518
		int layoutStyle = 0;
635
	DisplayIndependentRectangle getLayoutBounds() {
519
636
		double width = GraphContainer.SCALED_WIDTH - 10;
520
		if (checkStyle(ZestStyles.NODES_NO_LAYOUT_RESIZE)) {
637
		double height = GraphContainer.SCALED_HEIGHT - 10;
521
			layoutStyle = LayoutStyles.NO_LAYOUT_NODE_RESIZING;
638
		return new DisplayIndependentRectangle(25, 25, width - 50, height - 50);
522
		}
639
	}
523
640
641
	public void applyLayout() {
524
		if (layoutAlgorithm == null) {
642
		if (layoutAlgorithm == null) {
525
			layoutAlgorithm = new TreeLayoutAlgorithm(layoutStyle);
643
			setLayoutAlgorithm(new TreeLayoutAlgorithm(), false);
526
		}
527
528
		layoutAlgorithm.setStyle(layoutAlgorithm.getStyle() | layoutStyle);
529
530
		// calculate the size for the layout algorithm
531
		//Dimension d = this.scalledLayer.getSize();
532
		Dimension d = new Dimension();
533
		d.width = (int) scaledWidth;
534
		d.height = (int) scaledHeight;
535
536
		d.width = d.width - 10;
537
		d.height = d.height - 10;
538
		//if (d.height <= 0) {
539
		//d.height = (CONTAINER_HEIGHT);
540
		//}
541
		//d.scale(1 / this.scalledLayer.getScale());
542
543
		if (d.isEmpty()) {
544
			return;
545
		}
546
		LayoutRelationship[] connectionsToLayout = getGraph().getConnectionsToLayout(getNodes());
547
		LayoutEntity[] nodesToLayout = getGraph().getNodesToLayout(getNodes());
548
549
		try {
550
			Animation.markBegin();
551
			layoutAlgorithm.applyLayout(nodesToLayout, connectionsToLayout, 25, 25, d.width - 50, d.height - 50, false, false);
552
			Animation.run(ANIMATION_TIME);
553
			getFigure().getUpdateManager().performUpdate();
554
555
		} catch (InvalidLayoutConfiguration e) {
556
			e.printStackTrace();
557
		}
644
		}
558
645
		Animation.markBegin();
646
		layoutAlgorithm.applyLayout();
647
		layoutContext.flushChanges(false);
648
		Animation.run(ANIMATION_TIME);
649
		getFigure().getUpdateManager().performUpdate();
559
	}
650
	}
560
651
561
	/**
652
	/**
Lines 616-651 Link Here
616
			labelWidth = MIN_WIDTH;
707
			labelWidth = MIN_WIDTH;
617
			expandGraphLabel.setPreferredSize(labelWidth, labelHeight);
708
			expandGraphLabel.setPreferredSize(labelWidth, labelHeight);
618
		}
709
		}
619
		if (labelHeight < 30) {
620
			labelHeight = 30;
621
		}
622
710
623
		dimension.labelHeight = labelHeight;
711
		dimension.labelHeight = Math.max(labelHeight, MIN_HEIGHT);
624
		dimension.width = labelWidth;
712
		dimension.width = Math.max(labelWidth, this.size.width);
625
		dimension.width = Math.max(dimension.width, this.size.width);
713
		dimension.expandedHeight = Math.max(dimension.labelHeight + childAreaHeight - SUBLAYER_OFFSET, this.size.height);
626
		dimension.expandedHeight = dimension.labelHeight + childAreaHeight - SUBLAYER_OFFSET;
627
		dimension.expandedHeight = Math.max(dimension.expandedHeight, this.size.height);
628
714
629
		return dimension;
715
		return dimension;
630
	}
716
	}
631
717
632
	/*
633
	private double computeChildScale() {
634
		Dimension childArea = computeChildArea();
635
		double widthScale = childArea.width / scaledWidth;
636
		double heightScale = childArea.height / scaledHeight;
637
		return Math.min(widthScale, heightScale);
638
	}
639
	*/
640
	private double computeHeightScale() {
718
	private double computeHeightScale() {
641
		Dimension childArea = computeChildArea();
719
		Dimension childArea = computeChildArea();
642
		double heightScale = childArea.height / scaledHeight;
720
		double heightScale = childArea.height / SCALED_HEIGHT;
643
		return heightScale;
721
		return heightScale;
644
	}
722
	}
645
723
646
	private double computeWidthScale() {
724
	private double computeWidthScale() {
647
		Dimension childArea = computeChildArea();
725
		Dimension childArea = computeChildArea();
648
		double widthScale = childArea.width / scaledWidth;
726
		double widthScale = childArea.width / SCALED_WIDTH;
649
		return widthScale;
727
		return widthScale;
650
	}
728
	}
651
729
Lines 666-715 Link Here
666
		scrollPane.addLayoutListener(LayoutAnimator.getDefault());
744
		scrollPane.addLayoutListener(LayoutAnimator.getDefault());
667
745
668
		Viewport viewport = new FreeformViewport();
746
		Viewport viewport = new FreeformViewport();
669
		/*
670
		 * This is the code that helps remove the scroll bars moving when the nodes
671
		 * are dragged.  
672
		 *
673
		viewport.setHorizontalRangeModel(new DefaultRangeModel() {
674
			public void setAll(int min, int ext, int max) {
675
				System.out.println("Max: " + max + " : current Max:  " + getMaximum());
676
				if (max < getMaximum()) {
677
					max = getMaximum();
678
				}
679
				super.setAll(min, ext, max);
680
			}
681
682
			public void setMaximum(int maximum) {
683
				// TODO Auto-generated method stub
684
				System.out.println("Max: " + maximum + " : current Max:  " + getMaximum());
685
				if (maximum < getMaximum()) {
686
					return;
687
				}
688
				super.setMaximum(maximum);
689
			}
690
		});
691
		*/
692
747
693
		scrollPane.setViewport(viewport);
748
		scrollPane.setViewport(viewport);
694
		viewport.addLayoutListener(LayoutAnimator.getDefault());
749
		viewport.addLayoutListener(LayoutAnimator.getDefault());
695
		scrollPane.setScrollBarVisibility(ScrollPane.AUTOMATIC);
750
		scrollPane.setScrollBarVisibility(ScrollPane.AUTOMATIC);
696
751
697
		//scalledLayer = new ScalableFreeformLayeredPane();
698
		scalledLayer = new AspectRatioFreeformLayer("debug label");
752
		scalledLayer = new AspectRatioFreeformLayer("debug label");
699
		scalledLayer.addLayoutListener(LayoutAnimator.getDefault());
753
		scalledLayer.addLayoutListener(LayoutAnimator.getDefault());
700
		//scalledLayer.setScale(computeChildScale());
701
		scalledLayer.setScale(computeWidthScale(), computeHeightScale());
754
		scalledLayer.setScale(computeWidthScale(), computeHeightScale());
702
		//container = new FreeformLayer();
703
		//edgeLayer = new FreeformLayer();
704
		zestLayer = new ZestRootLayer();
755
		zestLayer = new ZestRootLayer();
705
		zestLayer.addLayoutListener(LayoutAnimator.getDefault());
756
		zestLayer.addLayoutListener(LayoutAnimator.getDefault());
706
		//container.addLayoutListener(LayoutAnimator.getDefault());
707
		//edgeLayer.addLayoutListener(LayoutAnimator.getDefault());
708
		//scalledLayer.add(edgeLayer);
709
		//scalledLayer.add(container);
710
		scalledLayer.add(zestLayer);
757
		scalledLayer.add(zestLayer);
711
758
712
		//container.setLayoutManager(new FreeformLayout());
713
		zestLayer.setLayoutManager(new FreeformLayout());
759
		zestLayer.setLayoutManager(new FreeformLayout());
714
		scrollPane.setSize(computeChildArea());
760
		scrollPane.setSize(computeChildArea());
715
		scrollPane.setLocation(new Point(0, containerDimension.labelHeight - SUBLAYER_OFFSET));
761
		scrollPane.setLocation(new Point(0, containerDimension.labelHeight - SUBLAYER_OFFSET));
Lines 728-733 Link Here
728
		return containerFigure;
774
		return containerFigure;
729
	}
775
	}
730
776
777
	private void registerToParent(NodeContainerAdapter parent) {
778
		if (parent.getItemType() == GRAPH) {
779
			createSelectionListener();
780
			parent.getGraph().addSelectionListener(selectionListener);
781
		}
782
	}
783
784
	private void createSelectionListener() {
785
		if (selectionListener == null) {
786
			selectionListener = new SelectionListener() {
787
				public void widgetSelected(SelectionEvent e) {
788
					if (e.item instanceof GraphContainer) {
789
						//set focus to expand label so that pressing space opens/closes
790
						//the last selected container
791
						((GraphContainer) e.item).expandGraphLabel.setFocus();
792
					}
793
				}
794
795
				public void widgetDefaultSelected(SelectionEvent e) {
796
					// ignore						
797
				}
798
			};
799
800
		}
801
	}
802
731
	protected void updateFigureForModel(IFigure currentFigure) {
803
	protected void updateFigureForModel(IFigure currentFigure) {
732
804
733
		expandGraphLabel.setTextT(getText());
805
		expandGraphLabel.setTextT(getText());
Lines 774-780 Link Here
774
		refreshLocation();
846
		refreshLocation();
775
		figure.getUpdateManager().performValidation();
847
		figure.getUpdateManager().performValidation();
776
		*/
848
		*/
777
778
	}
849
	}
779
850
780
	protected void refreshLocation() {
851
	protected void refreshLocation() {
Lines 803-835 Link Here
803
		scalledLayer.setScale(computeWidthScale(), computeHeightScale());
874
		scalledLayer.setScale(computeWidthScale(), computeHeightScale());
804
	}
875
	}
805
876
806
	void addConnectionFigure(PolylineConnection connection) {
877
	void addFigure(IFigure figure) {
807
		nodeFigure.add(connection);
878
		nodeFigure.add(figure);
808
		//zestLayer.addConnection(connection);
809
	}
879
	}
810
880
811
	void addNode(GraphNode node) {
881
	void addNode(GraphNode node) {
812
		zestLayer.addNode(node.getNodeFigure());
882
		zestLayer.addNode(node.getNodeFigure());
813
		this.childNodes.add(node);
883
		this.childNodes.add(node);
814
		//container.add(node.getNodeFigure());
884
		node.setVisible(isExpanded);
815
		//graph.registerItem(node);
816
	}
885
	}
817
886
818
	void addNode(GraphContainer container) {
887
	void addNode(GraphContainer container) {
819
		// Containers cannot be added to other containers (yet)
888
		throw new RuntimeException("Containers cannot be added to other containers (yet)");
820
	}
889
	}
821
890
822
	public List getNodes() {
891
	public List getNodes() {
823
		return this.childNodes;
892
		return this.childNodes;
824
	}
893
	}
825
826
	void paint() {
827
		Iterator iterator = getNodes().iterator();
828
829
		while (iterator.hasNext()) {
830
			GraphNode node = (GraphNode) iterator.next();
831
			node.paint();
832
		}
833
	}
834
835
}
894
}
(-)src/org/eclipse/zest/core/widgets/IContainer.java (-64 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright 2005-2007, CHISEL Group, University of Victoria, Victoria, BC, Canada.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     The Chisel Group, University of Victoria
10
 *******************************************************************************/
11
package org.eclipse.zest.core.widgets;
12
13
import java.util.List;
14
15
import org.eclipse.zest.layouts.LayoutAlgorithm;
16
17
/**
18
 * This interface describes all Zest components that are Containers. This is an internal interface
19
 * and thus should not be used outside of Zest.  Implementors of this interface must include the 
20
 * following two methods
21
 *   o addNode(GraphNode)
22
 *   o addNode(GraphContainer)
23
 *   
24
 * These are not actually listed here because Java does not allow protected methods in
25
 * interfaces.
26
 * 
27
 * @author Ian Bull
28
 */
29
public interface IContainer {
30
31
	public Graph getGraph();
32
33
	// All implementers must include this method
34
	/* protected void addNode(GraphNode node); */
35
36
	// All implementers must include this method
37
	/* protected void addNode(GraphContainer container); */
38
39
	public int getItemType();
40
41
	/**
42
	 * Re-applies the current layout algorithm
43
	 */
44
	public void applyLayout();
45
46
	/**
47
	 * Sets the LayoutAlgorithm for this container and optionally applies it.
48
	 *  
49
	 * @param algorithm The layout algorithm to set
50
	 * @param applyLayout 
51
	 */
52
	public void setLayoutAlgorithm(LayoutAlgorithm algorithm, boolean applyLayout);
53
54
	public List getNodes();
55
56
	/* protected void highlightNode(GraphNode node); */
57
58
	/* protected void highlightNode(GraphContainer container);*/
59
60
	/* protected void unhighlightNode(GraphNode node); */
61
62
	/* protected void unhighlightNode(GraphContainer container);*/
63
64
} // end of IContainer
(-)src/org/eclipse/zest/core/widgets/GraphConnection.java (-93 / +73 lines)
Lines 1-12 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:
9
 *     The Chisel Group, University of Victoria
10
 *     Mateusz Matela <mateusz.matela@gmail.com> - Adapt Zest to changes in layout - https://bugs.eclipse.org/bugs/show_bug.cgi?id=283179
9
 ******************************************************************************/
11
 ******************************************************************************/
12
10
package org.eclipse.zest.core.widgets;
13
package org.eclipse.zest.core.widgets;
11
14
12
import org.eclipse.draw2d.ChopboxAnchor;
15
import org.eclipse.draw2d.ChopboxAnchor;
Lines 28-39 Link Here
28
import org.eclipse.zest.core.widgets.internal.PolylineArcConnection;
31
import org.eclipse.zest.core.widgets.internal.PolylineArcConnection;
29
import org.eclipse.zest.core.widgets.internal.RoundedChopboxAnchor;
32
import org.eclipse.zest.core.widgets.internal.RoundedChopboxAnchor;
30
import org.eclipse.zest.core.widgets.internal.ZestRootLayer;
33
import org.eclipse.zest.core.widgets.internal.ZestRootLayer;
31
import org.eclipse.zest.layouts.LayoutBendPoint;
34
import org.eclipse.zest.layouts.ConnectionLayout;
32
import org.eclipse.zest.layouts.LayoutEntity;
35
import org.eclipse.zest.layouts.NodeLayout;
33
import org.eclipse.zest.layouts.LayoutRelationship;
34
import org.eclipse.zest.layouts.constraints.LayoutConstraint;
35
36
36
/*
37
/**
37
 * This is the graph connection model which stores the source and destination
38
 * This is the graph connection model which stores the source and destination
38
 * nodes and the properties of this connection (color, line width etc).
39
 * nodes and the properties of this connection (color, line width etc).
39
 * 
40
 * 
Lines 53-59 Link Here
53
	private Color foreground;
54
	private Color foreground;
54
	private int lineWidth;
55
	private int lineWidth;
55
	private int lineStyle;
56
	private int lineStyle;
56
	private final Graph graphModel;
57
	private final Graph graph;
57
58
58
	private int connectionStyle;
59
	private int connectionStyle;
59
	private int curveDepth;
60
	private int curveDepth;
Lines 72-78 Link Here
72
	private IFigure tooltip;
73
	private IFigure tooltip;
73
74
74
	private boolean highlighted;
75
	private boolean highlighted;
75
	private GraphLayoutConnection layoutConnection = null;
76
	private boolean hasCustomTooltip;
76
	private boolean hasCustomTooltip;
77
77
78
	public GraphConnection(Graph graphModel, int style, GraphNode source, GraphNode destination) {
78
	public GraphConnection(Graph graphModel, int style, GraphNode source, GraphNode destination) {
Lines 88-97 Link Here
88
		this.highlightColor = graphModel.DARK_BLUE;
88
		this.highlightColor = graphModel.DARK_BLUE;
89
		this.lineWidth = 1;
89
		this.lineWidth = 1;
90
		this.lineStyle = Graphics.LINE_SOLID;
90
		this.lineStyle = Graphics.LINE_SOLID;
91
		setWeight(weight);
91
		setWeight(1.0);
92
		this.graphModel = graphModel;
92
		this.graph = graphModel;
93
		this.curveDepth = 0;
93
		this.curveDepth = 0;
94
		this.layoutConnection = new GraphLayoutConnection();
95
		this.font = Display.getDefault().getSystemFont();
94
		this.font = Display.getDefault().getSystemFont();
96
		registerConnection(source, destination);
95
		registerConnection(source, destination);
97
	}
96
	}
Lines 109-124 Link Here
109
		if (source.getParent().getItemType() == GraphItem.CONTAINER && destination.getParent().getItemType() == GraphItem.CONTAINER && (source.getParent() == destination.getParent())) {
108
		if (source.getParent().getItemType() == GraphItem.CONTAINER && destination.getParent().getItemType() == GraphItem.CONTAINER && (source.getParent() == destination.getParent())) {
110
			// 196189: Edges should not draw on the edge layer if both the src and dest are in the same container
109
			// 196189: Edges should not draw on the edge layer if both the src and dest are in the same container
111
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=196189
110
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=196189
112
			graphModel.addConnection(this, ZestRootLayer.EDGES_ON_TOP);
111
			graph.addConnection(this, ZestRootLayer.EDGES_ON_TOP);
113
		} else {
112
		} else {
114
			graphModel.addConnection(this, true);
113
			graph.addConnection(this, true);
115
		}
114
		}
116
115
117
		if ((source.getParent()).getItemType() == GraphItem.CONTAINER) {
116
		if ((source.getParent()).getItemType() == GraphItem.CONTAINER) {
118
			// If the container of the source is a container, we need to draw another
117
			// If the container of the source is a container, we need to draw another
119
			// arc on that arc layer
118
			// arc on that arc layer
120
			sourceContainerConnectionFigure = doCreateFigure();
119
			sourceContainerConnectionFigure = doCreateFigure();
121
			((GraphContainer) source.getParent()).addConnectionFigure((PolylineConnection) sourceContainerConnectionFigure);
120
			((GraphContainer) source.getParent().getAdaptee()).addFigure(sourceContainerConnectionFigure);
122
			this.setVisible(false);
121
			this.setVisible(false);
123
		}
122
		}
124
123
Lines 126-135 Link Here
126
			// If the container of the source is a container, we need to draw another
125
			// If the container of the source is a container, we need to draw another
127
			// arc on that arc layer
126
			// arc on that arc layer
128
			targetContainerConnectionFigure = doCreateFigure();
127
			targetContainerConnectionFigure = doCreateFigure();
129
			((GraphContainer) destination.getParent()).addConnectionFigure((PolylineConnection) targetContainerConnectionFigure);
128
			((GraphContainer) destination.getParent().getAdaptee()).addFigure(targetContainerConnectionFigure);
130
			this.setVisible(false);
129
			this.setVisible(false);
131
		}
130
		}
132
		graphModel.getGraph().registerItem(this);
131
		graph.registerItem(this);
133
	}
132
	}
134
133
135
	void removeFigure() {
134
	void removeFigure() {
Lines 157-163 Link Here
157
		this.isDisposed = true;
156
		this.isDisposed = true;
158
		(getSource()).removeSourceConnection(this);
157
		(getSource()).removeSourceConnection(this);
159
		(getDestination()).removeTargetConnection(this);
158
		(getDestination()).removeTargetConnection(this);
160
		graphModel.removeConnection(this);
159
		graph.removeConnection(this);
161
		if (sourceContainerConnectionFigure != null) {
160
		if (sourceContainerConnectionFigure != null) {
162
			sourceContainerConnectionFigure.getParent().remove(sourceContainerConnectionFigure);
161
			sourceContainerConnectionFigure.getParent().remove(sourceContainerConnectionFigure);
163
		}
162
		}
Lines 172-193 Link Here
172
171
173
	public Connection getConnectionFigure() {
172
	public Connection getConnectionFigure() {
174
		if (connectionFigure == null) {
173
		if (connectionFigure == null) {
175
			connectionFigure = createFigure();
174
			connectionFigure = doCreateFigure();
176
		}
175
		}
177
		return connectionFigure;
176
		return connectionFigure;
178
	}
177
	}
179
178
180
	/**
179
	/**
181
	 * Gets a proxy to this connection that can be used with the Zest layout
182
	 * engine
183
	 * 
184
	 * @return
185
	 */
186
	public LayoutRelationship getLayoutRelationship() {
187
		return this.layoutConnection;
188
	}
189
190
	/**
191
	 * Gets the external connection object.
180
	 * Gets the external connection object.
192
	 * 
181
	 * 
193
	 * @return Object
182
	 * @return Object
Lines 202-212 Link Here
202
	 * @return String
191
	 * @return String
203
	 */
192
	 */
204
	public String toString() {
193
	public String toString() {
205
		String arrow = (isBidirectionalInLayout() ? " <--> " : " --> ");
194
		StringBuffer buffer = new StringBuffer("GraphModelConnection: ");
206
		String src = (sourceNode != null ? sourceNode.getText() : "null");
195
		buffer.append(sourceNode != null ? sourceNode.getText() : "null");
207
		String dest = (destinationNode != null ? destinationNode.getText() : "null");
196
		buffer.append(isDirected() ? " --> " : " --- ");
208
		String weight = "  (weight=" + getWeightInLayout() + ")";
197
		buffer.append(destinationNode != null ? destinationNode.getText() : "null");
209
		return ("GraphModelConnection: " + src + arrow + dest + weight);
198
		buffer.append("  (weight=").append(getWeightInLayout()).append(")");
199
		return buffer.toString();
210
	}
200
	}
211
201
212
	/**
202
	/**
Lines 415-421 Link Here
415
		}
405
		}
416
		highlighted = true;
406
		highlighted = true;
417
		updateFigure(connectionFigure);
407
		updateFigure(connectionFigure);
418
		graphModel.highlightEdge(this);
408
		graph.highlightEdge(this);
419
	}
409
	}
420
410
421
	/**
411
	/**
Lines 427-433 Link Here
427
		}
417
		}
428
		highlighted = false;
418
		highlighted = false;
429
		updateFigure(connectionFigure);
419
		updateFigure(connectionFigure);
430
		graphModel.unhighlightEdge(this);
420
		graph.unhighlightEdge(this);
431
	}
421
	}
432
422
433
	/**
423
	/**
Lines 445-451 Link Here
445
	 * @return The graph model that this connection is contained in
435
	 * @return The graph model that this connection is contained in
446
	 */
436
	 */
447
	public Graph getGraphModel() {
437
	public Graph getGraphModel() {
448
		return this.graphModel;
438
		return this.graph;
449
	}
439
	}
450
440
451
	/**
441
	/**
Lines 461-469 Link Here
461
		if (this.curveDepth == 0 && depth != 0 || this.curveDepth != 0 && depth == 0) {
451
		if (this.curveDepth == 0 && depth != 0 || this.curveDepth != 0 && depth == 0) {
462
			// There is currently no curve, so we have to create
452
			// There is currently no curve, so we have to create
463
			// a curved connection
453
			// a curved connection
464
			graphModel.removeConnection(this);
454
			graph.removeConnection(this);
465
			this.curveDepth = depth;
455
			this.curveDepth = depth;
466
			this.connectionFigure = createFigure();
456
			this.connectionFigure = doCreateFigure();
467
			registerConnection(sourceNode, destinationNode);
457
			registerConnection(sourceNode, destinationNode);
468
			updateFigure(this.connectionFigure);
458
			updateFigure(this.connectionFigure);
469
		} else {
459
		} else {
Lines 487-493 Link Here
487
	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.GraphItem#setVisible(boolean)
477
	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.GraphItem#setVisible(boolean)
488
	 */
478
	 */
489
	public void setVisible(boolean visible) {
479
	public void setVisible(boolean visible) {
490
		//graphModel.addRemoveFigure(this, visible);
491
		if (getSource().isVisible() && getDestination().isVisible() && visible) {
480
		if (getSource().isVisible() && getDestination().isVisible() && visible) {
492
			this.getFigure().setVisible(visible);
481
			this.getFigure().setVisible(visible);
493
			if (sourceContainerConnectionFigure != null) {
482
			if (sourceContainerConnectionFigure != null) {
Lines 532-537 Link Here
532
		}
521
		}
533
	}
522
	}
534
523
524
	public boolean isDirected() {
525
		return ZestStyles.checkStyle(connectionStyle, ZestStyles.CONNECTIONS_DIRECTED);
526
	}
527
528
	public void setDirected(boolean directed) {
529
		if (directed) {
530
			setConnectionStyle(connectionStyle | ZestStyles.CONNECTIONS_DIRECTED);
531
		} else {
532
			setConnectionStyle(connectionStyle & (-1 - ZestStyles.CONNECTIONS_DIRECTED));
533
		}
534
	}
535
535
	PolylineConnection getSourceContainerConnectionFigure() {
536
	PolylineConnection getSourceContainerConnectionFigure() {
536
		return (PolylineConnection) sourceContainerConnectionFigure;
537
		return (PolylineConnection) sourceContainerConnectionFigure;
537
	}
538
	}
Lines 559-565 Link Here
559
		connectionShape.setLineStyle(getLineStyle());
560
		connectionShape.setLineStyle(getLineStyle());
560
561
561
		if (this.getText() != null || this.getImage() != null) {
562
		if (this.getText() != null || this.getImage() != null) {
562
			//Label l = new Label(this.getText(), this.getImage());
563
			if (this.getImage() != null) {
563
			if (this.getImage() != null) {
564
				this.connectionLabel.setIcon(this.getImage());
564
				this.connectionLabel.setIcon(this.getImage());
565
			}
565
			}
Lines 602-625 Link Here
602
		connection.setToolTip(toolTip);
602
		connection.setToolTip(toolTip);
603
	}
603
	}
604
604
605
	private Connection createFigure() {
606
		/*
607
		if ((sourceNode.getParent()).getItemType() == GraphItem.CONTAINER) {
608
			GraphContainer container = (GraphContainer) sourceNode.getParent();
609
			sourceContainerConnectionFigure = doCreateFigure();
610
			container.addConnectionFigure((PolylineConnection) sourceContainerConnectionFigure);
611
		}
612
		if ((destinationNode.getParent()).getItemType() == GraphItem.CONTAINER) {
613
			GraphContainer container = (GraphContainer) destinationNode.getParent();
614
			targetContainerConnectionFigure = doCreateFigure();
615
			container.addConnectionFigure((PolylineConnection) targetContainerConnectionFigure);
616
		}
617
		*/
618
619
		return doCreateFigure();
620
621
	}
622
623
	private Connection doCreateFigure() {
605
	private Connection doCreateFigure() {
624
		Connection connectionFigure = null;
606
		Connection connectionFigure = null;
625
		ChopboxAnchor sourceAnchor = null;
607
		ChopboxAnchor sourceAnchor = null;
Lines 661-718 Link Here
661
		return connectionFigure;
643
		return connectionFigure;
662
	}
644
	}
663
645
664
	/*
646
	IFigure getFigure() {
665
	 * (non-Javadoc)
647
		return this.getConnectionFigure();
666
	 * 
667
	 * @see org.eclipse.mylar.zest.layouts.LayoutRelationship#isBidirectionalInLayout()
668
	 */
669
	private boolean isBidirectionalInLayout() {
670
		return !ZestStyles.checkStyle(connectionStyle, ZestStyles.CONNECTIONS_DIRECTED);
671
	}
648
	}
672
649
673
	class GraphLayoutConnection implements LayoutRelationship {
650
	private InternalConnectionLayout layout;
674
675
		Object layoutInformation = null;
676
651
677
		public void clearBendPoints() {
652
	InternalConnectionLayout getLayout() {
678
			// @tag TODO : add bendpoints
653
		if (layout == null) {
654
			layout = new InternalConnectionLayout();
679
		}
655
		}
656
		return layout;
657
	}
680
658
681
		public LayoutEntity getDestinationInLayout() {
659
	class InternalConnectionLayout implements ConnectionLayout {
682
			return getDestination().getLayoutEntity();
660
		private boolean visible = GraphConnection.this.isVisible();
683
		}
684
661
685
		public Object getLayoutInformation() {
662
		public NodeLayout getSource() {
686
			return layoutInformation;
663
			return sourceNode.getLayout();
687
		}
664
		}
688
665
689
		public LayoutEntity getSourceInLayout() {
666
		public NodeLayout getTarget() {
690
			return getSource().getLayoutEntity();
667
			return destinationNode.getLayout();
691
		}
668
		}
692
669
693
		public void populateLayoutConstraint(LayoutConstraint constraint) {
670
		public double getWeight() {
694
			graphModel.invokeConstraintAdapters(GraphConnection.this, constraint);
671
			return GraphConnection.this.getWeightInLayout();
695
		}
672
		}
696
673
697
		public void setBendPoints(LayoutBendPoint[] bendPoints) {
674
		public boolean isDirected() {
698
			// @tag TODO : add bendpoints
675
			return !ZestStyles.checkStyle(getConnectionStyle(), ZestStyles.CONNECTIONS_DIRECTED);
699
		}
676
		}
700
677
701
		public void setLayoutInformation(Object layoutInformation) {
678
		public boolean isVisible() {
702
			this.layoutInformation = layoutInformation;
679
			return visible;
703
		}
680
		}
704
681
705
		public Object getGraphData() {
682
		public void setVisible(boolean visible) {
706
			return GraphConnection.this;
683
			this.visible = visible;
707
		}
684
		}
708
685
709
		public void setGraphData(Object o) {
686
		void applyLayout() {
710
687
			if (GraphConnection.this.isVisible() != this.visible) {
688
				GraphConnection.this.setVisible(this.visible);
689
			}
711
		}
690
		}
712
713
	}
691
	}
714
692
715
	IFigure getFigure() {
693
	void applyLayoutChanges() {
716
		return this.getConnectionFigure();
694
		if (layout != null) {
695
			layout.applyLayout();
696
		}
717
	}
697
	}
718
}
698
}
(-)src/org/eclipse/zest/core/widgets/ConstraintAdapter.java (-31 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     The Chisel Group, University of Victoria
10
 *******************************************************************************/
11
package org.eclipse.zest.core.widgets;
12
13
import org.eclipse.zest.layouts.constraints.LayoutConstraint;
14
15
/**
16
 * 
17
 * This interface is used to populate layout constraints on Zest nodes.
18
 * Constraint will be a instance of LayoutConstraint (look at the heirarchy for an up-to-date list).
19
 * 
20
 * @author Ian Bull
21
 */
22
public interface ConstraintAdapter {
23
	
24
	/**
25
	 * 
26
	 * @param object
27
	 * @param constraint
28
	 */
29
	public void populateConstraint(Object object, LayoutConstraint constraint);
30
31
}
(-)src/org/eclipse/zest/core/widgets/GraphItem.java (-4 / +7 lines)
Lines 1-12 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:
9
 *     The Chisel Group, University of Victoria
10
 *     Mateusz Matela <mateusz.matela@gmail.com> - Adapt Zest to changes in layout - https://bugs.eclipse.org/bugs/show_bug.cgi?id=283179
9
 ******************************************************************************/
11
 ******************************************************************************/
12
10
package org.eclipse.zest.core.widgets;
13
package org.eclipse.zest.core.widgets;
11
14
12
import org.eclipse.draw2d.IFigure;
15
import org.eclipse.draw2d.IFigure;
(-)src/org/eclipse/zest/core/widgets/CGraphNode.java (-1 / +17 lines)
Lines 1-3 Link Here
1
/*******************************************************************************
2
 * Copyright 2005-2009, CHISEL Group, University of Victoria, Victoria, BC,
3
 * Canada. All rights reserved. This program and the accompanying materials are
4
 * made available under the terms of the Eclipse Public License v1.0 which
5
 * accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     The Chisel Group, University of Victoria
10
 *     Mateusz Matela <mateusz.matela@gmail.com> - Adapt Zest to changes in layout - https://bugs.eclipse.org/bugs/show_bug.cgi?id=283179
11
 ******************************************************************************/
12
1
package org.eclipse.zest.core.widgets;
13
package org.eclipse.zest.core.widgets;
2
14
3
import org.eclipse.draw2d.IFigure;
15
import org.eclipse.draw2d.IFigure;
Lines 11-17 Link Here
11
23
12
	IFigure figure = null;
24
	IFigure figure = null;
13
25
14
	public CGraphNode(IContainer graphModel, int style, IFigure figure) {
26
	public CGraphNode(Graph graphModel, int style, IFigure figure) {
27
		super(graphModel, style, figure);
28
	}
29
30
	public CGraphNode(GraphContainer graphModel, int style, IFigure figure) {
15
		super(graphModel, style, figure);
31
		super(graphModel, style, figure);
16
	}
32
	}
17
33
(-)src/org/eclipse/zest/core/widgets/InternalNodeLayout.java (+201 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Mateusz Matela and others. All rights reserved. This
3
 * program and the accompanying materials are made available under the terms of
4
 * the Eclipse Public License v1.0 which accompanies this distribution, and is
5
 * available at http://www.eclipse.org/legal/epl-v10.html
6
 * 
7
 * Contributors:
8
 * 	   Mateusz Matela <mateusz.matela@gmail.com> - initial API and implementation
9
 *******************************************************************************/
10
11
package org.eclipse.zest.core.widgets;
12
13
import java.util.ArrayList;
14
import java.util.Iterator;
15
16
import org.eclipse.draw2d.geometry.Dimension;
17
import org.eclipse.draw2d.geometry.Point;
18
import org.eclipse.zest.layouts.ConnectionLayout;
19
import org.eclipse.zest.layouts.EntityLayout;
20
import org.eclipse.zest.layouts.NodeLayout;
21
import org.eclipse.zest.layouts.SubgraphLayout;
22
import org.eclipse.zest.layouts.dataStructures.DisplayIndependentDimension;
23
import org.eclipse.zest.layouts.dataStructures.DisplayIndependentPoint;
24
25
class InternalNodeLayout implements NodeLayout {
26
	private DisplayIndependentPoint location;
27
	private DisplayIndependentDimension size;
28
	private boolean minimized = false;
29
	private final GraphNode node;
30
	private final InternalLayoutContext ownerLayoutContext;
31
	private SubgraphLayout subgraph;
32
33
	public InternalNodeLayout(GraphNode graphNode) {
34
		this.node = graphNode;
35
		this.ownerLayoutContext = node.parent.getLayoutContext();
36
	}
37
38
	public DisplayIndependentPoint getLocation() {
39
		if (location == null) {
40
			Point location2 = node.getLocation();
41
			location = new DisplayIndependentPoint(location2.x + getSize().width / 2, location2.y + size.height / 2);
42
		}
43
		return new DisplayIndependentPoint(location);
44
	}
45
46
	public DisplayIndependentDimension getSize() {
47
		if (size == null) {
48
			Dimension size2 = node.getSize();
49
			size = new DisplayIndependentDimension(size2.width, size2.height);
50
		}
51
		return new DisplayIndependentDimension(size);
52
	}
53
54
	public SubgraphLayout getSubgraph() {
55
		return subgraph;
56
	}
57
58
	public boolean isMovable() {
59
		return true;
60
	}
61
62
	public boolean isPrunable() {
63
		return ownerLayoutContext.isPruningEnabled();
64
	}
65
66
	public boolean isPruned() {
67
		return subgraph != null;
68
	}
69
70
	public boolean isResizable() {
71
		return (node.parent.getAdaptee().getStyle() & ZestStyles.NODES_NO_LAYOUT_RESIZE) == 0;
72
	}
73
74
	public void prune(SubgraphLayout subgraph) {
75
		if (subgraph == this.subgraph) {
76
			return;
77
		}
78
		if (this.subgraph != null) {
79
			SubgraphLayout subgraph2 = this.subgraph;
80
			this.subgraph = null;
81
			subgraph2.removeNodes(new NodeLayout[] { this });
82
		}
83
		if (subgraph != null) {
84
			this.subgraph = subgraph;
85
			subgraph.addNodes(new NodeLayout[] { this });
86
		}
87
	}
88
89
	public void setLocation(double x, double y) {
90
		location = new DisplayIndependentPoint(x, y);
91
	}
92
93
	public void setSize(double width, double height) {
94
		size = new DisplayIndependentDimension(width, height);
95
	}
96
97
	public void setMinimized(boolean minimized) {
98
		getSize();
99
		this.minimized = minimized;
100
	}
101
102
	public boolean isMinimized() {
103
		return minimized;
104
	}
105
106
	public NodeLayout[] getPredecessingNodes() {
107
		ConnectionLayout[] connections = getIncomingConnections();
108
		NodeLayout[] result = new NodeLayout[connections.length];
109
		for (int i = 0; i < connections.length; i++) {
110
			result[i] = connections[i].getSource();
111
			if (result[i] == this) {
112
				result[i] = connections[i].getTarget();
113
			}
114
		}
115
		return result;
116
	}
117
118
	public NodeLayout[] getSuccessingNodes() {
119
		ConnectionLayout[] connections = getOutgoingConnections();
120
		NodeLayout[] result = new NodeLayout[connections.length];
121
		for (int i = 0; i < connections.length; i++) {
122
			result[i] = connections[i].getTarget();
123
			if (result[i] == this) {
124
				result[i] = connections[i].getSource();
125
			}
126
		}
127
		return result;
128
	}
129
130
	public EntityLayout[] getSuccessingEntities() {
131
		// TODO Auto-generated method stub
132
		return getSuccessingNodes();
133
	}
134
135
	public EntityLayout[] getPredecessingEntities() {
136
		// TODO Auto-generated method stub
137
		return getPredecessingNodes();
138
	}
139
140
	public ConnectionLayout[] getIncomingConnections() {
141
		ArrayList result = new ArrayList();
142
		for (Iterator iterator = node.getTargetConnections().iterator(); iterator.hasNext();) {
143
			GraphConnection connection = (GraphConnection) iterator.next();
144
			if (!ownerLayoutContext.isLayoutItemFiltered(connection)) {
145
				result.add(connection.getLayout());
146
			}
147
		}
148
		for (Iterator iterator = node.getSourceConnections().iterator(); iterator.hasNext();) {
149
			GraphConnection connection = (GraphConnection) iterator.next();
150
			if (!connection.isDirected() && !ownerLayoutContext.isLayoutItemFiltered(connection)) {
151
				result.add(connection.getLayout());
152
			}
153
		}
154
		return (ConnectionLayout[]) result.toArray(new ConnectionLayout[result.size()]);
155
	}
156
157
	public ConnectionLayout[] getOutgoingConnections() {
158
		ArrayList result = new ArrayList();
159
		for (Iterator iterator = node.getSourceConnections().iterator(); iterator.hasNext();) {
160
			GraphConnection connection = (GraphConnection) iterator.next();
161
			if (!ownerLayoutContext.isLayoutItemFiltered(connection)) {
162
				result.add(connection.getLayout());
163
			}
164
		}
165
		for (Iterator iterator = node.getTargetConnections().iterator(); iterator.hasNext();) {
166
			GraphConnection connection = (GraphConnection) iterator.next();
167
			if (!connection.isDirected() && !ownerLayoutContext.isLayoutItemFiltered(connection)) {
168
				result.add(connection.getLayout());
169
			}
170
		}
171
		return (ConnectionLayout[]) result.toArray(new ConnectionLayout[result.size()]);
172
	}
173
174
	public double getPreferredAspectRatio() {
175
		return 0;
176
	}
177
178
	void applyLayout() {
179
		if (minimized) {
180
			node.setSize(0, 0);
181
			if (location != null) {
182
				node.setLocation(location.x, location.y);
183
			}
184
		} else {
185
			if (location != null) {
186
				node.setLocation(location.x - getSize().width / 2, location.y - size.height / 2);
187
			}
188
			if (size != null) {
189
				node.setSize(size.width, size.height);
190
			}
191
		}
192
	}
193
194
	InternalLayoutContext getOwnerLayoutContext() {
195
		return ownerLayoutContext;
196
	}
197
198
	public String toString() {
199
		return node.toString() + "(layout)";
200
	}
201
}
(-)src/org/eclipse/zest/core/widgets/LayoutFilter.java (+35 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright 2005, 2009 CHISEL Group, University of Victoria, Victoria, BC, Canada.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     The Chisel Group, University of Victoria
10
 *     Mateusz Matela <mateusz.matela@gmail.com> - Adapt Zest to changes in layout - https://bugs.eclipse.org/bugs/show_bug.cgi?id=283179
11
 *******************************************************************************/
12
package org.eclipse.zest.core.widgets;
13
14
/**
15
 * A filter is used to filter objects.  Once implemented, interested
16
 * parties can ask this filter whether or not a specific object
17
 * is filtered.
18
 * 
19
 * For example, in a visualization tool, only unfiltered objects should
20
 * be displayed.  Before displaying an object, the display can ask
21
 * this filter if the object is filtered.
22
 * 
23
 * @author Casey Best
24
 */
25
public interface LayoutFilter {
26
27
	/**
28
	 * Returns true if the object is filtered, or false if it's not filtered.
29
	 * 
30
	 * @param item
31
	 *            object to check
32
	 * @return
33
	 */
34
	public boolean isObjectFiltered(GraphItem item);
35
}
(-)src/org/eclipse/zest/core/widgets/InternalLayoutContext.java (+306 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Mateusz Matela and others. All rights reserved. This
3
 * program and the accompanying materials are made available under the terms of
4
 * the Eclipse Public License v1.0 which accompanies this distribution, and is
5
 * available at http://www.eclipse.org/legal/epl-v10.html
6
 * 
7
 * Contributors:
8
 * 	   Mateusz Matela <mateusz.matela@gmail.com> - initial API and implementation
9
 *******************************************************************************/
10
11
package org.eclipse.zest.core.widgets;
12
13
import java.util.ArrayList;
14
import java.util.HashSet;
15
import java.util.Iterator;
16
import java.util.List;
17
18
import org.eclipse.draw2d.Animation;
19
import org.eclipse.zest.layouts.ConnectionLayout;
20
import org.eclipse.zest.layouts.ContextListener;
21
import org.eclipse.zest.layouts.EntityLayout;
22
import org.eclipse.zest.layouts.ExpandCollapseManager;
23
import org.eclipse.zest.layouts.GraphStructureListener;
24
import org.eclipse.zest.layouts.LayoutAlgorithm;
25
import org.eclipse.zest.layouts.LayoutContext;
26
import org.eclipse.zest.layouts.LayoutListener;
27
import org.eclipse.zest.layouts.NodeLayout;
28
import org.eclipse.zest.layouts.SubgraphLayout;
29
import org.eclipse.zest.layouts.dataStructures.DisplayIndependentRectangle;
30
31
class InternalLayoutContext implements LayoutContext {
32
33
	final NodeContainerAdapter container;
34
	private List filters = new ArrayList();
35
	private List contextListeners = new ArrayList();
36
	private List graphStructureListeners = new ArrayList();
37
	private List layoutListeners = new ArrayList();
38
	private List pruningListeners = new ArrayList();
39
	private LayoutAlgorithm mainAlgorithm;
40
	private ExpandCollapseManager expandCollapseManager;
41
	private ArrayList subgraphs = new ArrayList();
42
43
	private final LayoutFilter defaultFilter = new LayoutFilter() {
44
		public boolean isObjectFiltered(GraphItem item) {
45
			// filter out invisible elements
46
			if (item instanceof GraphItem && ZestStyles.checkStyle(container.getGraph().getStyle(), ZestStyles.IGNORE_INVISIBLE_LAYOUT) && !(item).isVisible()) {
47
				return true;
48
			}
49
			return false;
50
		}
51
	};
52
53
	/**
54
	 * @param graph
55
	 *            the graph owning this context
56
	 */
57
	InternalLayoutContext(Graph graph) {
58
		this.container = NodeContainerAdapter.get(graph);
59
		addFilter(defaultFilter);
60
	}
61
62
	InternalLayoutContext(GraphContainer container) {
63
		this.container = NodeContainerAdapter.get(container);
64
		addFilter(defaultFilter);
65
	}
66
67
	public void addContextListener(ContextListener listener) {
68
		contextListeners.add(listener);
69
	}
70
71
	public void addGraphStructureListener(GraphStructureListener listener) {
72
		graphStructureListeners.add(listener);
73
	}
74
75
	public void addLayoutListener(LayoutListener listener) {
76
		layoutListeners.add(listener);
77
	}
78
79
	public SubgraphLayout addSubgraph(NodeLayout[] nodes) {
80
		// TODO Auto-generated method stub
81
		return null;
82
	}
83
84
	public void flushChanges(boolean animationHint) {
85
		// TODO Auto-generated method stub
86
		// TODO probably OK for nodes, need to add subgraphs
87
		// TODO support for asynchronous call
88
		animationHint = animationHint && container.getGraph().isVisible();
89
		if (animationHint) {
90
			Animation.markBegin();
91
		}
92
		for (Iterator iterator = container.getNodes().iterator(); iterator.hasNext();) {
93
			GraphNode node = (GraphNode) iterator.next();
94
			node.applyLayoutChanges();
95
		}
96
		for (Iterator iterator = container.getConnections().iterator(); iterator.hasNext();) {
97
			GraphConnection connection = (GraphConnection) iterator.next();
98
			connection.applyLayoutChanges();
99
		}
100
		if (animationHint) {
101
			Animation.run(Graph.ANIMATION_TIME);
102
		}
103
	}
104
105
	public DisplayIndependentRectangle getBounds() {
106
		return container.getLayoutBounds();
107
	}
108
109
	public LayoutAlgorithm getMainLayoutAlgorithm() {
110
		return mainAlgorithm;
111
	}
112
113
	public ExpandCollapseManager getExpandCollapseManager() {
114
		return expandCollapseManager;
115
	}
116
117
	public NodeLayout[] getNodes() {
118
		ArrayList result = new ArrayList();
119
		for (Iterator iterator = this.container.getNodes().iterator(); iterator.hasNext();) {
120
			GraphNode node = (GraphNode) iterator.next();
121
			if (!isLayoutItemFiltered(node)) {
122
				result.add(node.getLayout());
123
			}
124
		}
125
		return (NodeLayout[]) result.toArray(new NodeLayout[result.size()]);
126
	}
127
128
	public EntityLayout[] getEntities() {
129
		// TODO Auto-generated method stub
130
		return getNodes();
131
	}
132
133
	public SubgraphLayout[] getSubgraphs() {
134
		// TODO filter out subgraphs that have all elements filtered out
135
		return (SubgraphLayout[]) subgraphs.toArray(new SubgraphLayout[subgraphs.size()]);
136
	}
137
138
	public boolean isBoundsExpandable() {
139
		return false;
140
	}
141
142
	public boolean isContinuousLayoutEnabled() {
143
		return false;
144
	}
145
146
	public boolean isPruningEnabled() {
147
		return expandCollapseManager != null;
148
	}
149
150
	public void removeContextListener(ContextListener listener) {
151
		contextListeners.remove(listener);
152
	}
153
154
	public void removeGraphStructureListener(GraphStructureListener listener) {
155
		graphStructureListeners.remove(listener);
156
	}
157
158
	public void removeLayoutListener(LayoutListener listener) {
159
		layoutListeners.remove(listener);
160
	}
161
162
	public void setMainLayoutAlgorithm(LayoutAlgorithm algorithm) {
163
		mainAlgorithm = algorithm;
164
	}
165
166
	public void setExpandCollapseManager(ExpandCollapseManager pruningManager) {
167
		this.expandCollapseManager = pruningManager;
168
	}
169
170
	public ConnectionLayout[] getConnections() {
171
		List connections = container.getConnections();
172
		ConnectionLayout[] result = new ConnectionLayout[connections.size()];
173
		int i = 0;
174
		for (Iterator iterator = connections.iterator(); iterator.hasNext();) {
175
			GraphConnection connection = (GraphConnection) iterator.next();
176
			if (!isLayoutItemFiltered(connection)) {
177
				result[i++] = connection.getLayout();
178
			}
179
		}
180
		if (i == result.length) {
181
			return result;
182
		}
183
		ConnectionLayout[] result2 = new ConnectionLayout[i];
184
		System.arraycopy(result, 0, result2, 0, i);
185
		return result2;
186
	}
187
188
	public ConnectionLayout[] getConnections(EntityLayout source, EntityLayout target) {
189
		HashSet result = new HashSet();
190
		// TODO add support for subgraphs
191
		if (source instanceof NodeLayout && target instanceof NodeLayout) {
192
			ConnectionLayout[] outgoingConnections = ((NodeLayout) source).getOutgoingConnections();
193
			for (int i = 0; i < outgoingConnections.length; i++) {
194
				ConnectionLayout connection = outgoingConnections[i];
195
				if ((connection.getTarget() == target && connection.getSource() == source) || (connection.getTarget() == source && connection.getSource() == target)) {
196
					result.add(connection);
197
				}
198
			}
199
		}
200
		return (ConnectionLayout[]) result.toArray(new ConnectionLayout[result.size()]);
201
	}
202
203
	void addFilter(LayoutFilter filter) {
204
		filters.add(filter);
205
	}
206
207
	void removeFilter(LayoutFilter filter) {
208
		filters.remove(filter);
209
	}
210
211
	boolean isLayoutItemFiltered(GraphItem item) {
212
		for (Iterator it = filters.iterator(); it.hasNext();) {
213
			LayoutFilter filter = (LayoutFilter) it.next();
214
			if (filter.isObjectFiltered(item)) {
215
				return true;
216
			}
217
		}
218
		return false;
219
	}
220
221
	void setExpanded(NodeLayout node, boolean expanded) {
222
		if (expandCollapseManager != null) {
223
			expandCollapseManager.setExpanded(node, expanded);
224
		}
225
	}
226
227
	void applyMainAlgorithm() {
228
		if (mainAlgorithm != null) {
229
			mainAlgorithm.applyLayout();
230
			flushChanges(false);
231
		}
232
	}
233
234
	void fireNodeAddedEvent(NodeLayout node) {
235
		boolean intercepted = false;
236
		for (Iterator iterator = graphStructureListeners.iterator(); iterator.hasNext() && !intercepted;) {
237
			GraphStructureListener listener = (GraphStructureListener) iterator.next();
238
			intercepted = listener.nodeAdded(this, node);
239
		}
240
		if (!intercepted && mainAlgorithm != null) {
241
			mainAlgorithm.applyLayout();
242
		}
243
	}
244
245
	void fireNodeRemovedEvent(NodeLayout node) {
246
		boolean intercepted = false;
247
		for (Iterator iterator = graphStructureListeners.iterator(); iterator.hasNext() && !intercepted;) {
248
			GraphStructureListener listener = (GraphStructureListener) iterator.next();
249
			intercepted = listener.nodeRemoved(this, node);
250
		}
251
		if (!intercepted) {
252
			applyMainAlgorithm();
253
		}
254
	}
255
256
	void fireConnectionAddedEvent(ConnectionLayout connection) {
257
		InternalLayoutContext sourceContext = ((InternalNodeLayout) connection.getSource()).getOwnerLayoutContext();
258
		InternalLayoutContext targetContext = ((InternalNodeLayout) connection.getTarget()).getOwnerLayoutContext();
259
		if (sourceContext != targetContext) {
260
			return;
261
		}
262
		if (sourceContext == this) {
263
			boolean intercepted = false;
264
			for (Iterator iterator = graphStructureListeners.iterator(); iterator.hasNext() && !intercepted;) {
265
				GraphStructureListener listener = (GraphStructureListener) iterator.next();
266
				intercepted = listener.connectionAdded(this, connection);
267
			}
268
			if (!intercepted) {
269
				applyMainAlgorithm();
270
			}
271
		} else {
272
			sourceContext.fireConnectionAddedEvent(connection);
273
		}
274
	}
275
276
	void fireConnectionRemovedEvent(ConnectionLayout connection) {
277
		InternalLayoutContext sourceContext = ((InternalNodeLayout) connection.getSource()).getOwnerLayoutContext();
278
		InternalLayoutContext targetContext = ((InternalNodeLayout) connection.getTarget()).getOwnerLayoutContext();
279
		if (sourceContext != targetContext) {
280
			return;
281
		}
282
		if (sourceContext == this) {
283
			boolean intercepted = false;
284
			for (Iterator iterator = graphStructureListeners.iterator(); iterator.hasNext() && !intercepted;) {
285
				GraphStructureListener listener = (GraphStructureListener) iterator.next();
286
				intercepted = listener.connectionRemoved(this, connection);
287
			}
288
			if (!intercepted) {
289
				applyMainAlgorithm();
290
			}
291
		} else {
292
			sourceContext.fireConnectionAddedEvent(connection);
293
		}
294
	}
295
296
	void fireBoundsChangedEvent() {
297
		boolean intercepted = false;
298
		for (Iterator iterator = contextListeners.iterator(); iterator.hasNext() && !intercepted;) {
299
			ContextListener listener = (ContextListener) iterator.next();
300
			intercepted = listener.boundsChanged(this);
301
		}
302
		if (!intercepted) {
303
			applyMainAlgorithm();
304
		}
305
	}
306
}
(-)src/org/eclipse/zest/core/widgets/NodeContainerAdapter.java (+214 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Mateusz Matela and others. All rights reserved. This
3
 * program and the accompanying materials are made available under the terms of
4
 * the Eclipse Public License v1.0 which accompanies this distribution, and is
5
 * available at http://www.eclipse.org/legal/epl-v10.html
6
 * 
7
 * Contributors:
8
 * 	   Mateusz Matela <mateusz.matela@gmail.com> - initial API and implementation
9
 *******************************************************************************/
10
11
package org.eclipse.zest.core.widgets;
12
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.Iterator;
16
import java.util.List;
17
18
import org.eclipse.draw2d.IFigure;
19
import org.eclipse.draw2d.geometry.Dimension;
20
import org.eclipse.swt.widgets.Widget;
21
import org.eclipse.zest.layouts.dataStructures.DisplayIndependentRectangle;
22
23
/**
24
 * This adapter unifies API of {@link Graph} and {@link GraphContainer} and
25
 * is used everywhere objects of both these classes can be expected.
26
 * 
27
 * It's introduced in order to prevent some methods from change to public with
28
 * common interface.
29
 */
30
abstract class NodeContainerAdapter {
31
	private static class GraphAdapter extends NodeContainerAdapter {
32
		private Graph graph;
33
34
		private GraphAdapter(Graph graph) {
35
			graph.getStyle();
36
			this.graph = graph;
37
		}
38
39
		public Widget getAdaptee() {
40
			return graph;
41
		}
42
43
		public Graph getGraph() {
44
			return graph;
45
		}
46
47
		public List getNodes() {
48
			return graph.getNodes();
49
		}
50
51
		public List getConnections() {
52
			return filterConnections(graph.getConnections());
53
		}
54
55
		public void addNode(GraphNode graphNode) {
56
			graph.addNode(graphNode);
57
		}
58
59
		public void addFigure(IFigure figure) {
60
			graph.addFigure(figure);
61
		}
62
63
		public void highlightNode(GraphNode graphNode) {
64
			graph.highlightNode(graphNode);
65
		}
66
67
		public void unhighlightNode(GraphNode graphNode) {
68
			graph.highlightNode(graphNode);
69
		}
70
71
		public int getItemType() {
72
			return GraphItem.GRAPH;
73
		}
74
75
		public DisplayIndependentRectangle getLayoutBounds() {
76
			Dimension preferredSize = graph.getPreferredSize();
77
			return new DisplayIndependentRectangle(0, 0, preferredSize.width, preferredSize.height);
78
		}
79
80
		public InternalLayoutContext getLayoutContext() {
81
			return graph.getLayoutContext();
82
		}
83
	}
84
85
	private static class GraphContainerAdapter extends NodeContainerAdapter {
86
		private GraphContainer container;
87
88
		private GraphContainerAdapter(GraphContainer container) {
89
			this.container = container;
90
		}
91
92
		public Widget getAdaptee() {
93
			return container;
94
		}
95
96
		public Graph getGraph() {
97
			return container.getGraph();
98
		}
99
100
		public List getNodes() {
101
			return container.getNodes();
102
		}
103
104
		public List getConnections() {
105
			return filterConnections(container.getGraph().getConnections());
106
		}
107
108
		public void addNode(GraphNode graphNode) {
109
			container.addNode(graphNode);
110
		}
111
112
		public void addFigure(IFigure figure) {
113
			container.addFigure(figure);
114
		}
115
116
		public void highlightNode(GraphNode graphNode) {
117
			/* do nothing */
118
		}
119
120
		public void unhighlightNode(GraphNode graphNode) {
121
			/* do nothing */
122
		}
123
124
		public int getItemType() {
125
			return GraphItem.CONTAINER;
126
		}
127
128
		public DisplayIndependentRectangle getLayoutBounds() {
129
			return container.getLayoutBounds();
130
		}
131
132
		public InternalLayoutContext getLayoutContext() {
133
			return container.getLayoutContext();
134
		}
135
	}
136
137
	private static HashMap adaptersMap = new HashMap();
138
139
	static NodeContainerAdapter get(Graph graph) {
140
		NodeContainerAdapter adapter = (NodeContainerAdapter) adaptersMap.get(graph);
141
		if (adapter != null) {
142
			return adapter;
143
		}
144
145
		adapter = new GraphAdapter(graph);
146
		adaptersMap.put(graph, adapter);
147
		return adapter;
148
	}
149
150
	static NodeContainerAdapter get(GraphContainer container) {
151
		NodeContainerAdapter adapter = (NodeContainerAdapter) adaptersMap.get(container);
152
		if (adapter != null) {
153
			return adapter;
154
		}
155
156
		adapter = new GraphContainerAdapter(container);
157
		adaptersMap.put(container, adapter);
158
		return adapter;
159
	}
160
161
	public abstract Widget getAdaptee();
162
163
	public abstract Graph getGraph();
164
165
	public abstract List getNodes();
166
167
	/**
168
	 * Returns list of connections laying inside this container. Only
169
	 * connections which both source and target nodes lay directly in this
170
	 * container are returned.
171
	 * 
172
	 * @return
173
	 */
174
	public abstract List getConnections();
175
176
	public abstract void addNode(GraphNode graphNode);
177
178
	/**
179
	 * Adds a custom figure to be displayed on top of nodes. Can be used to add
180
	 * subgraph figures.
181
	 * 
182
	 * @param figure
183
	 */
184
	public abstract void addFigure(IFigure figure);
185
186
	public abstract void highlightNode(GraphNode graphNode);
187
188
	public abstract void unhighlightNode(GraphNode graphNode);
189
190
	public abstract int getItemType();
191
192
	public abstract DisplayIndependentRectangle getLayoutBounds();
193
194
	public abstract InternalLayoutContext getLayoutContext();
195
196
	/**
197
	 * Takes a list of connections and returns only those which source and
198
	 * target nodes lay directly in this container.
199
	 * 
200
	 * @param connections
201
	 *            list of GraphConnection to filter
202
	 * @return filtered list
203
	 */
204
	protected List filterConnections(List connections) {
205
		List result = new ArrayList();
206
		for (Iterator iterator = connections.iterator(); iterator.hasNext();) {
207
			GraphConnection connection = (GraphConnection) iterator.next();
208
			if (connection.getSource().getParent() == this && connection.getDestination().getParent() == this) {
209
				result.add(connection);
210
			}
211
		}
212
		return result;
213
	}
214
}

Return to bug 283179