1
14 package demo.layout.module;
15
16 import y.module.LayoutModule;
17 import y.module.YModule;
18
19 import y.layout.ComponentLayouter;
20 import y.layout.Layouter;
21 import y.layout.PartitionLayouter;
22 import y.layout.grouping.GroupNodeHider;
23 import y.layout.orthogonal.CompactOrthogonalLayouter;
24 import y.layout.orthogonal.OrthogonalLayouter;
25 import y.layout.router.ChannelEdgeRouter;
26 import y.layout.router.OrthogonalPatternEdgeRouter;
27 import y.option.ConstraintManager;
28 import y.option.IntOptionItem;
29 import y.option.OptionGroup;
30 import y.option.OptionHandler;
31
32 import java.awt.Dimension;
33
34
41 public class CompactOrthogonalLayoutModule extends LayoutModule {
42 private static final String NAME = "COMPACT_ORTHOGONAL";
43
44 private static final String ORTHOGONAL_LAYOUT_STYLE = "ORTHOGONAL_LAYOUT_STYLE";
45 private static final String GRID = "GRID";
46
47 private static final String NORMAL = "NORMAL";
48 private static final String NORMAL_TREE = "NORMAL_TREE";
49 private static final String FIXED_MIXED = "FIXED_MIXED";
50 private static final String FIXED_BOX_NODES = "FIXED_BOX_NODES";
51
52 private static final String ASPECT_RATIO = "ASPECT_RATIO";
53 private static final String USE_VIEW_ASPECT_RATIO = "USE_VIEW_ASPECT_RATIO";
54
55 private static final String PLACEMENT_STRATEGY = "PLACEMENT_STRATEGY";
56 private static final String STYLE_ROWS = "STYLE_ROWS";
57 private static final String STYLE_PACKED_COMPACT_RECTANGLE = "STYLE_PACKED_COMPACT_RECTANGLE";
58
59 private static final String PATH_FINDER = "PATH_FINDER";
61 private static final String ORTHOGONAL_PATTERN_PATH_FINDER = "ORTHOGONAL_PATTERN_PATH_FINDER";
62 private static final String ORTHOGONAL_SHORTESTPATH_PATH_FINDER = "ORTHOGONAL_SHORTESTPATH_PATH_FINDER";
63 private static final String INTER_EDGE_ROUTER = "INTER_EDGE_ROUTER";
64 private static final String ROUTE_ALL_EDGES = "ROUTE_ALL_EDGES";
65
66 private static final String MINIMUM_DISTANCE = "MINIMUM_DISTANCE";
68 private static final String CENTER_TO_SPACE_RATIO = "SPACE_DRIVEN_VS_CENTER_DRIVEN_SEARCH";
69 private static final String EDGE_CROSSING_COST = "EDGE_CROSSING_COST";
70 private static final String NODE_CROSSING_COST = "NODE_CROSSING_COST";
71 private static final String BEND_COST = "BEND_COST";
72
73 private static final String[] COMPONENT_STYLE_ENUM = {
75 STYLE_ROWS,
76 STYLE_PACKED_COMPACT_RECTANGLE
77 };
78 private static final String[] STYLE_ENUM = {
79 NORMAL, NORMAL_TREE, FIXED_MIXED, FIXED_BOX_NODES
80 };
81 private static final String[] PATH_FINDER_ENUM = {
82 ORTHOGONAL_PATTERN_PATH_FINDER,
83 ORTHOGONAL_SHORTESTPATH_PATH_FINDER
84 };
85
86
87 public CompactOrthogonalLayoutModule() {
88 super (NAME,"yFiles Layout Team",
89 "Compact Orthogonal Layouter");
90 setPortIntersectionCalculatorEnabled(true);
91 }
92
93 public OptionHandler createOptionHandler() {
94 OptionHandler op = new OptionHandler(getModuleName());
95 ConstraintManager cm = new ConstraintManager(op);
96 OptionGroup og;
97
98
99 CompactOrthogonalLayouter layouter = new CompactOrthogonalLayouter();
101 prepare(layouter);
102
103 OrthogonalLayouter cl = (OrthogonalLayouter) layouter.getCoreLayouter();
104
105 int styleIndex = 0;
106 switch (cl.getLayoutStyle()) {
107 case OrthogonalLayouter.NORMAL_STYLE:
108 styleIndex = 0;
109 break;
110 case OrthogonalLayouter.NORMAL_TREE_STYLE:
111 styleIndex = 1;
112 break;
113 case OrthogonalLayouter.FIXED_MIXED_STYLE:
114 styleIndex = 2;
115 break;
116 case OrthogonalLayouter.FIXED_BOX_STYLE:
117 styleIndex = 3;
118 break;
119 }
120 op.addEnum(ORTHOGONAL_LAYOUT_STYLE, STYLE_ENUM, styleIndex);
121
122
123 PartitionLayouter.ComponentPartitionPlacer cpp = (PartitionLayouter.ComponentPartitionPlacer) layouter.getPartitionPlacer();
124
125 int compStyleIndex = 0;
126 switch (cpp.getComponentLayouter().getStyle()) {
127 case ComponentLayouter.STYLE_ROWS:
128 compStyleIndex = 0;
129 break;
130 case ComponentLayouter.STYLE_PACKED_COMPACT_RECTANGLE:
131 compStyleIndex = 1;
132 break;
133 }
134 op.addEnum(PLACEMENT_STRATEGY, COMPONENT_STYLE_ENUM, compStyleIndex);
135
136 op.addBool(USE_VIEW_ASPECT_RATIO, true);
137 op.addDouble(ASPECT_RATIO, layouter.getAspectRatio());
138 cm.setEnabledOnValueEquals(USE_VIEW_ASPECT_RATIO, Boolean.FALSE, ASPECT_RATIO);
139
140 op.addInt(GRID, layouter.getGridSpacing())
141 .setAttribute(IntOptionItem.ATTRIBUTE_MIN_VALUE, new Integer(1));
142
143
144 og = new OptionGroup();
146 og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, INTER_EDGE_ROUTER);
147
148 og.addItem(op.addEnum(PATH_FINDER, PATH_FINDER_ENUM, 1));
149
150 PartitionLayouter.ChannelInterEdgeRouter cier = (PartitionLayouter.ChannelInterEdgeRouter)layouter.getInterEdgeRouter();
151 og.addItem(op.addBool(ROUTE_ALL_EDGES, !cier.isRouteInterEdgesOnly()));
152
153 OrthogonalPatternEdgeRouter oper = new OrthogonalPatternEdgeRouter();
155 ChannelEdgeRouter.OrthogonalShortestPathPathFinder osppf = new ChannelEdgeRouter.OrthogonalShortestPathPathFinder();
156
157 og.addItem(op.addDouble(BEND_COST, oper.getBendCost()));
159 og.addItem(op.addDouble(NODE_CROSSING_COST, oper.getNodeCrossingCost()));
160 og.addItem(op.addInt(MINIMUM_DISTANCE, osppf.getMinimumDistance()));
161 op.getItem(MINIMUM_DISTANCE)
162 .setAttribute(IntOptionItem.ATTRIBUTE_MIN_VALUE, new Integer(4));
163 og.addItem(op.addDouble(EDGE_CROSSING_COST, osppf.getCrossingCost()));
164 og.addItem(op.addDouble(CENTER_TO_SPACE_RATIO, osppf.getCenterToSpaceRatio(), 0, 1));
165
166 cm.setEnabledOnValueEquals(PATH_FINDER, ORTHOGONAL_PATTERN_PATH_FINDER, BEND_COST);
167 cm.setEnabledOnValueEquals(PATH_FINDER, ORTHOGONAL_PATTERN_PATH_FINDER, NODE_CROSSING_COST);
168 cm.setEnabledOnValueEquals(PATH_FINDER, ORTHOGONAL_SHORTESTPATH_PATH_FINDER, CENTER_TO_SPACE_RATIO);
169 return op;
170 }
171
172
173 private void prepare( CompactOrthogonalLayouter layouter ) {
174 PartitionLayouter.InterEdgeRouter ier = layouter.getInterEdgeRouter();
175 if (!(ier instanceof PartitionLayouter.ChannelInterEdgeRouter)) {
176 ier = new PartitionLayouter.ChannelInterEdgeRouter();
177 layouter.setInterEdgeRouter(ier);
178 }
179
180 PartitionLayouter.PartitionPlacer pp = layouter.getPartitionPlacer();
181 if (!(pp instanceof PartitionLayouter.ComponentPartitionPlacer)) {
182 pp = new PartitionLayouter.ComponentPartitionPlacer();
183 layouter.setPartitionPlacer(pp);
184 }
185 Layouter cl = layouter.getCoreLayouter();
186 if (!(cl instanceof OrthogonalLayouter)) {
187 cl = new OrthogonalLayouter();
188 layouter.setCoreLayouter(cl);
189 }
190 }
191
192 private void applyOptions( OptionHandler oh, PartitionLayouter.ChannelInterEdgeRouter router ) {
193 router.setRouteInterEdgesOnly(!oh.getBool(ROUTE_ALL_EDGES));
194 if (oh.getEnum(PATH_FINDER) == 0) {
195 OrthogonalPatternEdgeRouter oper = new OrthogonalPatternEdgeRouter();
196 oper.setMinimumDistance(oh.getInt(MINIMUM_DISTANCE));
197 oper.setEdgeCrossingCost(oh.getDouble(EDGE_CROSSING_COST));
198 oper.setNodeCrossingCost(oh.getDouble(NODE_CROSSING_COST));
199 oper.setBendCost(oh.getDouble(BEND_COST));
200 router.getChannelEdgeRouter().setPathFinderStrategy(oper);
201 } else {
202 ChannelEdgeRouter.OrthogonalShortestPathPathFinder osppf = new ChannelEdgeRouter.OrthogonalShortestPathPathFinder();
203 osppf.setMinimumDistance(oh.getInt(MINIMUM_DISTANCE));
204 osppf.setCrossingCost(oh.getDouble(EDGE_CROSSING_COST));
205 osppf.setCenterToSpaceRatio(oh.getDouble(CENTER_TO_SPACE_RATIO));
206 router.getChannelEdgeRouter().setPathFinderStrategy(osppf);
207 }
208 }
209
210 private void applyOptions( OptionHandler oh, PartitionLayouter.ComponentPartitionPlacer placer ) {
211 if (STYLE_PACKED_COMPACT_RECTANGLE.equals(oh.get(PLACEMENT_STRATEGY))) {
212 placer.getComponentLayouter().setStyle(ComponentLayouter.STYLE_PACKED_COMPACT_RECTANGLE);
213 }
214 else if (STYLE_ROWS.equals(oh.get(PLACEMENT_STRATEGY))) {
215 placer.getComponentLayouter().setStyle(ComponentLayouter.STYLE_ROWS);
216 }
217 }
218
219 private void applyOptions( OptionHandler oh, OrthogonalLayouter layouter ) {
220 switch (OptionHandler.getIndex(STYLE_ENUM, oh.getString(ORTHOGONAL_LAYOUT_STYLE))) {
221 default:
222 case 0:
223 layouter.setLayoutStyle(OrthogonalLayouter.NORMAL_STYLE);
224 break;
225 case 1:
226 layouter.setLayoutStyle(OrthogonalLayouter.NORMAL_TREE_STYLE);
227 break;
228 case 2:
229 layouter.setLayoutStyle(OrthogonalLayouter.FIXED_MIXED_STYLE);
230 break;
231 case 3:
232 layouter.setLayoutStyle(OrthogonalLayouter.FIXED_BOX_STYLE);
233 break;
234 }
235 }
236
237 private void applyOptions( OptionHandler oh, CompactOrthogonalLayouter layouter ) {
238 layouter.setGridSpacing(oh.getInt(GRID));
239
240 final double ar;
241 if (oh.getBool(USE_VIEW_ASPECT_RATIO) && getGraph2DView() != null) {
242 final Dimension dim = getGraph2DView().getSize();
243 ar = dim.getWidth()/dim.getHeight();
244 } else {
245 ar = oh.getDouble(ASPECT_RATIO);
246 }
247
248 layouter.setAspectRatio(ar);
251 }
252
253 public void mainrun() {
254 final OptionHandler op = getOptionHandler();
255
256 CompactOrthogonalLayouter compactOrthogonal = new CompactOrthogonalLayouter();
257 prepare(compactOrthogonal);
258
259 PartitionLayouter.ChannelInterEdgeRouter router = (PartitionLayouter.ChannelInterEdgeRouter) compactOrthogonal.getInterEdgeRouter();
260 applyOptions(op, router);
261
262 PartitionLayouter.ComponentPartitionPlacer placer = (PartitionLayouter.ComponentPartitionPlacer) compactOrthogonal.getPartitionPlacer();
263 applyOptions(op, placer);
264
265 OrthogonalLayouter orthogonalCore = (OrthogonalLayouter) compactOrthogonal.getCoreLayouter();
266 applyOptions(op, orthogonalCore);
267
268 applyOptions(op, compactOrthogonal);
269
270
271 GroupNodeHider groupNodeHider = new GroupNodeHider(compactOrthogonal);
273 groupNodeHider.setHidingEmptyGroupNodes(false);
274 launchLayouter(groupNodeHider);
275 }
276 }
277