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