1
28 package demo.layout.router;
29
30 import demo.view.DemoBase;
31 import demo.view.DemoDefaults;
32 import y.base.DataProvider;
33 import y.base.Edge;
34 import y.base.EdgeCursor;
35 import y.base.EdgeMap;
36 import y.base.Node;
37 import y.base.NodeList;
38 import y.io.IOHandler;
39 import y.layout.Layouter;
40 import y.layout.PortConstraintConfigurator;
41 import y.layout.PortConstraintKeys;
42 import y.layout.router.ChannelEdgeRouter;
43 import y.layout.router.OrthogonalEdgeRouter;
44 import y.layout.router.polyline.EdgeRouter;
45 import demo.layout.module.ChannelEdgeRouterModule;
46 import demo.layout.module.OrthogonalEdgeRouterModule;
47 import demo.layout.module.PolylineEdgeRouterModule;
48 import y.module.YModule;
49 import y.option.OptionHandler;
50 import y.util.DataProviderAdapter;
51 import y.view.Bend;
52 import y.view.BendCursor;
53 import y.view.CreateEdgeMode;
54 import y.view.DefaultGraph2DRenderer;
55 import y.view.Drawable;
56 import y.view.EdgeRealizer;
57 import y.view.EditMode;
58 import y.view.Graph2D;
59 import y.view.Graph2DView;
60 import y.view.HotSpotMode;
61 import y.view.MovePortMode;
62 import y.view.MoveSelectionMode;
63 import y.view.Port;
64 import y.view.Selections;
65
66 import javax.swing.AbstractAction;
67 import javax.swing.JComboBox;
68 import javax.swing.JToolBar;
69 import java.awt.EventQueue;
70 import java.awt.Graphics2D;
71 import java.awt.Rectangle;
72 import java.awt.event.ActionEvent;
73 import java.awt.event.ActionListener;
74 import java.io.IOException;
75 import java.util.HashSet;
76 import java.util.Locale;
77 import java.util.Set;
78
79
105 public class MazeRouterDemo extends DemoBase {
106 private RouterStrategy strategy;
107 private Graph2D mazeG;
108 private Drawable mazeD;
109 private NodeList mazeNodes;
110 private OrthogonalEdgeRouterStrategy orthogonalEdgeRouterStrategy;
111 private ChannelEdgeRouterStrategy channelEdgeRouterStrategy;
112 private PolylineEdgeRouterStrategy polylineEdgeRouterStrategy;
113
114 public MazeRouterDemo() {
115 initializeMaze();
116
117 initializeGraph();
118 }
119
120 protected void initialize() {
121 channelEdgeRouterStrategy = new ChannelEdgeRouterStrategy();
122 orthogonalEdgeRouterStrategy = new OrthogonalEdgeRouterStrategy();
123 polylineEdgeRouterStrategy = new PolylineEdgeRouterStrategy();
124 view.setContentPolicy(Graph2DView.CONTENT_POLICY_BACKGROUND_DRAWABLES);
125 }
126
127 protected void configureDefaultRealizers() {
128 super.configureDefaultRealizers();
129 view.getGraph2D().getDefaultNodeRealizer().setSize(30, 30);
130 }
131
132
135 protected JToolBar createToolBar() {
136 final JComboBox comboBox = new JComboBox(new Object[]{"Polyline Edge Router", "Orthogonal Edge Router", "Channel Edge Router"});
137 comboBox.setMaximumSize(comboBox.getPreferredSize());
138 comboBox.addActionListener(new ActionListener() {
139 public void actionPerformed(ActionEvent e) {
140 switch (comboBox.getSelectedIndex()) {
141 case 0:
142 strategy = polylineEdgeRouterStrategy;
143 break;
144 case 1:
145 strategy = orthogonalEdgeRouterStrategy;
146 break;
147 case 2:
148 strategy = channelEdgeRouterStrategy;
149 }
150 doLayout();
151 }
152 });
153 strategy = polylineEdgeRouterStrategy;
154
155 JToolBar toolBar = super.createToolBar();
156 toolBar.addSeparator();
157 toolBar.add(createActionControl(new LayoutAction()));
158 toolBar.addSeparator(TOOLBAR_SMALL_SEPARATOR);
159 toolBar.add(comboBox);
160 toolBar.addSeparator(TOOLBAR_SMALL_SEPARATOR);
161 toolBar.add(createActionControl(new OptionAction()));
162
163 return toolBar;
164 }
165
166
169 class OptionAction extends AbstractAction {
170 OptionAction() {
171 super("Settings...", getIconResource("resource/properties.png"));
172 }
173
174 public void actionPerformed(ActionEvent e) {
175 final ActionListener listener = new ActionListener() {
176 public void actionPerformed(ActionEvent e) {
177 doLayout();
178 }
179 };
180 OptionSupport.showDialog(strategy.getModule().getOptionHandler(), listener, false, view.getFrame());
181 }
182 }
183
184
187 class LayoutAction extends AbstractAction {
188 LayoutAction() {
189 super("Route Edges", SHARED_LAYOUT_ICON);
190 }
191
192 public void actionPerformed(ActionEvent e) {
193 doLayout();
194 }
195 }
196
197
200 class FitContent extends AbstractAction {
201 FitContent() {
202 super("Fit Content");
203 }
204
205 public void actionPerformed(ActionEvent e) {
206 Graph2D graph = view.getGraph2D();
207
208 Rectangle r = graph.getBoundingBox();
209 r.add(mazeD.getBounds());
210 view.fitRectangle(r);
211 graph.updateViews();
212 }
213 }
214
215 void doLayout() {
216 Graph2D graph = view.getGraph2D();
217 graph.firePreEvent();
218 try {
219 addMazeGraph();
220 strategy.getModule().start(graph);
222 subtractMazeGraph();
223 } finally {
224 graph.firePostEvent();
225 }
226 }
227
228
234 protected void registerViewModes() {
235 EditMode mode = new EditMode();
236 view.addViewMode(mode);
237
238 mode.setMoveSelectionMode(new MyMoveSelectionMode());
239 mode.setCreateEdgeMode(new MyCreateEdgeMode());
240 mode.setHotSpotMode(new MyHotSpotMode());
241 mode.setMovePortMode(new MyMovePortMode());
242 }
243
244
247 class MyCreateEdgeMode extends CreateEdgeMode {
248 private Node source;
249
250 protected boolean acceptSourceNode(Node s, double x, double y) {
251 source = s;
252 return true;
253 }
254
255 protected boolean acceptTargetNode(Node t, double x, double y) {
256 return (source != t);
257 }
258
259 protected Edge createEdge(Graph2D graph, Node startNode, Node targetNode, EdgeRealizer realizer) {
260 graph.firePreEvent();
261 return super.createEdge(graph, startNode, targetNode, realizer);
262 }
263
264 protected void edgeCreated(final Edge e) {
265 routeEdge(e);
266 getGraph2D().firePostEvent();
267 }
268 }
269
270 void routeEdge(Edge e) {
271 final Graph2D graph = view.getGraph2D();
272 addMazeGraph();
273 strategy.routeEdge(e);
274 subtractMazeGraph();
275 graph.updateViews();
276 }
277
278
281 class MyHotSpotMode extends HotSpotMode {
282 public void mouseReleasedLeft(double x, double y) {
283 super.mouseReleasedLeft(x, y);
284
285 final Graph2D graph = view.getGraph2D();
286
287 DataProvider selectedNodes = Selections.createSelectionDataProvider(graph);
288 addMazeGraph();
289 strategy.rerouteAdjacentEdges(selectedNodes, graph);
290 subtractMazeGraph();
291 graph.updateViews();
292 }
293 }
294
295
298 class MyMoveSelectionMode extends MoveSelectionMode {
299 private static final boolean ROUTE_EDGES_ON_MOVE = false;
300
301 protected void selectionOnMove(double dx, double dy, double x, double y) {
302 if (ROUTE_EDGES_ON_MOVE) {
303 routeEdgesToSelection(false);
304 }
305 }
306
307 protected void selectionMovedAction(double dx, double dy, double x, double y) {
308 routeEdgesToSelection(true);
309 }
310
311 void routeEdgesToSelection(boolean includeBends) {
312 final Graph2D graph = view.getGraph2D();
313 graph.firePreEvent();
314 graph.backupRealizers();
315 try {
316 if (graph.selectedNodes().ok() || (includeBends && graph.selectedBends().ok())) {
317 addMazeGraph();
318 strategy.routeEdgesToSelection(graph);
319 subtractMazeGraph();
320 graph.updateViews();
321 }
322 } finally {
323 graph.firePostEvent();
324 }
325 }
326 }
327
328 class MyMovePortMode extends MovePortMode {
329 MyMovePortMode() {
330 setChangeEdgeEnabled(true);
331 setIndicatingTargetNode(true);
332 }
333
334 protected void portMoved(Port port, double x, double y) {
335 super.portMoved(port, x, y);
336 final Edge edge = port.getOwner().getEdge();
337 strategy.routeEdge(edge);
338 }
339 }
340
341
345 private void addMazeGraph() {
346 mazeNodes = new NodeList(mazeG.nodes());
347 mazeG.moveSubGraph(mazeNodes, view.getGraph2D());
348 }
349
350
353 private void subtractMazeGraph() {
354 view.getGraph2D().moveSubGraph(mazeNodes, mazeG);
355 }
356
357
360 private void initializeMaze() {
361 mazeG = new Graph2D();
362 try {
363 IOHandler ioHandler = createGraphMLIOHandler();
364 ioHandler.read(mazeG, getResource("resource/maze.graphml"));
365 DemoDefaults.applyFillColor(mazeG, DemoDefaults.DEFAULT_CONTRAST_COLOR);
366 DemoDefaults.applyLineColor(mazeG, DemoDefaults.DEFAULT_CONTRAST_COLOR);
367
368 } catch (IOException e) {
369 System.out.println("Could not initialize maze!");
370 e.printStackTrace();
371 System.exit(-1);
372 }
373 mazeD = new MazeDrawable(mazeG);
376 view.addBackgroundDrawable(mazeD);
377 view.fitRectangle(mazeD.getBounds());
378 }
379
380
383 private void initializeGraph() {
384 loadGraph("resource/mazeRouterDemo.graphml");
385 }
386
389 public static void main(String[] args) {
390 EventQueue.invokeLater(new Runnable() {
391 public void run() {
392 Locale.setDefault(Locale.ENGLISH);
393 initLnF();
394 (new MazeRouterDemo()).start();
395 }
396 });
397 }
398
399
402 static class MazeDrawable implements Drawable {
403 private Graph2D mazeG;
404 private DefaultGraph2DRenderer render;
405
406 public MazeDrawable(Graph2D g) {
407 mazeG = g;
408 render = new DefaultGraph2DRenderer();
409 }
410
411 public Rectangle getBounds() {
412 return mazeG.getBoundingBox();
413 }
414
415 public void paint(Graphics2D gfx) {
416 render.paint(gfx, mazeG);
417 }
418 }
419
420 abstract static class RouterStrategy {
421 abstract YModule getModule();
422
423 abstract void routeEdge(Edge e);
424
425 abstract void rerouteAdjacentEdges(final DataProvider selectedNodes, final Graph2D graph);
426
427 abstract void routeEdgesToSelection(final Graph2D graph);
428
429 abstract void route(final Graph2D graph);
430
431 protected void routeEdge(final Edge e, final Graph2D graph) {
432 EdgeMap spc = (EdgeMap) graph.getDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY);
433 EdgeMap tpc = (EdgeMap) graph.getDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY);
434
435 PortConstraintConfigurator pcc = new PortConstraintConfigurator();
436 if (spc != null && tpc != null) {
437 spc.set(e, pcc.createPortConstraintFromSketch(graph, e, true, false));
438 tpc.set(e, pcc.createPortConstraintFromSketch(graph, e, false, false));
439 route(graph);
440 spc.set(e, null);
441 tpc.set(e, null);
442 } else {
443 route(graph);
444 }
445 }
446
447 protected void routeEdgesToSelection(final Graph2D graph, Object affectedEdgesKey) {
448 final Set selectedEdges = new HashSet();
449 for (EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
450 final Edge edge = ec.edge();
451 if (graph.isSelected(edge.source()) ^ graph.isSelected(edge.target())) {
452 selectedEdges.add(edge);
453 continue;
454 }
455 for (BendCursor bc = graph.selectedBends(); bc.ok(); bc.next()) {
456 final Bend bend = (Bend) bc.current();
457 if (bend.getEdge() == edge) {
458 selectedEdges.add(edge);
459 break;
460 }
461 }
462 }
463 graph.addDataProvider(affectedEdgesKey, new DataProviderAdapter() {
464 public boolean getBool(Object dataHolder) {
465 return selectedEdges.contains(dataHolder);
466 }
467 });
468 route(graph);
469 graph.removeDataProvider(affectedEdgesKey);
470 }
471
472 protected void routeEdge(final Edge e, Graph2D graph, Object selectedEdgesKey) {
473 graph.addDataProvider(selectedEdgesKey, new DataProviderAdapter() {
474 public boolean getBool(Object o) {
475 return e == o;
476 }
477 });
478 routeEdge(e, graph);
479 graph.removeDataProvider(selectedEdgesKey);
480 }
481 }
482
483 static class OrthogonalEdgeRouterStrategy extends RouterStrategy {
484 private final MyOrthogonalEdgeRouterModule module;
485
486 OrthogonalEdgeRouterStrategy() {
487 module = new MyOrthogonalEdgeRouterModule();
488 }
489
490 public YModule getModule() {
491 return module;
492 }
493
494 public void routeEdge(final Edge e) {
495 final Graph2D graph = (Graph2D) e.getGraph();
496 module.setSphereOfAction(OrthogonalEdgeRouter.ROUTE_SELECTED_EDGES);
497 routeEdge(e, graph, Layouter.SELECTED_EDGES);
498 module.resetSphereOfAction();
499 }
500
501 public void rerouteAdjacentEdges(final DataProvider selectedNodes, final Graph2D graph) {
502 module.setSphereOfAction(OrthogonalEdgeRouter.ROUTE_EDGES_AT_SELECTED_NODES);
503 graph.addDataProvider(Layouter.SELECTED_NODES, selectedNodes);
504 this.route(graph);
505 graph.removeDataProvider(Layouter.SELECTED_NODES);
506 module.resetSphereOfAction();
507 }
508
509 public void routeEdgesToSelection(final Graph2D graph) {
510 module.setSphereOfAction(OrthogonalEdgeRouter.ROUTE_SELECTED_EDGES);
511 routeEdgesToSelection(graph, Layouter.SELECTED_EDGES);
512 module.resetSphereOfAction();
513 }
514
515 void route(final Graph2D graph) {
516 module.start(graph);
517 }
518 }
519
520
524 private static class MyOrthogonalEdgeRouterModule extends OrthogonalEdgeRouterModule {
525 private final byte UNDEFINED = -1;
526 private byte sphereOfAction = UNDEFINED;
527
528 protected void configure(final OrthogonalEdgeRouter orthogonal, final OptionHandler options) {
529 super.configure(orthogonal, options);
530
531 if (sphereOfAction != UNDEFINED) {
532 orthogonal.setSphereOfAction(sphereOfAction);
533 }
534 }
535
536 public void setSphereOfAction(final byte sphereOfAction) {
537 this.sphereOfAction = sphereOfAction;
538 }
539
540 public void resetSphereOfAction() {
541 sphereOfAction = UNDEFINED;
542 }
543 }
544
545 static class ChannelEdgeRouterStrategy extends RouterStrategy {
546 private final MyChannelEdgeRouterModule module;
547
548 public ChannelEdgeRouterStrategy() {
549 module = new MyChannelEdgeRouterModule();
550 }
551
552 public YModule getModule() {
553 return module;
554 }
555
556 public void routeEdge(final Edge e) {
557 final Graph2D graph = (Graph2D) e.getGraph();
558 routeEdge(e, graph, ChannelEdgeRouter.AFFECTED_EDGES);
559 }
560
561 public void rerouteAdjacentEdges(final DataProvider selectedNodes, final Graph2D graph) {
562 graph.addDataProvider(ChannelEdgeRouter.AFFECTED_EDGES, new DataProviderAdapter() {
563 public boolean getBool(Object dataHolder) {
564 return selectedNodes.getBool((((Edge) dataHolder).source())) || selectedNodes.getBool(
565 ((Edge) dataHolder).target());
566 }
567 });
568 this.route(graph);
569 graph.removeDataProvider(ChannelEdgeRouter.AFFECTED_EDGES);
570 }
571
572 public void routeEdgesToSelection(final Graph2D graph) {
573 routeEdgesToSelection(graph, ChannelEdgeRouter.AFFECTED_EDGES);
574 }
575
576 void route(final Graph2D graph) {
577 module.start(graph);
578 }
579 }
580
581
584 private static class MyChannelEdgeRouterModule extends ChannelEdgeRouterModule {
585 protected OptionHandler createOptionHandler() {
586 final OptionHandler options = super.createOptionHandler();
587 options.set(ITEM_PATHFINDER, VALUE_ORTHOGONAL_SHORTESTPATH_PATH_FINDER);
588 return options;
589 }
590 }
591
592 static class PolylineEdgeRouterStrategy extends RouterStrategy {
593 private final MyPolylineEdgeRouterModule module;
594
595 PolylineEdgeRouterStrategy() {
596 module = new MyPolylineEdgeRouterModule();
597 }
598
599 YModule getModule() {
600 return module;
601 }
602
603 void routeEdge(final Edge e) {
604 final Graph2D graph = (Graph2D) e.getGraph();
605 module.setSphereOfAction(EdgeRouter.ROUTE_SELECTED_EDGES);
606 routeEdge(e, graph, Layouter.SELECTED_EDGES);
607 module.resetSphereOfAction();
608 }
609
610 void rerouteAdjacentEdges(final DataProvider selectedNodes, final Graph2D graph) {
611 module.setSphereOfAction(EdgeRouter.ROUTE_SELECTED_EDGES);
612 graph.addDataProvider(Layouter.SELECTED_EDGES, new DataProviderAdapter() {
613 public boolean getBool(Object dataHolder) {
614 return selectedNodes.getBool(((Edge) dataHolder).source())
615 || selectedNodes.getBool(((Edge) dataHolder).target());
616 }
617 });
618 this.route(graph);
619 graph.removeDataProvider(Layouter.SELECTED_EDGES);
620 module.resetSphereOfAction();
621 }
622
623 void routeEdgesToSelection(final Graph2D graph) {
624 module.setSphereOfAction(EdgeRouter.ROUTE_SELECTED_EDGES);
625 routeEdgesToSelection(graph, Layouter.SELECTED_EDGES);
626 module.resetSphereOfAction();
627 }
628
629 void route(final Graph2D graph) {
630 module.start(graph);
631 }
632 }
633
634
638 private static class MyPolylineEdgeRouterModule extends PolylineEdgeRouterModule {
639 private final byte UNDEFINED = -1;
640 private byte sphereOfAction = UNDEFINED;
641
642 protected OptionHandler createOptionHandler() {
643 final OptionHandler options = super.createOptionHandler();
644 options.set(ITEM_ENABLE_POLYLINE_ROUTING, Boolean.TRUE);
645 return options;
646 }
647
648 protected void configure(final EdgeRouter router, final OptionHandler options) {
649 super.configure(router, options);
650
651 if (sphereOfAction != UNDEFINED) {
652 router.setSphereOfAction(sphereOfAction);
653 }
654 }
655
656 public void setSphereOfAction(final byte sphereOfAction) {
657 this.sphereOfAction = sphereOfAction;
658 }
659
660 public void resetSphereOfAction() {
661 sphereOfAction = UNDEFINED;
662 }
663 }
664 }
665