1
28 package demo.layout.hierarchic;
29
30 import demo.view.DemoBase;
31 import demo.view.DemoDefaults;
32
33 import y.base.Edge;
34 import y.base.EdgeCursor;
35 import y.base.EdgeMap;
36 import y.base.Graph;
37 import y.base.Node;
38 import y.base.NodeCursor;
39 import y.base.NodeMap;
40 import y.io.GraphMLIOHandler;
41 import y.io.graphml.KeyScope;
42 import y.io.graphml.KeyType;
43 import y.layout.hierarchic.IncrementalHierarchicLayouter;
44 import y.layout.hierarchic.TopologicalLayerer;
45 import y.layout.hierarchic.incremental.LayerConstraintFactory;
46 import y.layout.hierarchic.incremental.ConstraintIncrementalLayerer;
47 import y.util.GraphCopier;
48 import y.view.Arrow;
49 import y.view.EdgeRealizer;
50 import y.view.Graph2D;
51 import y.view.Graph2DClipboard;
52
53 import javax.swing.AbstractAction;
54 import javax.swing.BorderFactory;
55 import javax.swing.JButton;
56 import javax.swing.JPanel;
57 import javax.swing.JScrollPane;
58 import javax.swing.JToolBar;
59 import java.awt.BorderLayout;
60 import java.awt.Color;
61 import java.awt.GridBagConstraints;
62 import java.awt.GridBagLayout;
63 import java.awt.Insets;
64 import java.awt.EventQueue;
65 import java.awt.event.ActionEvent;
66 import java.awt.event.ActionListener;
67 import java.util.HashMap;
68 import java.util.Locale;
69 import java.util.Map;
70
71
86 public class LayerConstraintsDemo extends DemoBase {
87
88 public static final int TOP_LEVEL = 1;
89 public static final int BOTTOM_LEVEL = 5;
90
91 private NodeMap levels;
92 private EdgeMap weights;
93
94 public LayerConstraintsDemo() {
95 super();
96 final Graph2D graph = view.getGraph2D();
97 EdgeRealizer defaultER = graph.getDefaultEdgeRealizer();
98 defaultER.setArrow(Arrow.STANDARD);
99
100 levels = graph.createNodeMap();
101
102 weights = graph.createEdgeMap();
104 graph.addDataProvider(ConstraintIncrementalLayerer.EDGE_WEIGHTS_DPKEY, weights);
105
106 JPanel left = new JPanel(new GridBagLayout());
107
108 GridBagConstraints gbc = new GridBagConstraints();
109 gbc.fill = GridBagConstraints.BOTH;
110 gbc.anchor = GridBagConstraints.NORTHWEST;
111
112 gbc.gridx = 0;
113 gbc.gridy = GridBagConstraints.RELATIVE;
114
115 JPanel groupSpec;
116 groupSpec = new JPanel(new GridBagLayout());
117 groupSpec.setBorder(BorderFactory.createTitledBorder("Layering constraints"));
118
119
121 Color[] groupColors = new Color[]{DemoDefaults.DEFAULT_CONTRAST_COLOR, Color.RED, Color.ORANGE, Color.yellow, new Color(204, 255, 0), Color.GREEN};
122 String[] groupLabels = new String[]{"Remove constraint", "Top-most level", "Above medium level", "Medium level",
123 "Below medium level",
124 "Bottom-most level"};
125 gbc.insets = new Insets(5, 0, 5, 0);
126 for (int i = 0; i < groupColors.length; i++) {
127 if (i > 1 && i < 5) {
128 gbc.insets = new Insets(0, 0, 0, 0);
129 } else {
130 gbc.insets = new Insets(5, 0, 5, 0);
131 }
132 GroupButton groupButton = new GroupButton(groupColors[i], groupLabels[i], i);
133 groupSpec.add(groupButton, gbc);
134 }
135 gbc.weightx = gbc.weighty = 1;
136 groupSpec.add(new JPanel(), gbc);
137 gbc.weightx = gbc.weighty = 0;
138 gbc.gridwidth = 2;
139 left.add(groupSpec, gbc);
140 gbc.gridwidth = 1;
141
142 gbc.weighty = 1.0d;
143 left.add(new JPanel(), gbc);
144
145 contentPane.add(new JScrollPane(left), BorderLayout.WEST);
146
147 loadGraph("resource/LayerConstraintsDemo.graphml");
148 }
149
150 protected GraphMLIOHandler createGraphMLIOHandler() {
151 GraphMLIOHandler ioh = super.createGraphMLIOHandler();
152 ioh.getGraphMLHandler().addOutputDataProvider("level", levels, KeyScope.NODE, KeyType.INT);
153 ioh.getGraphMLHandler().addInputDataAcceptor("level", levels, KeyScope.NODE, KeyType.INT);
154 return ioh;
155 }
156
157 protected void configureDefaultRealizers() {
158 super.configureDefaultRealizers();
159 view.getGraph2D().getDefaultNodeRealizer().setFillColor(DemoDefaults.DEFAULT_CONTRAST_COLOR);
160 }
161
162 protected JToolBar createToolBar() {
163 JToolBar toolBar = super.createToolBar();
164 toolBar.addSeparator();
165 toolBar.add(createActionControl(new LayoutAction()));
166 return toolBar;
167 }
168
169 protected Graph2DClipboard getClipboard() {
170 final Graph2DClipboard clipboard = super.getClipboard();
171 clipboard.setCopyFactory(new LayerConstraintGraphCopyFactory(clipboard.getCopyFactory()));
172 return clipboard;
173 }
174
175
176 protected void assignLevel(Color color, int index) {
177 Graph2D graph = view.getGraph2D();
178
179 for (NodeCursor nc = graph.selectedNodes(); nc.ok(); nc.next()) {
180 Node n = nc.node();
181 if (color != null) {
183 graph.getRealizer(n).setFillColor(color);
184 } else {
185 graph.getRealizer(n).setFillColor(graph.getDefaultNodeRealizer().getFillColor());
186 }
187 levels.setInt(n, index);
188 }
189 graph.updateViews();
190 }
191
192
193 class GroupButton extends JButton implements ActionListener {
195 Color color;
196 int index;
197
198 GroupButton(Color color, String groupLabel, int index) {
199 super("");
200 setText(groupLabel);
201 this.color = color;
202 this.index = index;
203 setBackground(color);
204 this.addActionListener(this);
205 }
206
207 public void actionPerformed(ActionEvent e) {
208 LayerConstraintsDemo.this.assignLevel(color, index);
209 }
210 }
211
212 class LayoutAction extends AbstractAction {
213 LayoutAction() {
214 super("Layout", SHARED_LAYOUT_ICON);
215 }
216
217 public void actionPerformed(ActionEvent ev) {
218 Graph2D graph = view.getGraph2D();
219
220
221 doLayout(graph);
222 graph.updateViews();
223 view.fitContent();
224 }
225 }
226
227 private void doLayout(Graph2D graph) {
228 IncrementalHierarchicLayouter hl = new IncrementalHierarchicLayouter();
229 hl.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_HIERARCHICAL_TOPMOST);
230 hl.setOrthogonallyRouted(true);
231 LayerConstraintFactory lcf = hl.createLayerConstraintFactory(graph);
232 createConstraints(graph, lcf);
233
234 TopologicalLayerer topologicalLayerer = new TopologicalLayerer();
235 topologicalLayerer.setRankingPolicy(TopologicalLayerer.NO_RERANKING);
236 hl.setFromScratchLayerer(topologicalLayerer);
237
238 view.applyLayoutAnimated(hl);
239 }
240
241
247 private void createConstraints(Graph2D graph, LayerConstraintFactory cf) {
248 Node flr, slr, thrdlr;
249 flr = slr = thrdlr = null;
250 for (NodeCursor nodeCursor = graph.nodes(); nodeCursor.ok(); nodeCursor.next()) {
251 Node node = nodeCursor.node();
252 int index = levels.getInt(node);
253 switch (index) {
254 case TOP_LEVEL:
255 cf.addPlaceNodeAtTopConstraint(node);
256 break;
257 case BOTTOM_LEVEL:
258 cf.addPlaceNodeAtBottomConstraint(node);
259 break;
260 case TOP_LEVEL + 1:
261 if (flr == null) {
262 flr = node;
263 } else {
264 cf.addPlaceNodeInSameLayerConstraint(flr, node);
265 }
266 break;
267 case TOP_LEVEL + 2:
268 if (slr == null) {
269 slr = node;
270 } else {
271 cf.addPlaceNodeInSameLayerConstraint(slr, node);
272 }
273 break;
274 case TOP_LEVEL + 3:
275 if (thrdlr == null) {
276 thrdlr = node;
277 } else {
278 cf.addPlaceNodeInSameLayerConstraint(thrdlr, node);
279 }
280 break;
281 default:
282 break;
283 }
284 if (flr != null && slr != null) {
285 cf.addPlaceNodeBelowConstraint(flr, slr);
287 }
288 if (slr != null && thrdlr != null) {
289 cf.addPlaceNodeBelowConstraint(slr, thrdlr);
291 }
292 if (flr != null && thrdlr != null) {
293 cf.addPlaceNodeAboveConstraint(thrdlr, flr);
295 }
296 }
297
298 for (EdgeCursor edgeCursor = graph.edges(); edgeCursor.ok(); edgeCursor.next()) {
300 Edge edge = edgeCursor.edge();
301 if (graph.getRealizer(edge).labelCount() > 0) {
302 String str = graph.getLabelText(edge);
303 try {
304 weights.setInt(edge, Integer.parseInt(str));
305 }
306 catch (NumberFormatException e) {
307 weights.setInt(edge, 1);
308 }
309 }
310 else {
311 weights.setInt(edge, 1);
312 }
313 }
314 }
315
316
317
318 public static void main(String[] args) {
319 EventQueue.invokeLater(new Runnable() {
320 public void run() {
321 Locale.setDefault(Locale.ENGLISH);
322 initLnF();
323 (new LayerConstraintsDemo()).start("Layer Constraints Demo");
324 }
325 });
326 }
327
328
331 private class LayerConstraintGraphCopyFactory implements GraphCopier.CopyFactory {
332 private final GraphCopier.CopyFactory copyFactory;
333 private final HashMap node2level;
334
335 public LayerConstraintGraphCopyFactory(GraphCopier.CopyFactory copyFactory) {
336 this.copyFactory = copyFactory;
337 node2level = new HashMap();
338 }
339
340 public Node copyNode(Graph targetGraph, Node originalNode) {
341 return copyFactory.copyNode(targetGraph, originalNode);
342 }
343
344 public Edge copyEdge(Graph targetGraph, Node newSource, Node newTarget, Edge originalEdge) {
345 return copyFactory.copyEdge(targetGraph, newSource, newTarget, originalEdge);
346 }
347
348 public Graph createGraph() {
349 return copyFactory.createGraph();
350 }
351
352 public void preCopyGraphData(Graph sourceGraph, Graph targetGraph) {
353 copyFactory.preCopyGraphData(sourceGraph, targetGraph);
354 }
355
356
360 public void postCopyGraphData(Graph sourceGraph, Graph targetGraph, Map nodeMap, Map edgeMap) {
361 copyFactory.postCopyGraphData(sourceGraph, targetGraph, nodeMap, edgeMap);
362
363 if (sourceGraph == view.getGraph2D()) {
365 node2level.clear();
368 for (NodeCursor nodeCursor = sourceGraph.nodes(); nodeCursor.ok(); nodeCursor.next()) {
369 final Node sourceNode = nodeCursor.node();
370 final Node targetNode = (Node) nodeMap.get(sourceNode);
371 if (targetNode != null) {
372 node2level.put(targetNode, levels.get(sourceNode));
373 }
374 }
375 } else {
376 for (NodeCursor nodeCursor = sourceGraph.nodes(); nodeCursor.ok(); nodeCursor.next()) {
379 final Node sourceNode = nodeCursor.node();
380 final Node targetNode = (Node) nodeMap.get(sourceNode);
381 levels.set(targetNode, node2level.get(sourceNode));
382 }
383 }
384 }
385 }
386
387 }
388