1   
28  package demo.layout.router;
29  
30  import demo.view.DemoBase;
31  import y.base.Edge;
32  import y.base.EdgeCursor;
33  import y.base.GraphEvent;
34  import y.base.GraphListener;
35  import y.base.Node;
36  import y.base.NodeList;
37  import y.geom.YPoint;
38  import y.util.DataProviderAdapter;
39  import y.util.DataProviders;
40  import y.view.Arrow;
41  import y.view.BridgeCalculator;
42  import y.view.DefaultGraph2DRenderer;
43  import y.view.EdgeRealizer;
44  import y.view.EditMode;
45  import y.view.GenericNodeRealizer;
46  import y.view.Graph2D;
47  import y.view.Graph2DView;
48  import y.view.Graph2DViewActions;
49  import y.view.HotSpotMode;
50  import y.view.MovePortMode;
51  import y.view.MoveSelectionMode;
52  import y.view.NodePort;
53  import y.view.NodeRealizer;
54  import y.view.SelectionBoxMode;
55  import y.view.ShapeNodePainter;
56  import y.view.ViewMode;
57  
58  import javax.swing.AbstractAction;
59  import javax.swing.Action;
60  import javax.swing.ActionMap;
61  import javax.swing.JComponent;
62  import javax.swing.JMenu;
63  import javax.swing.JMenuBar;
64  import javax.swing.JPanel;
65  import javax.swing.JRootPane;
66  import javax.swing.JSplitPane;
67  import javax.swing.JToolBar;
68  import java.awt.BorderLayout;
69  import java.awt.Color;
70  import java.awt.EventQueue;
71  import java.awt.event.ActionEvent;
72  import java.net.URL;
73  import java.util.Locale;
74  import java.util.Map;
75  
76  
100 public class BusRouterDemo extends DemoBase {
101   static final String HUB_CONFIGURATION = "BusHub";
102   static final Object HUB_MARKER_DPKEY = "demo.layout.router.BusRouterDemo.HUB_MARKER_DPKEY";
103 
104   static final int MODE_ALL = 0;
105   static final int MODE_SELECTED = 1;
106   static final int MODE_PARTIAL = 2;
107 
108   private final BusDyer busDyer;
109   private JComponent glassPane;
110   private NodeRealizer hubRealizer;
111   private HubRoutingSupport hubRoutingSupport;
112 
113   
116   public BusRouterDemo() {
117     this(null);
118   }
119 
120   
123   public BusRouterDemo(final String helpFilePath) {
124         busDyer = createBusDyer();
126     view.getGraph2D().addGraphListener(busDyer);
127 
128     hubRoutingSupport = createHubRoutingSupport();
129 
130         BusRouterDemoTools demoTools = new BusRouterDemoTools();
132     demoTools.setViewAndRouter(view, hubRoutingSupport.getModule());
133     demoTools.updateGrid();
134     demoTools.updateSnapping();
135 
136     JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, demoTools.createOptionComponent(), view);
137     mainSplitPane.setBorder(null);
138     contentPane.add(mainSplitPane, BorderLayout.CENTER);
139 
140     addHelpPane(helpFilePath);
141 
142     EventQueue.invokeLater(new Runnable() {
143       public void run() {
144         loadInitialGraph();
145       }
146     });
147   }
148 
149   protected void loadInitialGraph() {
150     loadGraph("resource/threeBuses.graphml");
151   }
152 
153   protected boolean isClipboardEnabled() {
154     return false;
155   }
156 
157   
160   public void doLayout(final int mode) {
161     final Graph2D graph = view.getGraph2D();
162     final NodeRealizer oldNodeRealizer = graph.getDefaultNodeRealizer();
163 
164     if (glassPane == null) {
165             glassPane = new JPanel();
167       final JRootPane rootPane = view.getRootPane();
168       rootPane.setGlassPane(glassPane);
169     }
170     glassPane.setEnabled(true);
171 
172     graph.firePreEvent();
173     try {
174             graph.backupRealizers();
176 
177             setBridgeCalculatorEnabled(false);
179       graph.setDefaultNodeRealizer(getHubRealizer());
180 
181       hubRoutingSupport.doLayout(graph, mode);
182       busDyer.colorize(null);
183     } finally {
184       graph.setDefaultNodeRealizer(oldNodeRealizer);
185       setBridgeCalculatorEnabled(true);
186 
187       glassPane.setEnabled(false);
188       graph.updateViews();
189       graph.firePostEvent();
190     }
191   }
192 
193   
196   protected void initialize() {
197     super.initialize();
198     hubRealizer = createHubRealizer();
199 
200     setBridgeCalculatorEnabled(true);
201 
202         view.getGraph2D().addDataProvider(HUB_MARKER_DPKEY, new DataProviderAdapter() {
204       public boolean getBool(Object dataHolder) {
205         return dataHolder instanceof Node && isHub((Node) dataHolder);
206       }
207     });
208 
209         view.getGraph2D().addDataProvider(EditMode.ORTHOGONAL_ROUTING_DPKEY,
211         DataProviders.createConstantDataProvider(Boolean.TRUE));
212   }
213 
214   
218   protected void registerViewActions() {
219     super.registerViewActions();
220         ActionMap amap = view.getCanvasComponent().getActionMap();
222     if (amap != null) {
223       if (isDeletionEnabled()) {
224         amap.put(Graph2DViewActions.DELETE_SELECTION, createDeleteSelectionAction());
225       }
226 
227             amap.put(Graph2DViewActions.SELECT_ALL, new Graph2DViewActions.SelectAllAction(view) {
229         protected void setSelected(Graph2D graph, Node node, boolean flag) {
230           if (!isHub(node)) {
231             super.setSelected(graph, node, flag);
232           }
233         }
234       });
235     }
236   }
237 
238   
241   protected Action createDeleteSelectionAction() {
242     final Action oldAction = super.createDeleteSelectionAction();
243     final Action newAction = new HubDeleteSelectionAction();
244     newAction.putValue(Action.SHORT_DESCRIPTION, oldAction.getValue(Action.SHORT_DESCRIPTION));
245     newAction.putValue(Action.SMALL_ICON, oldAction.getValue(Action.SMALL_ICON));
246     return newAction;
247   }
248 
249   
252   protected JToolBar createToolBar() {
253     JToolBar toolBar = super.createToolBar();
254     toolBar.setFloatable(false);
255 
256     toolBar.addSeparator();
257 
258         Action routeAllAction = new AbstractAction("Route All") {
260       public void actionPerformed(ActionEvent e) {
261         doLayout(MODE_ALL);
262       }
263     };
264     routeAllAction.putValue(Action.SHORT_DESCRIPTION, "Route all buses");
265     routeAllAction.putValue(Action.SMALL_ICON, SHARED_LAYOUT_ICON);
266     toolBar.add(createActionControl(routeAllAction));
267 
268         Action routeSelectedAction = new AbstractAction("Route Selected") {
270       public void actionPerformed(ActionEvent e) {
271         doLayout(MODE_SELECTED);
272       }
273     };
274     routeSelectedAction.putValue(Action.SHORT_DESCRIPTION, "Route selected buses");
275     routeSelectedAction.putValue(Action.SMALL_ICON, SHARED_LAYOUT_ICON);
276     toolBar.add(createActionControl(routeSelectedAction, true));
277 
278         Action propertiesAction = new AbstractAction("Settings...") {
280       public void actionPerformed(ActionEvent e) {
281         OptionSupport.showDialog(hubRoutingSupport.getModule(), view.getGraph2D(), false, view.getFrame());
282       }
283     };
284     propertiesAction.putValue(Action.SHORT_DESCRIPTION, "Configure the bus router");
285     propertiesAction.putValue(Action.SMALL_ICON, getIconResource("resource/properties.png"));
286     toolBar.add(createActionControl(propertiesAction));
287 
288     return toolBar;
289   }
290 
291   
294   protected JMenuBar createMenuBar() {
295     final JMenuBar menuBar = super.createMenuBar();
296     JMenu menu = new JMenu("Sample Graphs");
297     menuBar.add(menu);
298 
299     menu.add(new EmptyGraphAction("Empty Graph"));
300 
301     menu.add(new AbstractAction("One Bus") {
302       public void actionPerformed(ActionEvent e) {
303         loadGraph("resource/oneBus.graphml");
304       }
305     });
306 
307     menu.add(new AbstractAction("Three Buses") {
308       public void actionPerformed(ActionEvent e) {
309         loadGraph("resource/threeBuses.graphml");
310       }
311     });
312 
313     return menuBar;
314   }
315 
316   
319   protected EditMode createEditMode() {
320     EditMode editMode = new HubEditMode();
321 
322         if (editMode.getMovePortMode() instanceof MovePortMode) {
324       ((MovePortMode) editMode.getMovePortMode()).setIndicatingTargetNode(true);
325     }
326 
327         editMode.allowMovingWithPopup(true);
329     return editMode;
330   }
331 
332   
335   protected BusDyer createBusDyer() {
336     return new BusDyer(view.getGraph2D());
337   }
338 
339   
342   protected HubRoutingSupport createHubRoutingSupport() {
343     return new HubRoutingSupport();
344   }
345 
346   
349   protected void configureDefaultRealizers() {
350     super.configureDefaultRealizers();
351 
352     EdgeRealizer er = view.getGraph2D().getDefaultEdgeRealizer();
353     er.setTargetArrow(Arrow.NONE);
354     view.getGraph2D().setDefaultEdgeRealizer(er);
355   }
356 
357   
360   protected void loadGraph(URL resource) {
361     super.loadGraph(resource);
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 Edge createEdge(Graph2D graph, Node startNode, Node targetNode, EdgeRealizer realizer) {
554             graph.firePreEvent();
556       return super.createEdge(graph, startNode, targetNode, realizer);
557     }
558 
559     protected void edgeCreated(final Edge edge) {
560       super.edgeCreated(edge);
561             if (!isHub(edge.source()) && !isHub(edge.target())) {
563                 final Edge edge2 = splitSingleBusEdge(edge);
565         EventQueue.invokeLater(new Runnable() {
566           public void run() {
567             getGraph2D().unselectAll();
568             getGraph2D().setSelected(edge, true);
569             getGraph2D().setSelected(edge2, true);
570             doLayout(MODE_SELECTED);
571 
572                         getGraph2D().firePostEvent();
574           }
575         });
576       } else if (isHub(edge.source()) && isHub(edge.target())) {
577                 EventQueue.invokeLater(new Runnable() {
579           public void run() {
580             getGraph2D().unselectAll();
581             getGraph2D().setSelected(edge, true);
582             doLayout(MODE_SELECTED);
583 
584                         getGraph2D().firePostEvent();
586           }
587         });
588       } else {
589                 EventQueue.invokeLater(new Runnable() {
591           public void run() {
592             getGraph2D().unselectAll();
593             getGraph2D().setSelected(edge, true);
594             doLayout(MODE_PARTIAL);
595 
596                         getGraph2D().firePostEvent();
598           }
599         });
600       }
601     }
602 
603     
610     protected Edge splitSingleBusEdge(Edge edge) {
611       final Graph2D graph = getGraph2D();
612       final Node oldSource = edge.source();
613       final Node oldTarget = edge.target();
614 
615       graph.firePreEvent();
616       try {
617                 
620         final Node hub = graph.createNode(getHubRealizer().createCopy());
621         graph.setCenter(hub, YPoint.midPoint(graph.getSourcePointAbs(edge), graph.getTargetPointAbs(edge)));
622 
623         graph.changeEdge(edge, oldSource, hub);
624         graph.setTargetPointRel(edge, YPoint.ORIGIN);
625 
626         final EdgeRealizer edgeRealizer = graph.getRealizer(edge);
627         final EdgeRealizer edgeRealizer2 = edgeRealizer.createCopy();
628         final Edge edge2 = graph.createEdge(hub, oldTarget, edgeRealizer2);
629         graph.setSourcePointRel(edge2, YPoint.ORIGIN);
630 
631         final NodePort targetPort = NodePort.getTargetPort(edgeRealizer);
632         if (isNodePortAware() && targetPort != null) {
633           NodePort.bindTargetPort(targetPort, edgeRealizer2);
634         }
635 
636         return edge2;
637       } finally {
638         graph.firePostEvent();
639       }
640     }
641   }
642 
643   
647   protected class HubDeleteSelectionAction extends Graph2DViewActions.DeleteSelectionAction {
648 
649     protected HubDeleteSelectionAction() {
650       super(BusRouterDemo.this.view);
651     }
652 
653     public void delete(Graph2DView view) {
654       final Graph2D graph = view.getGraph2D();
655       try {
656         graph.firePreEvent();
657         deleteImpl(view);
658       } finally {
659         graph.firePostEvent();
660       }
661     }
662 
663     
667     private void deleteImpl(Graph2DView view) {
668       final NodeList hubsToDelete = new NodeList();
669 
670       GraphListener listener = new GraphListener() {
671         public void onGraphEvent(GraphEvent e) {
672           if (e.getType() == GraphEvent.PRE_EDGE_REMOVAL) {
673             final Edge edge = (Edge) e.getData();
674             if (isHubToDelete(edge.source())) {
675               hubsToDelete.add(edge.source());
676             }
677             if (isHubToDelete(edge.target())) {
678               hubsToDelete.add(edge.target());
679             }
680           }
681         }
682 
683         private boolean isHubToDelete(Node node) {
684                     return isHub(node) && node.degree() < 3;
686         }
687       };
688 
689       final Graph2D graph = view.getGraph2D();
690       try {
691         graph.addGraphListener(listener);
692         super.delete(view);
693 
694         while (!hubsToDelete.isEmpty()) {
695           final Node node = hubsToDelete.popNode();
696           if (node.getGraph() != null) {
697             graph.removeNode(node);
698           }
699         }
700       } finally {
701         graph.removeGraphListener(listener);
702       }
703     }
704   }
705 
706   
709   protected class EmptyGraphAction extends AbstractAction {
710 
711     protected EmptyGraphAction(String name) {
712       super(name);
713     }
714 
715     public void actionPerformed(ActionEvent e) {
716       view.getGraph2D().clear();
717       view.getGraph2D().setURL(null);
718       view.fitContent();
719       view.updateView();
720       getUndoManager().resetQueue();
721     }
722   }
723 
724   
729   public static void main(String[] args) {
730     EventQueue.invokeLater(new Runnable() {
731       public void run() {
732         Locale.setDefault(Locale.ENGLISH);
733         initLnF();
734         new BusRouterDemo("resource/busrouterhelp.html").start("Bus Router Demo");
735       }
736     });
737   }
738 }
739