1
14 package demo.layout.router;
15
16 import demo.view.DemoBase;
17 import y.base.Edge;
18 import y.base.EdgeCursor;
19 import y.base.GraphEvent;
20 import y.base.GraphListener;
21 import y.base.Node;
22 import y.base.NodeList;
23 import y.geom.YPoint;
24 import y.util.DataProviderAdapter;
25 import y.util.DataProviders;
26 import y.view.Arrow;
27 import y.view.BridgeCalculator;
28 import y.view.DefaultGraph2DRenderer;
29 import y.view.EdgeRealizer;
30 import y.view.EditMode;
31 import y.view.GenericNodeRealizer;
32 import y.view.Graph2D;
33 import y.view.Graph2DUndoManager;
34 import y.view.Graph2DView;
35 import y.view.Graph2DViewActions;
36 import y.view.HotSpotMode;
37 import y.view.MovePortMode;
38 import y.view.MoveSelectionMode;
39 import y.view.NodePort;
40 import y.view.NodeRealizer;
41 import y.view.SelectionBoxMode;
42 import y.view.ShapeNodePainter;
43 import y.view.ViewMode;
44
45 import javax.swing.AbstractAction;
46 import javax.swing.Action;
47 import javax.swing.ActionMap;
48 import javax.swing.JComponent;
49 import javax.swing.JMenu;
50 import javax.swing.JMenuBar;
51 import javax.swing.JPanel;
52 import javax.swing.JRootPane;
53 import javax.swing.JSplitPane;
54 import javax.swing.JToolBar;
55 import java.awt.BorderLayout;
56 import java.awt.Color;
57 import java.awt.EventQueue;
58 import java.awt.event.ActionEvent;
59 import java.net.URL;
60 import java.util.Locale;
61 import java.util.Map;
62
63
87 public class BusRouterDemo extends DemoBase {
88 static final String HUB_CONFIGURATION = "BusHub";
89 static final Object HUB_MARKER_DPKEY = "demo.layout.router.BusRouterDemo.HUB_MARKER_DPKEY";
90
91 static final int MODE_ALL = 0;
92 static final int MODE_SELECTED = 1;
93 static final int MODE_PARTIAL = 2;
94
95 private final BusDyer busDyer;
96 private JComponent glassPane;
97 private NodeRealizer hubRealizer;
98 private HubRoutingSupport hubRoutingSupport;
99 private Graph2DUndoManager undoManager;
100
101
104 public BusRouterDemo() {
105 this(null);
106 }
107
108
111 public BusRouterDemo(final String helpFilePath) {
112 busDyer = createBusDyer();
114 view.getGraph2D().addGraphListener(busDyer);
115
116 hubRoutingSupport = createHubRoutingSupport();
117
118 BusRouterDemoTools demoTools = new BusRouterDemoTools();
120 demoTools.setViewAndRouter(view, hubRoutingSupport.getModule().getBusRouter());
121 demoTools.updateGrid();
122 demoTools.updateSnapping();
123
124 JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, demoTools.createOptionComponent(), view);
125 mainSplitPane.setBorder(null);
126 contentPane.add(mainSplitPane, BorderLayout.CENTER);
127
128 addHelpPane(helpFilePath);
129
130 EventQueue.invokeLater(new Runnable() {
131 public void run() {
132 loadInitialGraph();
133 }
134 });
135 }
136
137 protected void loadInitialGraph() {
138 loadGraph("resource/threeBuses.graphml");
139 }
140
141
144 public void doLayout(final int mode) {
145 final Graph2D graph = view.getGraph2D();
146 final NodeRealizer oldNodeRealizer = graph.getDefaultNodeRealizer();
147
148 if (glassPane == null) {
149 glassPane = new JPanel();
151 final JRootPane rootPane = view.getRootPane();
152 rootPane.setGlassPane(glassPane);
153 }
154 glassPane.setEnabled(true);
155
156 try {
157 graph.backupRealizers();
159
160 setBridgeCalculatorEnabled(false);
162 graph.setDefaultNodeRealizer(getHubRealizer());
163
164 hubRoutingSupport.doLayout(graph, mode);
165 busDyer.colorize(null);
166 } finally {
167 graph.setDefaultNodeRealizer(oldNodeRealizer);
168 setBridgeCalculatorEnabled(true);
169
170 glassPane.setEnabled(false);
171 graph.updateViews();
172 }
173 }
174
175
178 protected void initialize() {
179 super.initialize();
180 hubRealizer = createHubRealizer();
181
182 setBridgeCalculatorEnabled(true);
183
184 view.getGraph2D().addDataProvider(HUB_MARKER_DPKEY, new DataProviderAdapter() {
186 public boolean getBool(Object dataHolder) {
187 return dataHolder instanceof Node && isHub((Node) dataHolder);
188 }
189 });
190
191 view.getGraph2D().addDataProvider(EditMode.ORTHOGONAL_ROUTING_DPKEY,
193 DataProviders.createConstantDataProvider(Boolean.TRUE));
194
195 undoManager = new Graph2DUndoManager(view.getGraph2D());
196 undoManager.setViewContainer(view);
197 }
198
199
203 protected void registerViewActions() {
204 super.registerViewActions();
205 ActionMap amap = view.getCanvasComponent().getActionMap();
207 if (amap != null) {
208 if (isDeletionEnabled()) {
209 amap.put(Graph2DViewActions.DELETE_SELECTION, createDeleteSelectionAction());
210 }
211
212 amap.put(Graph2DViewActions.SELECT_ALL, new Graph2DViewActions.SelectAllAction(view) {
214 protected void setSelected(Graph2D graph, Node node, boolean flag) {
215 if (!isHub(node)) {
216 super.setSelected(graph, node, flag);
217 }
218 }
219 });
220 }
221 }
222
223
226 protected Action createDeleteSelectionAction() {
227 final Action oldAction = super.createDeleteSelectionAction();
228 final Action newAction = new HubDeleteSelectionAction();
229 newAction.putValue(Action.SHORT_DESCRIPTION, oldAction.getValue(Action.SHORT_DESCRIPTION));
230 newAction.putValue(Action.SMALL_ICON, oldAction.getValue(Action.SMALL_ICON));
231 return newAction;
232 }
233
234
237 protected JToolBar createToolBar() {
238 JToolBar toolBar = super.createToolBar();
239 toolBar.setFloatable(false);
240
241 toolBar.addSeparator();
242
243 Action undoAction = undoManager.getUndoAction();
245 undoAction.putValue(Action.SMALL_ICON, getIconResource("resource/undo.png"));
246 undoAction.putValue(Action.SHORT_DESCRIPTION, "Undo");
247 toolBar.add(undoAction);
248
249 Action redoAction = undoManager.getRedoAction();
251 redoAction.putValue(Action.SMALL_ICON, getIconResource("resource/redo.png"));
252 redoAction.putValue(Action.SHORT_DESCRIPTION, "Redo");
253 toolBar.add(redoAction);
254
255 toolBar.addSeparator();
256
257 Action routeAllAction = new AbstractAction("Route All") {
259 public void actionPerformed(ActionEvent e) {
260 doLayout(MODE_ALL);
261 }
262 };
263 routeAllAction.putValue(Action.SHORT_DESCRIPTION, "Route all buses");
264 routeAllAction.putValue(Action.SMALL_ICON, SHARED_LAYOUT_ICON);
265 toolBar.add(createActionControl(routeAllAction));
266
267 Action routeSelectedAction = new AbstractAction("Route Selected") {
269 public void actionPerformed(ActionEvent e) {
270 doLayout(MODE_SELECTED);
271 }
272 };
273 routeSelectedAction.putValue(Action.SHORT_DESCRIPTION, "Route selected buses");
274 routeSelectedAction.putValue(Action.SMALL_ICON, SHARED_LAYOUT_ICON);
275 toolBar.add(createActionControl(routeSelectedAction, true));
276
277 Action propertiesAction = new AbstractAction("Settings...") {
279 public void actionPerformed(ActionEvent e) {
280 OptionSupport.showDialog(hubRoutingSupport.getModule(), view.getGraph2D(), false, view.getFrame());
281 }
282 };
283 propertiesAction.putValue(Action.SHORT_DESCRIPTION, "Configure the bus router");
284 propertiesAction.putValue(Action.SMALL_ICON, getIconResource("resource/properties.png"));
285 toolBar.add(createActionControl(propertiesAction));
286
287 return toolBar;
288 }
289
290
293 protected JMenuBar createMenuBar() {
294 final JMenuBar menuBar = super.createMenuBar();
295 JMenu menu = new JMenu("Sample Graphs");
296 menuBar.add(menu);
297
298 menu.add(new EmptyGraphAction("Empty Graph"));
299
300 menu.add(new AbstractAction("One Bus") {
301 public void actionPerformed(ActionEvent e) {
302 loadGraph("resource/oneBus.graphml");
303 }
304 });
305
306 menu.add(new AbstractAction("Three Buses") {
307 public void actionPerformed(ActionEvent e) {
308 loadGraph("resource/threeBuses.graphml");
309 }
310 });
311
312 return menuBar;
313 }
314
315
318 protected EditMode createEditMode() {
319 EditMode editMode = new HubEditMode();
320
321 if (editMode.getMovePortMode() instanceof MovePortMode) {
323 ((MovePortMode) editMode.getMovePortMode()).setIndicatingTargetNode(true);
324 }
325
326 editMode.allowMovingWithPopup(true);
328 return editMode;
329 }
330
331
334 protected BusDyer createBusDyer() {
335 return new BusDyer(view.getGraph2D());
336 }
337
338
341 protected HubRoutingSupport createHubRoutingSupport() {
342 return new HubRoutingSupport();
343 }
344
345
348 protected void configureDefaultRealizers() {
349 super.configureDefaultRealizers();
350
351 EdgeRealizer er = view.getGraph2D().getDefaultEdgeRealizer();
352 er.setTargetArrow(Arrow.NONE);
353 view.getGraph2D().setDefaultEdgeRealizer(er);
354 }
355
356
359 protected void loadGraph(URL resource) {
360 super.loadGraph(resource);
361 undoManager.resetQueue();
362
363 EventQueue.invokeLater(new Runnable() {
364 public void run() {
365 doLayout(MODE_ALL);
366 }
367 });
368 }
369
370
373 private void setBridgeCalculatorEnabled(boolean enable) {
374 if (enable) {
375 BridgeCalculator bridgeCalculator = new BridgeCalculator();
377 ((DefaultGraph2DRenderer) view.getGraph2DRenderer()).setBridgeCalculator(bridgeCalculator);
378 bridgeCalculator.setCrossingMode(BridgeCalculator.CROSSING_MODE_ORDER_INDUCED);
379 bridgeCalculator.setCrossingStyle(BridgeCalculator.CROSSING_STYLE_ARC);
380 bridgeCalculator.setOrientationStyle(BridgeCalculator.ORIENTATION_STYLE_UP);
381 } else {
382 ((DefaultGraph2DRenderer) view.getGraph2DRenderer()).setBridgeCalculator(null);
383 }
384 }
385
386 NodeRealizer getHubRealizer() {
387 return hubRealizer;
388 }
389
390
393 static boolean isHub(final Node node) {
394 final NodeRealizer realizer = ((Graph2D) node.getGraph()).getRealizer(node);
395 return realizer instanceof GenericNodeRealizer
396 && HUB_CONFIGURATION.equals(((GenericNodeRealizer) realizer).getConfiguration());
397 }
398
399
402 static NodeRealizer createHubRealizer() {
403 final GenericNodeRealizer.Factory factory = GenericNodeRealizer.getFactory();
404 final Map map = GenericNodeRealizer.getFactory().createDefaultConfigurationMap();
405
406 map.put(GenericNodeRealizer.Painter.class, new ShapeNodePainter(ShapeNodePainter.RECT));
407 factory.addConfiguration(HUB_CONFIGURATION, map);
408
409 NodeRealizer nr = new GenericNodeRealizer(HUB_CONFIGURATION);
410 nr.setFillColor(Color.BLACK);
411 nr.setLineColor(null);
412 nr.setSize(5.0, 5.0);
413 nr.removeLabel(nr.getLabel(0));
414 return nr;
415 }
416
417
423 protected class HubEditMode extends EditMode {
424 protected HubEditMode() {
425 setCreateEdgeMode(new AutoRoutingCreateEdgeMode(getHubRealizer()));
426 }
427
428
432 protected ViewMode createMoveSelectionMode() {
433 return new MoveSelectionMode() {
434 protected void selectionMovedAction(double dx, double dy, double x, double y) {
435 super.selectionMovedAction(dx, dy, x, y);
436 doLayout(MODE_PARTIAL);
437 }
438 };
439 }
440
441 protected ViewMode createCreateEdgeMode() {
442 return null;
443 }
444
445 protected ViewMode createMovePortMode() {
446 return null;
447 }
448
449
452 protected ViewMode createHotSpotMode() {
453 return new HotSpotMode() {
454 private boolean dirty;
455
456 public void mousePressedLeft(double x, double y) {
457 dirty = false;
458 super.mousePressedLeft(x, y);
459 }
460
461 public void mouseReleasedLeft(double x, double y) {
462 super.mouseReleasedLeft(x, y);
463 if (dirty) {
464 doLayout(MODE_PARTIAL);
465 }
466 dirty = false;
467 }
468
469 protected void updateNodeRealizerBounds(NodeRealizer vr, double x, double y, double w, double h) {
470 super.updateNodeRealizerBounds(vr, x, y, w, h);
471 dirty = true;
472 }
473 };
474 }
475
476
479 protected ViewMode createSelectionBoxMode() {
480 return new SelectionBoxMode() {
481 protected void setSelected(Graph2D graph, Node n, boolean state) {
482 if (!isHub(n)) {
483 super.setSelected(graph, n, state);
484 }
485 }
486 };
487 }
488
489
492 protected void setSelected(Graph2D graph, Node node, boolean state) {
493 if (!isHub(node)) {
494 super.setSelected(graph, node, state);
495 }
496 }
497
498
501 protected void nodeClicked(Graph2D graph, Node node, boolean wasSelected, double x, double y,
502 boolean modifierSet) {
503 if (isHub(node)) {
504 if (!modifierSet) {
505 graph.unselectAll();
506 }
507
508 if (!modifierSet || graph.isSelectionEmpty() || graph.selectedEdges().ok()) {
509 for (EdgeCursor edgeCursor = node.edges(); edgeCursor.ok(); edgeCursor.next()) {
510 final Edge edge = edgeCursor.edge();
511 setSelected(graph, edge, true);
512 }
513 }
514 graph.updateViews();
515 } else {
516 super.nodeClicked(graph, node, wasSelected, x, y, modifierSet);
517 }
518 }
519
520
523 public void mouseDraggedLeft(double x, double y) {
524 if (isModifierPressed(lastPressEvent)) {
525 double px = translateX(lastPressEvent.getX());
526 double py = translateY(lastPressEvent.getY());
527 Edge edge = getHitInfo(px, py).getHitEdge();
528 if (edge != null) {
529 setChild(getCreateEdgeMode(), lastPressEvent, lastDragEvent);
530 return;
531 }
532 }
533 super.mouseDraggedLeft(x, y);
534 }
535
536 }
537
538
547 protected class AutoRoutingCreateEdgeMode extends HubCreateEdgeMode {
548
549 protected AutoRoutingCreateEdgeMode(NodeRealizer hubRealizer) {
550 super(hubRealizer);
551 }
552
553 protected void edgeCreated(final Edge edge) {
554 super.edgeCreated(edge);
555 if (!isHub(edge.source()) && !isHub(edge.target())) {
557 final Edge edge2 = splitSingleBusEdge(edge);
559 EventQueue.invokeLater(new Runnable() {
560 public void run() {
561 getGraph2D().unselectAll();
562 getGraph2D().setSelected(edge, true);
563 getGraph2D().setSelected(edge2, true);
564 doLayout(MODE_SELECTED);
565 }
566 });
567 } else if (isHub(edge.source()) && isHub(edge.target())) {
568 EventQueue.invokeLater(new Runnable() {
570 public void run() {
571 getGraph2D().unselectAll();
572 getGraph2D().setSelected(edge, true);
573 doLayout(MODE_SELECTED);
574 }
575 });
576 } else {
577 EventQueue.invokeLater(new Runnable() {
579 public void run() {
580 getGraph2D().unselectAll();
581 getGraph2D().setSelected(edge, true);
582 doLayout(MODE_PARTIAL);
583 }
584 });
585 }
586 }
587
588
595 protected Edge splitSingleBusEdge(Edge edge) {
596 final Graph2D graph = getGraph2D();
597 final Node oldSource = edge.source();
598 final Node oldTarget = edge.target();
599
600 graph.firePreEvent();
601 try {
602
605 final Node hub = graph.createNode(getHubRealizer().createCopy());
606 graph.setCenter(hub, YPoint.midPoint(graph.getSourcePointAbs(edge), graph.getTargetPointAbs(edge)));
607
608 graph.changeEdge(edge, oldSource, hub);
609 graph.setTargetPointRel(edge, YPoint.ORIGIN);
610
611 final EdgeRealizer edgeRealizer = graph.getRealizer(edge);
612 final EdgeRealizer edgeRealizer2 = edgeRealizer.createCopy();
613 final Edge edge2 = graph.createEdge(hub, oldTarget, edgeRealizer2);
614 graph.setSourcePointRel(edge2, YPoint.ORIGIN);
615
616 final NodePort targetPort = NodePort.getTargetPort(edgeRealizer);
617 if (isNodePortAware() && targetPort != null) {
618 NodePort.bindTargetPort(targetPort, edgeRealizer2);
619 }
620
621 return edge2;
622 } finally {
623 graph.firePostEvent();
624 }
625 }
626 }
627
628
632 protected class HubDeleteSelectionAction extends Graph2DViewActions.DeleteSelectionAction {
633
634 protected HubDeleteSelectionAction() {
635 super(BusRouterDemo.this.view);
636 }
637
638 public void delete(Graph2DView view) {
639 final Graph2D graph = view.getGraph2D();
640 try {
641 graph.firePreEvent();
642 deleteImpl(view);
643 } finally {
644 graph.firePostEvent();
645 }
646 }
647
648
652 private void deleteImpl(Graph2DView view) {
653 final NodeList hubsToDelete = new NodeList();
654
655 GraphListener listener = new GraphListener() {
656 public void onGraphEvent(GraphEvent e) {
657 if (e.getType() == GraphEvent.PRE_EDGE_REMOVAL) {
658 final Edge edge = (Edge) e.getData();
659 if (isHubToDelete(edge.source())) {
660 hubsToDelete.add(edge.source());
661 }
662 if (isHubToDelete(edge.target())) {
663 hubsToDelete.add(edge.target());
664 }
665 }
666 }
667
668 private boolean isHubToDelete(Node node) {
669 return isHub(node) && node.degree() < 3;
671 }
672 };
673
674 final Graph2D graph = view.getGraph2D();
675 try {
676 graph.addGraphListener(listener);
677 super.delete(view);
678
679 while (!hubsToDelete.isEmpty()) {
680 final Node node = hubsToDelete.popNode();
681 if (node.getGraph() != null) {
682 graph.removeNode(node);
683 }
684 }
685 } finally {
686 graph.removeGraphListener(listener);
687 }
688 }
689 }
690
691
694 protected class EmptyGraphAction extends AbstractAction {
695
696 protected EmptyGraphAction(String name) {
697 super(name);
698 }
699
700 public void actionPerformed(ActionEvent e) {
701 view.getGraph2D().clear();
702 view.getGraph2D().setURL(null);
703 view.fitContent();
704 view.updateView();
705 undoManager.resetQueue();
706 }
707 }
708
709
714 public static void main(String[] args) {
715 EventQueue.invokeLater(new Runnable() {
716 public void run() {
717 Locale.setDefault(Locale.ENGLISH);
718 initLnF();
719 new BusRouterDemo("resource/busrouterhelp.html").start("Bus Router Demo");
720 }
721 });
722 }
723 }
724