1
14 package demo.layout.hierarchic;
15
16 import demo.view.DemoDefaults;
17
18 import y.base.DataMap;
19 import y.base.EdgeCursor;
20 import y.base.EdgeList;
21 import y.base.Node;
22 import y.base.NodeCursor;
23 import y.geom.YInsets;
24 import y.layout.grouping.Grouping;
25 import y.layout.hierarchic.IncrementalHierarchicLayouter;
26 import y.layout.hierarchic.incremental.IncrementalHintsFactory;
27 import y.util.Maps;
28 import y.view.EditMode;
29 import y.view.GenericNodeRealizer;
30 import y.view.GenericNodeRealizer.Factory;
31 import y.view.Graph2D;
32 import y.view.Graph2DCanvas;
33 import y.view.Graph2DLayoutExecutor;
34 import y.view.HitInfo;
35 import y.view.LineType;
36 import y.view.NodeLabel;
37 import y.view.NodeRealizer;
38 import y.view.ShinyPlateNodePainter;
39 import y.view.SmartNodeLabelModel;
40 import y.view.TooltipMode;
41 import y.view.ViewMode;
42 import y.view.hierarchy.DefaultHierarchyGraphFactory;
43 import y.view.hierarchy.GenericGroupNodeRealizer;
44 import y.view.hierarchy.GroupLayoutConfigurator;
45 import y.view.hierarchy.HierarchyManager;
46 import y.view.tabular.TableGroupNodeRealizer;
47 import y.view.tabular.TableGroupNodeRealizer.Column;
48 import y.view.tabular.TableGroupNodeRealizer.Table;
49 import y.view.tabular.TableNodePainter;
50 import y.view.tabular.TableStyle;
51
52 import java.awt.Color;
53 import java.awt.EventQueue;
54 import java.awt.event.ActionEvent;
55 import java.awt.event.MouseEvent;
56 import java.util.Locale;
57 import java.util.Map;
58
59 import javax.swing.AbstractAction;
60 import javax.swing.JToolBar;
61
62
89 public class SwimlaneGroupDemo extends IncrementalHierarchicGroupDemo {
90 private static final Color NODE_COLOR = DemoDefaults.DEFAULT_NODE_COLOR;
91 private static final Color NODE_GRADIENT_COLOR = Color.WHITE;
92 private static final Color NODE_LINE_COLOR = DemoDefaults.DEFAULT_NODE_LINE_COLOR;
93 private static final Color GROUP_NODE_COLOR = new Color(255, 255, 255, 127);
94 private static final Color GROUP_NODE_LINE_COLOR = DemoDefaults.DEFAULT_NODE_COLOR;
95 private static final Color GROUP_NODE_LABEL_COLOR = DemoDefaults.DEFAULT_NODE_COLOR;
96 private static final Color ODD_LANE_COLOR = DemoDefaults.DEFAULT_CONTRAST_COLOR;
97 private static final Color EVEN_LANE_COLOR = new Color(237, 247, 247);
98
99 private static final String NODE_CONFIGURATION = "NODE_CONFIGURATION";
100 private static final String SWIMLANE_CONFIGURATION = "SWIMLANE_CONFIGURATION";
101
102 static {
103 initConfigurations();
104 }
105
106
107 public SwimlaneGroupDemo() {
108 view.addViewMode(new TriggerIncrementalLayout());
109 configureRealizers(view.getGraph2D());
110 loadInitialGraph();
111 }
112
113
116 protected void loadInitialGraph() {
117 final Graph2D graph = view.getGraph2D();
118 graph.clear();
119
120 HierarchyManager hierarchy = getHierarchyManager();
121
122 if (layouter != null && hierarchy != null) {
123 final TableGroupNodeRealizer tgnr = new TableGroupNodeRealizer();
125 tgnr.setConfiguration(SWIMLANE_CONFIGURATION);
126
127 tgnr.setLabelText("Swimlane Pool");
128 NodeLabel label = tgnr.getLabel();
129 SmartNodeLabelModel labelModel = new SmartNodeLabelModel();
130 label.setLabelModel(labelModel);
131 label.setModelParameter(labelModel.createDiscreteModelParameter(SmartNodeLabelModel.POSITION_TOP));
132 tgnr.getLabel().setVisible(false);
135
136 final TableStyle.SimpleStyle oddLane =
138 new TableStyle.SimpleStyle(null, null, ODD_LANE_COLOR);
139 tgnr.setStyleProperty(TableNodePainter.COLUMN_STYLE_ID, oddLane);
140 tgnr.setStyleProperty(TableNodePainter.COLUMN_SELECTION_STYLE_ID, oddLane);
141
142 final TableStyle.SimpleStyle evenLane =
143 new TableStyle.SimpleStyle(null, null, EVEN_LANE_COLOR);
144 tgnr.setStyleProperty(TableNodePainter.ALTERNATE_COLUMN_STYLE_ID, evenLane);
145 tgnr.setStyleProperty(TableNodePainter.ALTERNATE_COLUMN_SELECTION_STYLE_ID, evenLane);
146
147 final TableStyle.SimpleStyle none = new TableStyle.SimpleStyle();
148 tgnr.setStyleProperty(TableNodePainter.ROW_STYLE_ID, none);
149 tgnr.setStyleProperty(TableNodePainter.ROW_SELECTION_STYLE_ID, none);
150 tgnr.setStyleProperty(TableNodePainter.TABLE_STYLE_ID, none);
151 tgnr.setStyleProperty(TableNodePainter.TABLE_SELECTION_STYLE_ID, none);
152
153 tgnr.setDefaultColumnInsets(new YInsets(25, 5, 0, 5));
155 tgnr.setDefaultMinimumColumnWidth(50);
156 tgnr.setDefaultRowInsets(new YInsets(15, 0, 15, 0));
157
158 final Column[] columns = new Column[9];
160 final Table table = tgnr.getTable();
161 for (int i = 0; i < columns.length; ++i) {
162 columns[i] = i == 0 ? table.getColumn(0) : table.addColumn();
163
164 final NodeLabel nl = tgnr.createNodeLabel();
165 nl.setText("Lane " + (i + 1));
166 tgnr.configureColumnLabel(nl, columns[i], true, 0);
167 tgnr.addLabel(nl);
168 }
169
170 tgnr.updateTableBounds();
171
172
173 final Node pool = hierarchy.createGroupNode(graph);
174 graph.setRealizer(pool, tgnr);
175
176 final Node n00 = graph.createNode();
177 final Node n01 = graph.createNode();
178 final Node g03 = hierarchy.createGroupNode(graph);
179 final Node g04 = hierarchy.createGroupNode(graph);
180 final Node n05 = graph.createNode();
181 final Node n06 = graph.createNode();
182 final Node n07 = graph.createNode();
183 final Node g08 = hierarchy.createGroupNode(graph);
184 final Node n09 = graph.createNode();
185 final Node n10 = graph.createNode();
186 final Node n11 = graph.createNode();
187 final Node g12 = hierarchy.createGroupNode(graph);
188 final Node n13 = graph.createNode();
189 final Node n14 = graph.createNode();
190 final Node n15 = graph.createNode();
191 final Node n16 = graph.createNode();
192 final Node n17 = graph.createNode();
193 final Node g18 = hierarchy.createGroupNode(graph);
194 final Node n19 = graph.createNode();
195 final Node n20 = graph.createNode();
196 final Node n21 = graph.createNode();
197 final Node n22 = graph.createNode();
198 final Node n23 = graph.createNode();
199
200 hierarchy.setParentNode(n00, pool);
202 hierarchy.setParentNode(n01, pool);
203
204 hierarchy.setParentNode(g03, pool);
205 hierarchy.setParentNode(g04, pool);
206 hierarchy.setParentNode(n05, pool);
207 hierarchy.setParentNode(n06, pool);
208 hierarchy.setParentNode(n07, pool);
209
210 hierarchy.setParentNode(g08, g03);
211 hierarchy.setParentNode(n09, g03);
212 hierarchy.setParentNode(n10, g03);
213 hierarchy.setParentNode(n11, g03);
214
215 hierarchy.setParentNode(g12, g08);
216 hierarchy.setParentNode(n13, g08);
217 hierarchy.setParentNode(n14, g08);
218
219 hierarchy.setParentNode(n15, g12);
220 hierarchy.setParentNode(n16, g12);
221 hierarchy.setParentNode(n17, g12);
222
223 hierarchy.setParentNode(g18, g04);
224 hierarchy.setParentNode(n19, g04);
225 hierarchy.setParentNode(n20, g04);
226
227 hierarchy.setParentNode(n21, g18);
228 hierarchy.setParentNode(n22, g18);
229 hierarchy.setParentNode(n23, g18);
230
231
232 hierarchy.createEdge(n00, n01);
233 hierarchy.createEdge(n01, n06);
234 hierarchy.createEdge(n06, n07);
235 hierarchy.createEdge(n06, n05);
236 hierarchy.createEdge(n06, n20);
237 hierarchy.createEdge(n07, n11);
238 hierarchy.createEdge(n09, n05);
239 hierarchy.createEdge(n10, n05);
240 hierarchy.createEdge(n11, n09);
241 hierarchy.createEdge(n11, n14);
242 hierarchy.createEdge(n13, n09);
243 hierarchy.createEdge(n14, n13);
244 hierarchy.createEdge(n14, n15);
245 hierarchy.createEdge(n15, n13);
246 hierarchy.createEdge(n15, n17);
247 hierarchy.createEdge(n16, n13);
248 hierarchy.createEdge(n17, n16);
249 hierarchy.createEdge(n19, n05);
250 hierarchy.createEdge(n20, n19);
251 hierarchy.createEdge(n20, n21);
252 hierarchy.createEdge(n21, n22);
253 hierarchy.createEdge(n21, n23);
254 hierarchy.createEdge(n21, n05);
255 hierarchy.createEdge(n22, n05);
256 hierarchy.createEdge(n23, n05);
257
258 table.moveToColumn(n00, columns[8]);
260 table.moveToColumn(n01, columns[5]);
261 table.moveToColumn(n05, columns[5]);
265 table.moveToColumn(n06, columns[5]);
266 table.moveToColumn(n07, columns[1]);
267 table.moveToColumn(n09, columns[1]);
269 table.moveToColumn(n10, columns[0]);
270 table.moveToColumn(n11, columns[1]);
271 table.moveToColumn(n13, columns[2]);
273 table.moveToColumn(n14, columns[2]);
274 table.moveToColumn(n15, columns[3]);
275 table.moveToColumn(n16, columns[2]);
276 table.moveToColumn(n17, columns[4]);
277 table.moveToColumn(n19, columns[7]);
279 table.moveToColumn(n20, columns[6]);
280 table.moveToColumn(n21, columns[6]);
281 table.moveToColumn(n22, columns[6]);
282 table.moveToColumn(n23, columns[6]);
283
284 initLabels(graph);
286
287 layout();
288 }
289
290 view.fitContent();
291 view.getGraph2D().updateViews();
292 }
293
294
298 private void initLabels(final Graph2D graph) {
299 Node tableNode = null;
300 Table table = null;
301 for (NodeCursor nc = graph.nodes(); nc.ok(); nc.next()) {
302 final NodeRealizer nr = graph.getRealizer(nc.node());
303 if (nr instanceof TableGroupNodeRealizer) {
304 tableNode = nc.node();
305 table = ((TableGroupNodeRealizer) nr).getTable();
306 break;
307 }
308 }
309
310 HierarchyManager hierarchy = getHierarchyManager();
311
312 int grp = 0;
313 int fldr = 0;
314 for (NodeCursor nc = graph.nodes(); nc.ok(); nc.next()) {
315 if (nc.node() == tableNode) {
316 continue;
317 }
318
319 if (hierarchy.isNormalNode(nc.node())) {
320 final Column column = table == null ? null : table.getColumn(nc.node());
321 if (column != null) {
322 graph.getRealizer(nc.node()).setLabelText(
323 Integer.toString(column.getIndex() + 1));
324 } else {
325 graph.getRealizer(nc.node()).setLabelText("");
326 }
327 NodeLabel label = graph.getRealizer(nc.node()).getLabel();
328 SmartNodeLabelModel model = new SmartNodeLabelModel();
329 label.setLabelModel(model);
330 label.setModelParameter(model.getDefaultParameter());
331 } else if (hierarchy.isGroupNode(nc.node())) {
332 graph.getRealizer(nc.node()).setLabelText(
333 "Group " + (++grp));
334 } else if (hierarchy.isFolderNode(nc.node())) {
335 graph.getRealizer(nc.node()).setLabelText(
336 "Folder " + (++fldr));
337 }
338 }
339 }
340
341
346
347
351 void layoutIncrementally() {
352 Graph2D graph = view.getGraph2D();
353
354 layouter.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_INCREMENTAL);
355
356 DataMap incrementalElements = Maps.createHashedDataMap();
358 final IncrementalHintsFactory ihf = layouter.createIncrementalHintsFactory();
360
361 final GroupLayoutConfigurator glc = new GroupLayoutConfigurator(graph);
363 glc.prepareAll();
364 final Grouping grouping = new Grouping(graph);
365
366 for (NodeCursor nc = graph.selectedNodes(); nc.ok(); nc.next()) {
368 Node n = nc.node();
369 incrementalElements.set(n, ihf.createLayerIncrementallyHint(nc.node()));
370 if (grouping.isGroupNode(n)) {
371 EdgeList markedEdges = grouping.getEdgesGoingIn(n);
373 markedEdges.addAll(grouping.getEdgesGoingOut(n));
374 for (EdgeCursor ec = markedEdges.edges(); ec.ok(); ec.next()) {
375 incrementalElements.set(ec.edge(), ihf.createSequenceIncrementallyHint(ec.edge()));
376 }
377 }
378 }
379 grouping.dispose();
380 glc.restoreAll();
381
382 for (EdgeCursor ec = graph.selectedEdges(); ec.ok(); ec.next()) {
383 incrementalElements.set(ec.edge(), ihf.createSequenceIncrementallyHint(ec.edge()));
384 }
385 graph.addDataProvider(IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY, incrementalElements);
386
387 try {
388 final Graph2DLayoutExecutor layoutExecutor =
389 new Graph2DLayoutExecutor(Graph2DLayoutExecutor.ANIMATED);
390 layoutExecutor.setConfiguringTableNodeRealizers(true);
391 layoutExecutor.doLayout(view, layouter);
392 } finally {
393 graph.removeDataProvider(IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY);
394 }
395
396 initLabels(graph);
398 graph.updateViews();
399 }
400
401
404 void layout() {
405 final Graph2D graph = view.getGraph2D();
406 layouter.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_FROM_SCRATCH);
407
408 final Graph2DLayoutExecutor layoutExecutor = new Graph2DLayoutExecutor();
409 layoutExecutor.setConfiguringTableNodeRealizers(true);
410 layoutExecutor.doLayout(view, layouter);
411
412 initLabels(graph);
414 graph.updateViews();
415 }
416
417
422
423 protected void addLayoutActions(JToolBar toolBar) {
424 toolBar.addSeparator();
425 toolBar.add(createActionControl(new AbstractAction(
426 "Layout", SHARED_LAYOUT_ICON) {
427 public void actionPerformed(ActionEvent e) {
428 layout();
429 }
430 }));
431 }
432
433 protected EditMode createEditMode() {
434 final EditMode editMode = new EditMode() {
435 protected void nodeCreated(final Node v) {
436 layoutIncrementally();
437 }
438 };
439 editMode.getMouseInputMode().setNodeSearchingEnabled(true);
441
442 editMode.assignNodeLabel(false);
445
446 editMode.setChildNodeCreationEnabled(true);
448
449 return editMode;
450 }
451
452
455 protected TooltipMode createTooltipMode() {
456 return new TooltipMode() {
457 protected String getNodeTip(Node node) {
458 NodeRealizer nodeRealizer = view.getGraph2D().getRealizer(node);
459 if (nodeRealizer instanceof TableGroupNodeRealizer) {
460 MouseEvent event = getLastMoveEvent();
462 Graph2DCanvas canvas = (Graph2DCanvas) view.getCanvasComponent();
463 double x = canvas.translateX(event.getX());
464 double y = canvas.translateY(event.getY());
465 int index = ((TableGroupNodeRealizer) nodeRealizer).getTable().columnAt(x,y).getIndex() + 1;
467 return nodeRealizer.getLabel(index).getText();
468 } else {
469 return super.getNodeTip(node);
471 }
472 }
473 };
474 }
475
476 void configureRealizers(final Graph2D graph) {
477 graph.setDefaultNodeRealizer(createDefaultNodeRealizer());
478 final DefaultHierarchyGraphFactory hgf =
479 (DefaultHierarchyGraphFactory) graph.getHierarchyManager().getGraphFactory();
480 hgf.setDefaultGroupNodeRealizer(createDefaultGroupNodeRealizer());
481 hgf.setDefaultFolderNodeRealizer(createDefaultFolderNodeRealizer());
482 }
483
484 private NodeRealizer createDefaultNodeRealizer() {
485 Factory factory = GenericNodeRealizer.getFactory();
486 Map map = factory.createDefaultConfigurationMap();
487 ShinyPlateNodePainter painter = new ShinyPlateNodePainter();
488 map.put(GenericNodeRealizer.Painter.class, painter);
489 map.put(GenericNodeRealizer.ContainsTest.class, painter);
490 factory.addConfiguration(NODE_CONFIGURATION, map);
491 GenericNodeRealizer gnr = new GenericNodeRealizer(NODE_CONFIGURATION);
492 gnr.setFillColor(NODE_COLOR);
493 gnr.setLineColor(NODE_LINE_COLOR);
494 gnr.setFillColor2(NODE_GRADIENT_COLOR);
495 gnr.setLineType(LineType.LINE_1);
496 return gnr;
497 }
498
499 private NodeRealizer createDefaultGroupNodeRealizer() {
500 GenericGroupNodeRealizer defaultGroup = new GenericGroupNodeRealizer();
501 defaultGroup.setConfiguration(CONFIGURATION_GROUP);
502 defaultGroup.setSize(100, 60);
503 defaultGroup.setFillColor(GROUP_NODE_COLOR);
504 defaultGroup.setGroupClosed(false);
505 defaultGroup.setLineType(LineType.LINE_2);
506 defaultGroup.setLineColor(GROUP_NODE_LINE_COLOR);
507 defaultGroup.getLabel().setBackgroundColor(GROUP_NODE_LABEL_COLOR);
508 defaultGroup.getLabel().setTextColor(getBlackOrWhite(GROUP_NODE_LABEL_COLOR));
509 return defaultGroup;
510 }
511
512 private NodeRealizer createDefaultFolderNodeRealizer() {
513 GenericGroupNodeRealizer defaultFolder = new GenericGroupNodeRealizer();
514 defaultFolder.setConfiguration(CONFIGURATION_GROUP);
515 defaultFolder.setSize(100, 60);
516 defaultFolder.setFillColor(GROUP_NODE_COLOR);
517 defaultFolder.setGroupClosed(true);
518 defaultFolder.setLineType(LineType.LINE_2);
519 defaultFolder.setLineColor(GROUP_NODE_LINE_COLOR);
520 defaultFolder.getLabel().setBackgroundColor(GROUP_NODE_LABEL_COLOR);
521 defaultFolder.getLabel().setTextColor(getBlackOrWhite(GROUP_NODE_LABEL_COLOR));
522 return defaultFolder;
523 }
524
525 private Color getBlackOrWhite(Color c) {
526 if (c.getRed() + c.getGreen() + c.getBlue() > 3 * 127) {
527 return Color.BLACK;
528 } else {
529 return Color.WHITE;
530 }
531 }
532
533
534 public static void main(String[] args) {
535 EventQueue.invokeLater(new Runnable() {
536 public void run() {
537 Locale.setDefault(Locale.ENGLISH);
538 initLnF();
539 (new SwimlaneGroupDemo()).start();
540 }
541 });
542 }
543
544
545
549 private static void initConfigurations() {
550 final Map map = TableGroupNodeRealizer.createDefaultConfigurationMap();
552 map.put(TableGroupNodeRealizer.Painter.class,
553 TableNodePainter.newAlternatingColumnsInstance());
554 map.put(TableGroupNodeRealizer.GenericMouseInputEditorProvider.class, null);
555
556 TableGroupNodeRealizer.getFactory()
558 .addConfiguration(SWIMLANE_CONFIGURATION, map);
559 }
560
561
562
566 class TriggerIncrementalLayout extends ViewMode {
567 private boolean dragging;
568 private boolean hasHitNodes;
569
570 TriggerIncrementalLayout() {
571 this.dragging = false;
572 this.hasHitNodes = false;
573 }
574
575 public void mouseDraggedLeft(final double x, final double y) {
576 dragging = true;
577 }
578
579 public void mousePressedLeft(final double x, final double y) {
580 final HitInfo info = new HitInfo(view, x, y, true, HitInfo.NODE);
581 hasHitNodes = info.hasHitNodes();
582 }
583
584 public void mouseReleasedLeft(final double x, final double y) {
585 if (dragging && hasHitNodes) {
586 layoutIncrementally();
587 }
588 hasHitNodes = false;
589 dragging = false;
590 }
591 }
592 }
593