1
14 package demo.layout.router;
15
16 import demo.view.DemoBase;
17 import demo.view.DemoDefaults;
18
19 import y.base.DataProvider;
20 import y.base.Edge;
21 import y.base.EdgeMap;
22 import y.base.Node;
23 import y.base.NodeList;
24 import y.io.IOHandler;
25 import y.layout.LayoutGraph;
26 import y.layout.Layouter;
27 import y.layout.PortConstraintConfigurator;
28 import y.layout.PortConstraintKeys;
29 import y.layout.router.ChannelEdgeRouter;
30 import y.layout.router.OrthogonalEdgeRouter;
31 import y.module.ChannelEdgeRouterModule;
32 import y.module.OrthogonalEdgeRouterModule;
33 import y.module.YModule;
34 import y.util.DataProviderAdapter;
35 import y.view.CreateEdgeMode;
36 import y.view.DefaultGraph2DRenderer;
37 import y.view.Drawable;
38 import y.view.EditMode;
39 import y.view.Graph2D;
40 import y.view.HotSpotMode;
41 import y.view.MoveSelectionMode;
42 import y.view.Selections;
43 import y.view.Graph2DView;
44
45 import javax.swing.AbstractAction;
46 import javax.swing.JComboBox;
47 import javax.swing.JToolBar;
48 import java.awt.EventQueue;
49 import java.awt.Graphics2D;
50 import java.awt.Rectangle;
51 import java.awt.event.ActionEvent;
52 import java.awt.event.ActionListener;
53 import java.io.IOException;
54 import java.util.Locale;
55
56
82 public class MazeRouterDemo extends DemoBase {
83 private RouterStrategy strategy;
84 private Graph2D mazeG;
85 private Drawable mazeD;
86 private NodeList mazeNodes;
87 private OrthogonalEdgeRouterStrategy orthogonalEdgeRouterStrategy;
88 private ChannelEdgeRouterStrategy channelEdgeRouterStrategy;
89
90 public MazeRouterDemo() {
91 initializeMaze();
92
93 initializeGraph();
94 }
95
96 protected void initialize() {
97 channelEdgeRouterStrategy = new ChannelEdgeRouterStrategy();
98 orthogonalEdgeRouterStrategy = new OrthogonalEdgeRouterStrategy();
99 view.setContentPolicy(Graph2DView.CONTENT_POLICY_BACKGROUND_DRAWABLES);
100 }
101
102 protected void configureDefaultRealizers() {
103 super.configureDefaultRealizers();
104 view.getGraph2D().getDefaultNodeRealizer().setSize(30, 30);
105 }
106
107
110 protected JToolBar createToolBar() {
111 final JComboBox comboBox = new JComboBox(new Object[]{"Orthogonal Edge Router", "Channel Edge Router"});
112 comboBox.setMaximumSize(comboBox.getPreferredSize());
113 comboBox.addActionListener(new ActionListener() {
114 public void actionPerformed(ActionEvent e) {
115 strategy = comboBox.getSelectedIndex() == 0 ?
116 (RouterStrategy) orthogonalEdgeRouterStrategy :
117 channelEdgeRouterStrategy;
118 doLayout();
119 }
120 });
121 strategy = orthogonalEdgeRouterStrategy;
122
123 JToolBar toolBar = super.createToolBar();
124 toolBar.addSeparator();
125 toolBar.add(createActionControl(new LayoutAction()));
126 toolBar.addSeparator(TOOLBAR_SMALL_SEPARATOR);
127 toolBar.add(comboBox);
128 toolBar.addSeparator(TOOLBAR_SMALL_SEPARATOR);
129 toolBar.add(createActionControl(new OptionAction()));
130
131 return toolBar;
132 }
133
134
137 class OptionAction extends AbstractAction {
138 OptionAction() {
139 super("Settings...", getIconResource("resource/properties.png"));
140 }
141
142 public void actionPerformed(ActionEvent e) {
143 final ActionListener listener = new ActionListener() {
144 public void actionPerformed(ActionEvent e) {
145 doLayout();
146 }
147 };
148 OptionSupport.showDialog(strategy.getModule().getOptionHandler(), listener, false, view.getFrame());
149 }
150 }
151
152
155 class LayoutAction extends AbstractAction {
156 LayoutAction() {
157 super("Route Edges", SHARED_LAYOUT_ICON);
158 }
159
160 public void actionPerformed(ActionEvent e) {
161 doLayout();
162 }
163 }
164
165
168 class FitContent extends AbstractAction {
169 FitContent() {
170 super("Fit Content");
171 }
172
173 public void actionPerformed(ActionEvent e) {
174 Graph2D graph = view.getGraph2D();
175
176 Rectangle r = graph.getBoundingBox();
177 r.add(mazeD.getBounds());
178 view.fitRectangle(r);
179 graph.updateViews();
180 }
181 }
182
183 void doLayout() {
184 Graph2D graph = view.getGraph2D();
185 addMazeGraph();
186 strategy.getModule().start(graph);
188 subtractMazeGraph();
189 }
190
191
197 protected void registerViewModes() {
198 EditMode mode = new EditMode();
199 view.addViewMode(mode);
200
201 mode.setMoveSelectionMode(new MyMoveSelectionMode());
202 mode.setCreateEdgeMode(new MyCreateEdgeMode());
203 mode.setHotSpotMode(new MyHotSpotMode());
204 }
205
206
209 class MyCreateEdgeMode extends CreateEdgeMode {
210 private Node source;
211
212 protected boolean acceptSourceNode(Node s, double x, double y) {
213 source = s;
214 return true;
215 }
216
217 protected boolean acceptTargetNode(Node t, double x, double y) {
218 return (source != t);
219 }
220
221 protected void edgeCreated(final Edge e) {
222 routeNewEdge(e);
223 }
224 }
225
226 void routeNewEdge(Edge e) {
227 final Graph2D graph = view.getGraph2D();
228 addMazeGraph();
229 strategy.routeNewEdge(e);
230 subtractMazeGraph();
231 graph.updateViews();
232 }
233
234
237 class MyHotSpotMode extends HotSpotMode {
238 public void mouseReleasedLeft(double x, double y) {
239 super.mouseReleasedLeft(x, y);
240
241 final Graph2D graph = view.getGraph2D();
242
243 DataProvider selectedNodes = Selections.createSelectionDataProvider(graph);
244 addMazeGraph();
245 strategy.rerouteAdjacentEdges(selectedNodes, graph);
246 subtractMazeGraph();
247 graph.updateViews();
248 }
249 }
250
251
254 class MyMoveSelectionMode extends MoveSelectionMode {
255 private static final boolean ROUTE_EDGES_ON_MOVE = false;
256
257 protected void selectionOnMove(double dx, double dy, double x, double y) {
258 if (ROUTE_EDGES_ON_MOVE) {
259 routeEdgesToSelection();
260 }
261 }
262
263 protected void selectionMovedAction(double dx, double dy, double x, double y) {
264 routeEdgesToSelection();
265 }
266
267 void routeEdgesToSelection() {
268 final Graph2D graph = view.getGraph2D();
269
270 if (graph.selectedNodes().ok()) {
271 addMazeGraph();
272 strategy.routeEdgesToSelection(graph);
273 subtractMazeGraph();
274 graph.updateViews();
275 }
276 }
277 }
278
279
283 private void addMazeGraph() {
284 mazeNodes = new NodeList(mazeG.nodes());
285 mazeG.moveSubGraph(mazeNodes, view.getGraph2D());
286 }
287
288
291 private void subtractMazeGraph() {
292 view.getGraph2D().moveSubGraph(mazeNodes, mazeG);
293 }
294
295
298 private void initializeMaze() {
299 mazeG = new Graph2D();
300 try {
301 IOHandler ioHandler = createGraphMLIOHandler();
302 ioHandler.read(mazeG, getClass().getResource("resource/maze.graphml"));
303 DemoDefaults.applyFillColor(mazeG, DemoDefaults.DEFAULT_CONTRAST_COLOR);
304 DemoDefaults.applyLineColor(mazeG, DemoDefaults.DEFAULT_CONTRAST_COLOR);
305
306 } catch (IOException e) {
307 System.out.println("Could not initialize maze!");
308 e.printStackTrace();
309 System.exit(-1);
310 }
311 mazeD = new MazeDrawable(mazeG);
314 view.addBackgroundDrawable(mazeD);
315 view.fitRectangle(mazeD.getBounds());
316 }
317
318
321 private void initializeGraph() {
322 final Graph2D graph = view.getGraph2D();
323 Node start = graph.createNode();
324 graph.setLocation(start, 20,600);
325 Node end = graph.createNode();
326 graph.setLocation(end, 600,20);
327 Edge edge = graph.createEdge(start, end);
328 routeNewEdge(edge);
329 }
330
333 public static void main(String[] args) {
334 EventQueue.invokeLater(new Runnable() {
335 public void run() {
336 Locale.setDefault(Locale.ENGLISH);
337 initLnF();
338 (new MazeRouterDemo()).start();
339 }
340 });
341 }
342
343
346 static class MazeDrawable implements Drawable {
347 private Graph2D mazeG;
348 private DefaultGraph2DRenderer render;
349
350 public MazeDrawable(Graph2D g) {
351 mazeG = g;
352 render = new DefaultGraph2DRenderer();
353 }
354
355 public Rectangle getBounds() {
356 return mazeG.getBoundingBox();
357 }
358
359 public void paint(Graphics2D gfx) {
360 render.paint(gfx, mazeG);
361 }
362 }
363
364 abstract static class RouterStrategy {
365 abstract YModule getModule();
366
367 abstract void routeNewEdge(Edge e);
368
369 abstract void rerouteAdjacentEdges(DataProvider selectedNodes, LayoutGraph graph);
370
371 abstract void routeEdgesToSelection(Graph2D graph);
372
373 abstract void route(Layouter router, LayoutGraph graph);
374
375 protected void routeNewEdge(Layouter router, final Edge e, Graph2D graph) {
376 EdgeMap spc = (EdgeMap) graph.getDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY);
377 EdgeMap tpc = (EdgeMap) graph.getDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY);
378
379 PortConstraintConfigurator pcc = new PortConstraintConfigurator();
380 if (spc != null && tpc != null) {
381 spc.set(e, pcc.createPortConstraintFromSketch(graph, e, true, false));
382 tpc.set(e, pcc.createPortConstraintFromSketch(graph, e, false, false));
383 route(router, graph);
384 spc.set(e, null);
385 tpc.set(e, null);
386 } else {
387 route(router, graph);
388 }
389 }
390
391 protected void routeEdgesToSelection(final Graph2D graph, Layouter router, Object affectedEdgesKey) {
392 graph.addDataProvider(affectedEdgesKey, new DataProviderAdapter() {
393 public boolean getBool(Object dataHolder) {
394 return graph.isSelected(((Edge) dataHolder).source()) || graph.isSelected(((Edge) dataHolder).target());
395 }
396 });
397 route(router, graph);
398 graph.removeDataProvider(affectedEdgesKey);
399 }
400
401 protected void routeNewEdge(final Edge e, Graph2D graph, Layouter router, Object selectedEdgesKey) {
402 DataProvider activeEdges = new DataProviderAdapter() {
403 public boolean getBool(Object o) {
404 return e == o;
405 }
406 };
407 graph.addDataProvider(selectedEdgesKey, activeEdges);
408 routeNewEdge(router, e, graph);
409 graph.removeDataProvider(selectedEdgesKey);
410 }
411 }
412
413 static class OrthogonalEdgeRouterStrategy extends RouterStrategy {
414 private OrthogonalEdgeRouterModule module = new OrthogonalEdgeRouterModule();
415
416 public YModule getModule() {
417 return module;
418 }
419
420 public void routeNewEdge(final Edge e) {
421 Graph2D graph = (Graph2D) e.getGraph();
422 OrthogonalEdgeRouter router = new OrthogonalEdgeRouter();
423 module.configure(router);
424 router.setSphereOfAction(OrthogonalEdgeRouter.ROUTE_SELECTED_EDGES);
425 routeNewEdge(e, graph, router, Layouter.SELECTED_EDGES);
426 }
427
428 public void rerouteAdjacentEdges(DataProvider selectedNodes, LayoutGraph graph) {
429 OrthogonalEdgeRouter router = new OrthogonalEdgeRouter();
430 module.configure(router);
431 router.setSphereOfAction(OrthogonalEdgeRouter.ROUTE_EDGES_AT_SELECTED_NODES);
432 graph.addDataProvider(Layouter.SELECTED_NODES, selectedNodes);
433 this.route(router, graph);
434 graph.removeDataProvider(Layouter.SELECTED_NODES);
435 }
436
437 public void routeEdgesToSelection(final Graph2D graph) {
438 OrthogonalEdgeRouter router = new OrthogonalEdgeRouter();
439 module.configure(router);
440 router.setSphereOfAction(OrthogonalEdgeRouter.ROUTE_SELECTED_EDGES);
441 routeEdgesToSelection(graph, router, Layouter.SELECTED_EDGES);
442 }
443
444 void route(Layouter router, LayoutGraph graph) {
445 router.doLayout(graph);
446 }
447 }
448
449 static class ChannelEdgeRouterStrategy extends RouterStrategy {
450 private ChannelEdgeRouterModule module;
451
452 public ChannelEdgeRouterStrategy() {
453 module = new ChannelEdgeRouterModule();
454 module.getOptionHandler().set("PATHFINDER", "ORTHOGONAL_SHORTESTPATH_PATH_FINDER");
455 }
456
457 public YModule getModule() {
458 return module;
459 }
460
461 public void routeNewEdge(final Edge e) {
462 final Graph2D graph = (Graph2D) e.getGraph();
463 ChannelEdgeRouter router = new ChannelEdgeRouter();
464 module.configure(router);
465 routeNewEdge(e, graph, router, ChannelEdgeRouter.AFFECTED_EDGES);
466 }
467
468 public void rerouteAdjacentEdges(final DataProvider selectedNodes, LayoutGraph graph) {
469 ChannelEdgeRouter router = new ChannelEdgeRouter();
470 module.configure(router);
471 graph.addDataProvider(ChannelEdgeRouter.AFFECTED_EDGES, new DataProviderAdapter() {
472 public boolean getBool(Object dataHolder) {
473 return selectedNodes.getBool((((Edge) dataHolder).source())) || selectedNodes.getBool(
474 ((Edge) dataHolder).target());
475 }
476 });
477 this.route(router, graph);
478 graph.removeDataProvider(ChannelEdgeRouter.AFFECTED_EDGES);
479 }
480
481 public void routeEdgesToSelection(final Graph2D graph) {
482 ChannelEdgeRouter router = new ChannelEdgeRouter();
483 module.configure(router);
484 routeEdgesToSelection(graph, router, ChannelEdgeRouter.AFFECTED_EDGES);
485 }
486
487 void route(Layouter router, LayoutGraph graph) {
488 router.doLayout(graph);
489 }
490 }
491 }
492