1
28 package demo.layout.module;
29
30 import y.module.LayoutModule;
31 import y.module.YModule;
32
33 import y.layout.ComponentLayouter;
34 import y.layout.Layouter;
35 import y.layout.PartitionLayouter;
36 import y.layout.PartitionLayouter.ComponentPartitionPlacer;
37 import y.layout.grouping.GroupNodeHider;
38 import y.layout.orthogonal.CompactOrthogonalLayouter;
39 import y.layout.orthogonal.OrthogonalLayouter;
40 import y.layout.router.ChannelEdgeRouter;
41 import y.layout.router.OrthogonalPatternEdgeRouter;
42 import y.layout.router.polyline.EdgeLayoutDescriptor;
43 import y.layout.router.polyline.EdgeRouter;
44 import y.layout.router.polyline.PenaltySettings;
45 import y.option.ConstraintManager;
46 import y.option.IntOptionItem;
47 import y.option.OptionGroup;
48 import y.option.OptionHandler;
49 import y.option.OptionItem;
50 import y.view.Graph2DView;
51
52 import java.awt.Dimension;
53
54
61 public class CompactOrthogonalLayoutModule extends LayoutModule {
62 protected static final String MODULE_COMPACT_ORTHOGONAL = "COMPACT_ORTHOGONAL";
64
65 protected static final String ITEM_ORTHOGONAL_LAYOUT_STYLE = "ORTHOGONAL_LAYOUT_STYLE";
67 protected static final String VALUE_NORMAL = "NORMAL";
68 protected static final String VALUE_NORMAL_TREE = "NORMAL_TREE";
69 protected static final String VALUE_FIXED_MIXED = "FIXED_MIXED";
70 protected static final String VALUE_FIXED_BOX_NODES = "FIXED_BOX_NODES";
71 protected static final String ITEM_PLACEMENT_STRATEGY = "PLACEMENT_STRATEGY";
72 protected static final String VALUE_STYLE_ROWS = "STYLE_ROWS";
73 protected static final String VALUE_STYLE_PACKED_COMPACT_RECTANGLE = "STYLE_PACKED_COMPACT_RECTANGLE";
74 protected static final String ITEM_USE_VIEW_ASPECT_RATIO = "USE_VIEW_ASPECT_RATIO";
75 protected static final String ITEM_ASPECT_RATIO = "ASPECT_RATIO";
76 protected static final String ITEM_GRID = "GRID";
77 protected static final String TITLE_INTER_EDGE_ROUTER = "INTER_EDGE_ROUTER";
78 protected static final String ITEM_EDGE_ROUTER = "EDGE_ROUTER";
79 protected static final String VALUE_EDGE_ROUTER_CHANNEL_FAST = "EDGE_ROUTER_CHANNEL_FAST";
80 protected static final String VALUE_EDGE_ROUTER_CHANNEL_HQ = "EDGE_ROUTER_CHANNEL_HQ";
81 protected static final String VALUE_EDGE_ROUTER_ORTHOGONAL = "EDGE_ROUTER_ORTHOGONAL";
83 protected static final String ITEM_ROUTE_ALL_EDGES = "ROUTE_ALL_EDGES";
84 protected static final String ITEM_BEND_COST = "BEND_COST";
85 protected static final String ITEM_NODE_CROSSING_COST = "NODE_CROSSING_COST";
86 protected static final String ITEM_MINIMUM_DISTANCE = "MINIMUM_DISTANCE";
87 protected static final String ITEM_EDGE_CROSSING_COST = "EDGE_CROSSING_COST";
88 protected static final String ITEM_CENTER_TO_SPACE_RATIO = "SPACE_DRIVEN_VS_CENTER_DRIVEN_SEARCH";
89
90
93 public CompactOrthogonalLayoutModule() {
94 super(MODULE_COMPACT_ORTHOGONAL);
95 setPortIntersectionCalculatorEnabled(true);
96 }
97
98
102 protected OptionHandler createOptionHandler() {
103 final OptionHandler options = new OptionHandler(getModuleName());
104 final ConstraintManager optionConstraints = new ConstraintManager(options);
105 final CompactOrthogonalLayouter defaults = new CompactOrthogonalLayouter();
107 if (false) {
108 defaults.setInterEdgeRouter(new PartitionLayouter.PolylineInterEdgeRouter());
109 } else {
110 defaults.setInterEdgeRouter(new PartitionLayouter.ChannelInterEdgeRouter());
111 }
112 defaults.setPartitionPlacer(new ComponentPartitionPlacer());
113 defaults.setCoreLayouter(new OrthogonalLayouter());
114 final OrthogonalPatternEdgeRouter defaultsOper = new OrthogonalPatternEdgeRouter();
115 final ChannelEdgeRouter.OrthogonalShortestPathPathFinder defaultsPsppf =
116 new ChannelEdgeRouter.OrthogonalShortestPathPathFinder();
117
118 final int styleIndex;
120 switch (((OrthogonalLayouter) defaults.getCoreLayouter()).getLayoutStyle()) {
121 case OrthogonalLayouter.NORMAL_STYLE:
122 default:
123 styleIndex = 0;
124 break;
125 case OrthogonalLayouter.NORMAL_TREE_STYLE:
126 styleIndex = 1;
127 break;
128 case OrthogonalLayouter.FIXED_MIXED_STYLE:
129 styleIndex = 2;
130 break;
131 case OrthogonalLayouter.FIXED_BOX_STYLE:
132 styleIndex = 3;
133 break;
134 }
135 options.addEnum(ITEM_ORTHOGONAL_LAYOUT_STYLE, new String[]{
136 VALUE_NORMAL,
137 VALUE_NORMAL_TREE,
138 VALUE_FIXED_MIXED,
139 VALUE_FIXED_BOX_NODES
140 }, styleIndex);
141
142 int compStyleIndex;
143 switch (((ComponentPartitionPlacer) defaults.getPartitionPlacer()).getComponentLayouter().getStyle()) {
144 case ComponentLayouter.STYLE_ROWS:
145 default:
146 compStyleIndex = 0;
147 break;
148 case ComponentLayouter.STYLE_PACKED_COMPACT_RECTANGLE:
149 compStyleIndex = 1;
150 break;
151 }
152 options.addEnum(ITEM_PLACEMENT_STRATEGY, new String[]{
153 VALUE_STYLE_ROWS,
154 VALUE_STYLE_PACKED_COMPACT_RECTANGLE
155 }, compStyleIndex);
156
157 final OptionItem itemUseViewAspectRation = options.addBool(ITEM_USE_VIEW_ASPECT_RATIO, true);
158 final OptionItem itemAspectRatio = options.addDouble(ITEM_ASPECT_RATIO, defaults.getAspectRatio());
159 options.addInt(ITEM_GRID, defaults.getGridSpacing()).setAttribute(IntOptionItem.ATTRIBUTE_MIN_VALUE, new Integer(1));
160 optionConstraints.setEnabledOnValueEquals(itemUseViewAspectRation, Boolean.FALSE, itemAspectRatio);
162
163 final OptionGroup interEdgeGroup = new OptionGroup();
165 interEdgeGroup.setAttribute(OptionGroup.ATTRIBUTE_TITLE, TITLE_INTER_EDGE_ROUTER);
166 final OptionItem itemEdgeRouter = interEdgeGroup.addItem(
168 options.addEnum(ITEM_EDGE_ROUTER, new String[]{
169 VALUE_EDGE_ROUTER_CHANNEL_FAST,
170 VALUE_EDGE_ROUTER_CHANNEL_HQ,
171 VALUE_EDGE_ROUTER_ORTHOGONAL
172 }, 1));
173 interEdgeGroup.addItem(options.addBool(ITEM_ROUTE_ALL_EDGES,
174 !((PartitionLayouter.ChannelInterEdgeRouter) defaults.getInterEdgeRouter()).isRouteInterEdgesOnly()));
175
176 final OptionItem itemBendCost = interEdgeGroup.addItem(
178 options.addDouble(ITEM_BEND_COST, defaultsOper.getBendCost()));
179 final OptionItem itemNodeCrossingCost = interEdgeGroup.addItem(
180 options.addDouble(ITEM_NODE_CROSSING_COST, defaultsOper.getNodeCrossingCost()));
181 final OptionItem itemMinimumDistance =interEdgeGroup.addItem(
182 options.addInt(ITEM_MINIMUM_DISTANCE, defaultsPsppf.getMinimumDistance()));
183 itemMinimumDistance.setAttribute(IntOptionItem.ATTRIBUTE_MIN_VALUE, new Integer(4));
184 interEdgeGroup.addItem(options.addDouble(ITEM_EDGE_CROSSING_COST, defaultsPsppf.getCrossingCost()));
185 final OptionItem itemCenterSpaceRatio = interEdgeGroup.addItem(
186 options.addDouble(ITEM_CENTER_TO_SPACE_RATIO, defaultsPsppf.getCenterToSpaceRatio(), 0, 1));
187
188 optionConstraints.setEnabledOnCondition(
190 optionConstraints.createConditionValueEquals(itemEdgeRouter, VALUE_EDGE_ROUTER_CHANNEL_FAST).or(
191 optionConstraints.createConditionValueEquals(itemEdgeRouter, VALUE_EDGE_ROUTER_ORTHOGONAL)
192 ), itemBendCost);
193 optionConstraints.setEnabledOnValueEquals(itemEdgeRouter, VALUE_EDGE_ROUTER_CHANNEL_FAST, itemNodeCrossingCost);
194 optionConstraints.setEnabledOnValueEquals(itemEdgeRouter, VALUE_EDGE_ROUTER_CHANNEL_HQ, itemCenterSpaceRatio);
195
196 return options;
197 }
198
199
200
204 protected void mainrun() {
205 final CompactOrthogonalLayouter orthogonal = new CompactOrthogonalLayouter();
206
207 final OptionHandler options = getOptionHandler();
208 configure(orthogonal, options);
209
210 final GroupNodeHider gnh = new GroupNodeHider(orthogonal);
212 gnh.setHidingEmptyGroupNodes(false);
213 launchLayouter(gnh);
214 }
215
216
217
218
227 protected void configure(final CompactOrthogonalLayouter orthogonal, final OptionHandler options) {
228 final boolean useOrthogonalEdgeRouter = VALUE_EDGE_ROUTER_ORTHOGONAL.equals(options.get(ITEM_EDGE_ROUTER));
229 final PartitionLayouter.InterEdgeRouter ier;
230 if (useOrthogonalEdgeRouter) {
231 ier = new PartitionLayouter.PolylineInterEdgeRouter();
232 orthogonal.setInterEdgeRouter(ier);
233 } else {
234 ier = new PartitionLayouter.ChannelInterEdgeRouter();
235 orthogonal.setInterEdgeRouter(ier);
236 }
237 configure(ier, options);
238
239 final ComponentPartitionPlacer pp = new ComponentPartitionPlacer();
240 orthogonal.setPartitionPlacer(pp);
241 configure(pp, options);
242
243 final OrthogonalLayouter cl = new OrthogonalLayouter();
244 orthogonal.setCoreLayouter(cl);
245 configure(cl, options);
246
247 orthogonal.setGridSpacing(options.getInt(ITEM_GRID));
248
249 final double ar;
250 final Graph2DView view = getGraph2DView();
251 if (options.getBool(ITEM_USE_VIEW_ASPECT_RATIO) && view != null) {
252 final Dimension dim = view.getSize();
253 ar = dim.getWidth()/dim.getHeight();
254 } else {
255 ar = options.getDouble(ITEM_ASPECT_RATIO);
256 }
257 orthogonal.setAspectRatio(ar);
260 }
261
262 private void configure(final PartitionLayouter.InterEdgeRouter router, final OptionHandler options) {
263 if (router instanceof PartitionLayouter.PolylineInterEdgeRouter) {
264 final PartitionLayouter.PolylineInterEdgeRouter ier = (PartitionLayouter.PolylineInterEdgeRouter) router;
265 ier.setRouteInterEdgesOnly(!options.getBool(ITEM_ROUTE_ALL_EDGES));
266
267 final EdgeRouter er = ier.getEdgeRouter();
268 er.setMinimalNodeToEdgeDistance(options.getInt(ITEM_MINIMUM_DISTANCE));
269 final EdgeLayoutDescriptor eld = er.getDefaultEdgeLayoutDescriptor();
270 eld.setMinimalEdgeToEdgeDistance(options.getInt(ITEM_MINIMUM_DISTANCE));
271
272 final PenaltySettings ps = eld.getPenaltySettings();
273 ps.setEdgeCrossingPenalty((int) Math.ceil(options.getDouble(ITEM_EDGE_CROSSING_COST)));
274 ps.setBendPenalty((int) Math.ceil(options.getDouble(ITEM_BEND_COST)));
275 } else if (router instanceof PartitionLayouter.ChannelInterEdgeRouter) {
276 final PartitionLayouter.ChannelInterEdgeRouter ier = (PartitionLayouter.ChannelInterEdgeRouter) router;
277 ier.setRouteInterEdgesOnly(!options.getBool(ITEM_ROUTE_ALL_EDGES));
278
279 if (VALUE_EDGE_ROUTER_CHANNEL_FAST.equals(options.getString(ITEM_EDGE_ROUTER))) {
280 final OrthogonalPatternEdgeRouter oper = new OrthogonalPatternEdgeRouter();
281 oper.setMinimumDistance(options.getInt(ITEM_MINIMUM_DISTANCE));
282 oper.setEdgeCrossingCost(options.getDouble(ITEM_EDGE_CROSSING_COST));
283 oper.setNodeCrossingCost(options.getDouble(ITEM_NODE_CROSSING_COST));
284 oper.setBendCost(options.getDouble(ITEM_BEND_COST));
285 ier.getChannelEdgeRouter().setPathFinderStrategy(oper);
286 } else {
287 final ChannelEdgeRouter.OrthogonalShortestPathPathFinder osppf = new ChannelEdgeRouter.OrthogonalShortestPathPathFinder();
288 osppf.setMinimumDistance(options.getInt(ITEM_MINIMUM_DISTANCE));
289 osppf.setCrossingCost(options.getDouble(ITEM_EDGE_CROSSING_COST));
290 osppf.setCenterToSpaceRatio(options.getDouble(ITEM_CENTER_TO_SPACE_RATIO));
291 ier.getChannelEdgeRouter().setPathFinderStrategy(osppf);
292 }
293 }
294 }
295
296 private void configure(final PartitionLayouter.ComponentPartitionPlacer placer, final OptionHandler options) {
297 if (VALUE_STYLE_PACKED_COMPACT_RECTANGLE.equals(options.get(ITEM_PLACEMENT_STRATEGY))) {
298 placer.getComponentLayouter().setStyle(ComponentLayouter.STYLE_PACKED_COMPACT_RECTANGLE);
299 } else if (VALUE_STYLE_ROWS.equals(options.get(ITEM_PLACEMENT_STRATEGY))) {
300 placer.getComponentLayouter().setStyle(ComponentLayouter.STYLE_MULTI_ROWS);
301 }
302 }
303
304 private void configure(final OrthogonalLayouter orthogonal, final OptionHandler options) {
305 final String ols = options.getString(ITEM_ORTHOGONAL_LAYOUT_STYLE);
306 if (VALUE_NORMAL_TREE.equals(ols)) {
307 orthogonal.setLayoutStyle(OrthogonalLayouter.NORMAL_TREE_STYLE);
308 } else if (VALUE_FIXED_MIXED.equals(ols)) {
309 orthogonal.setLayoutStyle(OrthogonalLayouter.FIXED_MIXED_STYLE);
310 } else if (VALUE_FIXED_BOX_NODES.equals(ols)) {
311 orthogonal.setLayoutStyle(OrthogonalLayouter.FIXED_BOX_STYLE);
312 } else {
313 orthogonal.setLayoutStyle(OrthogonalLayouter.NORMAL_STYLE);
315 }
316 }
317
318 }
319