1
28 package demo.layout.module;
29
30 import y.module.LayoutModule;
31 import y.module.YModule;
32
33 import y.base.Edge;
34 import y.layout.Layouter;
35 import y.layout.router.ChannelEdgeRouter;
36 import y.layout.router.ChannelEdgeRouter.OrthogonalShortestPathPathFinder;
37 import y.layout.router.OrthogonalPatternEdgeRouter;
38 import y.layout.router.OrthogonalSegmentDistributionStage;
39 import y.option.ConstraintManager;
40 import y.option.DoubleOptionItem;
41 import y.option.OptionGroup;
42 import y.option.OptionHandler;
43 import y.option.OptionItem;
44 import y.util.DataProviderAdapter;
45 import y.view.Graph2D;
46
47
54 public class ChannelEdgeRouterModule extends LayoutModule {
55 protected static final String MODULE_CHANNEL_EDGE_ROUTER = "CHANNEL_EDGE_ROUTER";
57
58 protected static final String TITLE_LAYOUT_OPTIONS = "LAYOUT_OPTIONS";
60 protected static final String ITEM_PATHFINDER = "PATHFINDER";
61 protected static final String VALUE_ORTHOGONAL_PATTERN_PATH_FINDER = "ORTHOGONAL_PATTERN_PATH_FINDER";
62 protected static final String VALUE_ORTHOGONAL_SHORTESTPATH_PATH_FINDER = "ORTHOGONAL_SHORTESTPATH_PATH_FINDER";
63 protected static final String ITEM_SCOPE = "SCOPE";
64 protected static final String VALUE_SCOPE_ALL_EDGES = "SCOPE_ALL_EDGES";
65 protected static final String VALUE_SCOPE_SELECTED_EDGES = "SCOPE_SELECTED_EDGES";
66 protected static final String VALUE_SCOPE_AT_SELECTED_NODES = "SCOPE_AT_SELECTED_NODES";
67 protected static final String ITEM_MINIMUM_DISTANCE = "MINIMUM_DISTANCE";
68 protected static final String ITEM_ACTIVATE_GRID_ROUTING = "ACTIVATE_GRID_ROUTING";
69 protected static final String ITEM_GRID_SPACING = "GRID_SPACING";
70 protected static final String TITLE_COST = "COST";
71 protected static final String ITEM_BEND_COST = "BEND_COST_FACTOR";
72 protected static final String ITEM_EDGE_CROSSING_COST = "EDGE_CROSSING_COST";
73 protected static final String ITEM_NODE_CROSSING_COST = "NODE_CROSSING_COST";
74 private boolean isEdgeDPAddedByModule;
75
76
79 public ChannelEdgeRouterModule() {
80 super(MODULE_CHANNEL_EDGE_ROUTER);
81 setPortIntersectionCalculatorEnabled(true);
82 }
83
84
88 protected OptionHandler createOptionHandler() {
89 final OptionHandler options = new OptionHandler(getModuleName());
90 final ConstraintManager optionConstraints = new ConstraintManager(options);
91 final ChannelEdgeRouter defaults = new ChannelEdgeRouter();
93 final double minimumDistance, gridSpacing, bendCost, edgeCrossingCost, nodeCrossingCost;
95 final boolean isGridRoutingEnabled;
96 if (defaults.getPathFinderStrategy() instanceof OrthogonalPatternEdgeRouter) {
97 final OrthogonalPatternEdgeRouter defaultsOper = (OrthogonalPatternEdgeRouter) defaults.getPathFinderStrategy();
99 minimumDistance = defaultsOper.getMinimumDistance();
101 isGridRoutingEnabled = defaultsOper.isGridRoutingEnabled();
102 gridSpacing = defaultsOper.getGridWidth();
103 bendCost = defaultsOper.getBendCost();
104 edgeCrossingCost = defaultsOper.getEdgeCrossingCost();
105 nodeCrossingCost = defaultsOper.getNodeCrossingCost();
106 } else if (defaults.getPathFinderStrategy() instanceof ChannelEdgeRouter.OrthogonalShortestPathPathFinder) {
107 final ChannelEdgeRouter.OrthogonalShortestPathPathFinder defaultsOsppf =
109 (ChannelEdgeRouter.OrthogonalShortestPathPathFinder) defaults.getPathFinderStrategy();
110 minimumDistance = defaultsOsppf.getMinimumDistance();
112 isGridRoutingEnabled = defaultsOsppf.isGridRoutingEnabled();
113 gridSpacing = defaultsOsppf.getGridSpacing();
114 bendCost = 1;
115 edgeCrossingCost = 5;
116 nodeCrossingCost = 50;
117 } else {
118 minimumDistance = 10;
120 isGridRoutingEnabled = true;
121 gridSpacing = 20;
122 bendCost = 1;
123 edgeCrossingCost = 5;
124 nodeCrossingCost = 20;
125 }
126
127 final boolean isOrthogonalShortestPath =
128 defaults.getPathFinderStrategy() instanceof ChannelEdgeRouter.OrthogonalShortestPathPathFinder;
129
130 final OptionGroup layoutGroup = new OptionGroup();
132 layoutGroup.setAttribute(OptionGroup.ATTRIBUTE_TITLE, TITLE_LAYOUT_OPTIONS);
133 final OptionItem itemPathfinder = layoutGroup.addItem(
135 options.addEnum(ITEM_PATHFINDER, new String[]{
136 VALUE_ORTHOGONAL_PATTERN_PATH_FINDER,
137 VALUE_ORTHOGONAL_SHORTESTPATH_PATH_FINDER
138 }, isOrthogonalShortestPath ? 1 : 0));
139 layoutGroup.addItem(
140 options.addEnum(ITEM_SCOPE, new String[]{
141 VALUE_SCOPE_ALL_EDGES,
142 VALUE_SCOPE_SELECTED_EDGES,
143 VALUE_SCOPE_AT_SELECTED_NODES
144 }, 0));
145 final OptionItem itemMinimumDistance = layoutGroup.addItem(
146 options.addDouble(ITEM_MINIMUM_DISTANCE, minimumDistance));
147 if (isOrthogonalShortestPath) {
148 itemMinimumDistance.setAttribute(DoubleOptionItem.ATTRIBUTE_MIN_VALUE, new Double(4.0));
149 }
150 final OptionItem itemActivateGridRouting = layoutGroup.addItem(
151 options.addBool(ITEM_ACTIVATE_GRID_ROUTING, isGridRoutingEnabled));
152 final OptionItem itemGridSpacing =layoutGroup.addItem(
153 options.addDouble(ITEM_GRID_SPACING, gridSpacing));
154 itemGridSpacing.setAttribute(DoubleOptionItem.ATTRIBUTE_MIN_VALUE, new Double(2.0));
155 optionConstraints.setEnabledOnValueEquals(itemActivateGridRouting, Boolean.TRUE, itemGridSpacing);
157
158 final OptionGroup costGroup = new OptionGroup();
160 costGroup.setAttribute(OptionGroup.ATTRIBUTE_TITLE, TITLE_COST);
161 final OptionItem itemBendCost = costGroup.addItem(options.addDouble(ITEM_BEND_COST, bendCost));
163 final OptionItem itemEdgeCrossingCost = costGroup.addItem(
164 options.addDouble(ITEM_EDGE_CROSSING_COST, edgeCrossingCost));
165 final OptionItem itemNodeCrossingCost = costGroup.addItem(
166 options.addDouble(ITEM_NODE_CROSSING_COST, nodeCrossingCost));
167 optionConstraints.setEnabledOnValueEquals(itemPathfinder, VALUE_ORTHOGONAL_PATTERN_PATH_FINDER, itemBendCost);
169 optionConstraints.setEnabledOnValueEquals(itemPathfinder, VALUE_ORTHOGONAL_PATTERN_PATH_FINDER, itemEdgeCrossingCost);
170 optionConstraints.setEnabledOnValueEquals(itemPathfinder, VALUE_ORTHOGONAL_PATTERN_PATH_FINDER, itemNodeCrossingCost);
171 return options;
172 }
173
174
178 protected void mainrun() {
179 final ChannelEdgeRouter channel = new ChannelEdgeRouter();
180
181 final OptionHandler options = getOptionHandler();
182 configure(channel, options);
183
184 final Graph2D graph = getGraph2D();
185 prepareGraph(graph, options);
186 try {
187 launchLayouter(channel);
188 } finally {
189 restoreGraph(graph, options);
190 }
191 }
192
193
203 protected void prepareGraph(final Graph2D graph, OptionHandler options) {
204 isEdgeDPAddedByModule = graph.getDataProvider(ChannelEdgeRouter.AFFECTED_EDGES) == null;
205 if (isEdgeDPAddedByModule) {
206 if (options.get(ITEM_SCOPE).equals(VALUE_SCOPE_ALL_EDGES)) {
208 graph.addDataProvider(ChannelEdgeRouter.AFFECTED_EDGES, new DataProviderAdapter() {
209 public boolean getBool(Object dataHolder) {
210 return true;
211 }
212 });
213 } else if (options.get(ITEM_SCOPE).equals(VALUE_SCOPE_SELECTED_EDGES)) {
214 graph.addDataProvider(ChannelEdgeRouter.AFFECTED_EDGES, new DataProviderAdapter() {
215 public boolean getBool(Object dataHolder) {
216 return graph.isSelected((Edge) dataHolder);
217 }
218 });
219 } else {
220 graph.addDataProvider(ChannelEdgeRouter.AFFECTED_EDGES, new DataProviderAdapter() {
221 public boolean getBool(Object dataHolder) {
222 return graph.isSelected(((Edge) dataHolder).source()) || graph.isSelected(((Edge) dataHolder).target());
223 }
224 });
225 }
226 }
227 }
228
229
230
236 protected void restoreGraph(final Graph2D graph, final OptionHandler options) {
237 if (isEdgeDPAddedByModule) {
238 isEdgeDPAddedByModule = false;
239 graph.removeDataProvider(ChannelEdgeRouter.AFFECTED_EDGES);
240 }
241 }
242
243
248 protected void configure(final ChannelEdgeRouter channel, final OptionHandler options) {
249 final Layouter pathFinder;
250 if (options.get(ITEM_PATHFINDER).equals(VALUE_ORTHOGONAL_PATTERN_PATH_FINDER)) {
251 final OrthogonalPatternEdgeRouter oper = new OrthogonalPatternEdgeRouter();
252 configure(oper, options);
253 pathFinder = oper;
254 } else {
255 final OrthogonalShortestPathPathFinder ospf = new OrthogonalShortestPathPathFinder();
256 configure(ospf, options);
257 pathFinder = ospf;
258 }
259 channel.setPathFinderStrategy(pathFinder);
260
261 OrthogonalSegmentDistributionStage segmentDistributionStage = new OrthogonalSegmentDistributionStage();
262 segmentDistributionStage.setAffectedEdgesDPKey(ChannelEdgeRouter.AFFECTED_EDGES);
263 segmentDistributionStage.setPreferredDistance(options.getDouble(ITEM_MINIMUM_DISTANCE));
264 segmentDistributionStage.setGridEnabled(options.getBool(ITEM_ACTIVATE_GRID_ROUTING));
265 segmentDistributionStage.setGridWidth(options.getDouble(ITEM_GRID_SPACING));
266
267 channel.setEdgeDistributionStrategy(segmentDistributionStage);
268 }
269
270 private void configure(final OrthogonalShortestPathPathFinder ospf, final OptionHandler options) {
271 ospf.setSelectedEdgesDpKey(ChannelEdgeRouter.AFFECTED_EDGES);
272 ospf.setMinimumDistance((int) options.getDouble(ITEM_MINIMUM_DISTANCE));
273
274 ospf.setGridRoutingEnabled(options.getBool(ITEM_ACTIVATE_GRID_ROUTING));
275 ospf.setGridSpacing((int) options.getDouble(ITEM_GRID_SPACING));
276
277 ospf.setCrossingCost(options.getDouble(ITEM_EDGE_CROSSING_COST));
278 }
279
280 private void configure(final OrthogonalPatternEdgeRouter oper, OptionHandler options) {
281 oper.setAffectedEdgesDPKey(ChannelEdgeRouter.AFFECTED_EDGES);
282 oper.setMinimumDistance(options.getDouble(ITEM_MINIMUM_DISTANCE));
283
284 oper.setGridRoutingEnabled(options.getBool(ITEM_ACTIVATE_GRID_ROUTING));
285 oper.setGridWidth(options.getDouble(ITEM_GRID_SPACING));
286
287 oper.setBendCost(options.getDouble(ITEM_BEND_COST));
288 oper.setEdgeCrossingCost(options.getDouble(ITEM_EDGE_CROSSING_COST));
289 oper.setNodeCrossingCost(options.getDouble(ITEM_NODE_CROSSING_COST));
290
291 oper.setEdgeOverlapCost(0.0);
293 }
294 }
295