1
14 package demo.module;
15
16 import y.base.Edge;
17 import y.base.EdgeCursor;
18
19 import y.layout.LabelLayoutConstants;
20 import y.layout.LabelLayoutTranslator;
21 import y.layout.LabelRanking;
22 import y.layout.LayoutStage;
23 import y.layout.Layouter;
24 import y.layout.grouping.FixedGroupLayoutStage;
25 import y.layout.labeling.GreedyMISLabeling;
26 import y.layout.orthogonal.OrthogonalGroupLayouter;
27 import y.layout.orthogonal.OrthogonalLayouter;
28 import y.option.ConstraintManager;
29
30 import y.view.EdgeLabel;
31 import y.view.EdgeRealizer;
32 import y.view.Graph2D;
33 import y.view.hierarchy.GroupLayoutConfigurator;
34 import y.view.hierarchy.HierarchyManager;
35
36 import y.option.OptionHandler;
37 import y.module.LayoutModule;
38
39
40
47 public class OrthogonalLayoutModule extends LayoutModule
48 {
49 private static final String ORTHOGONAL = "ORTHOGONAL_LAYOUTER";
50 private static final String GROUPING = "GROUPING";
51 private static final String GROUP_POLICY = "GROUP_LAYOUT_POLICY";
52 private static final String IGNORE_GROUPS = "IGNORE_GROUPS";
53 private static final String LAYOUT_GROUPS = "LAYOUT_GROUPS";
54 private static final String FIX_GROUPS = "FIX_GROUPS";
55 private static final String GROUP_LAYOUT_QUALITY = "GROUP_LAYOUT_QUALITY";
56
57 private static final String LENGTH_REDUCTION = "LENGTH_REDUCTION";
58 private static final String STYLE = "STYLE";
59 private static final String USE_RANDOMIZATION = "USE_RANDOMIZATION";
60 private static final String USE_FACE_MAXIMIZATION = "USE_FACE_MAXIMIZATION";
61 private static final String USE_EXISTING_DRAWING_AS_SKETCH = "USE_EXISTING_DRAWING_AS_SKETCH";
62 private static final String CROSSING_POSTPROCESSING = "CROSSING_POSTPROCESSING";
63 private static final String PERCEIVED_BENDS_POSTPROCESSING = "PERCEIVED_BENDS_POSTPROCESSING";
64 private static final String GRID = "GRID";
65 private static final String NORMAL = "NORMAL";
66 private static final String NORMAL_TREE = "NORMAL_TREE";
67 private static final String UNIFORM_NODES = "UNIFORM_NODES";
68 private static final String BOX_NODES = "BOX_NODES";
69 private static final String MIXED = "MIXED";
70 private static final String FIXED_MIXED = "FIXED_MIXED";
71 private static final String FIXED_BOX_NODES = "FIXED_BOX_NODES";
72
73 private static final String LAYOUT = "LAYOUT";
74 private static final String EDGE_LABEL_MODEL = "EDGE_LABEL_MODEL";
75 private static final String EDGE_LABELING = "EDGE_LABELING";
76 private static final String LABELING = "LABELING";
77 private static final String GENERIC = "GENERIC";
78 private static final String NONE = "NONE";
79 private static final String INTEGRATED = "INTEGRATED";
80 private static final String FREE = "FREE";
81 private static final String SIDE_SLIDER = "SIDE_SLIDER";
82 private static final String CENTER_SLIDER = "CENTER_SLIDER";
83 private static final String AS_IS = "AS_IS";
84 private static final String BEST = "BEST";
85
86 private final String styleEnum[] = {NORMAL, NORMAL_TREE, UNIFORM_NODES, BOX_NODES, MIXED, FIXED_MIXED, FIXED_BOX_NODES};
87
88 private static final String[] edgeLabeling = {
89 NONE,
90 INTEGRATED,
91 GENERIC
92 };
93
94 private static final String[] edgeLabelModel = {
95 BEST,
96 AS_IS,
97 CENTER_SLIDER,
98 SIDE_SLIDER,
99 FREE,
100 };
101
102 public OrthogonalLayoutModule()
103 {
104 super (ORTHOGONAL,"yFiles Layout Team",
105 "Orthogonal Layouter");
106 setPortIntersectionCalculatorEnabled(true);
107 }
108
109 public OptionHandler createOptionHandler()
110 {
111 OptionHandler op = new OptionHandler(getModuleName());
112
113 ConstraintManager cm = new ConstraintManager( op );
114
115
116 op.useSection(LAYOUT);
117 op.addEnum(STYLE,styleEnum,0);
118 op.addInt(GRID,25);
119 op.addBool(LENGTH_REDUCTION, true);
120 op.addBool(USE_EXISTING_DRAWING_AS_SKETCH,false);
121 op.addBool(CROSSING_POSTPROCESSING,true);
122 op.addBool(PERCEIVED_BENDS_POSTPROCESSING, true);
123 op.addBool(USE_RANDOMIZATION,true);
124 op.addBool(USE_FACE_MAXIMIZATION,false);
125 op.useSection(LABELING);
126 op.addEnum(EDGE_LABELING, edgeLabeling, 0);
127 op.addEnum(EDGE_LABEL_MODEL, edgeLabelModel, 0);
128
129 cm.setEnabledOnValueEquals( EDGE_LABELING, NONE, EDGE_LABEL_MODEL, true);
130
131 cm.setEnabledOnValueEquals( USE_EXISTING_DRAWING_AS_SKETCH, Boolean.FALSE, CROSSING_POSTPROCESSING);
132 cm.setEnabledOnValueEquals( USE_EXISTING_DRAWING_AS_SKETCH, Boolean.FALSE, PERCEIVED_BENDS_POSTPROCESSING);
133 cm.setEnabledOnValueEquals( USE_EXISTING_DRAWING_AS_SKETCH, Boolean.FALSE, STYLE);
134 cm.setEnabledOnValueEquals( USE_EXISTING_DRAWING_AS_SKETCH, Boolean.FALSE, USE_RANDOMIZATION);
135
136
137 op.useSection(GROUPING);
138 String[] gEnum = { LAYOUT_GROUPS, FIX_GROUPS, IGNORE_GROUPS };
139 op.addEnum(GROUP_POLICY, gEnum, 0);
140 op.addDouble(GROUP_LAYOUT_QUALITY, 1.0, 0.0, 1.0);
141
142 cm.setEnabledOnValueEquals( GROUP_POLICY, LAYOUT_GROUPS, GROUP_LAYOUT_QUALITY);
143
144 return op;
145 }
146
147 public void mainrun()
148 {
149 OptionHandler op = getOptionHandler();
150
151 OrthogonalLayouter orthogonal = new OrthogonalLayouter();
152
153
157 switch (OptionHandler.getIndex(styleEnum, op.getString(STYLE))){
158 default:
159 case 0:
160 orthogonal.setLayoutStyle(OrthogonalLayouter.NORMAL_STYLE);
161 break;
162 case 1:
163 orthogonal.setLayoutStyle(OrthogonalLayouter.NORMAL_TREE_STYLE);
164 break;
165 case 2:
166 orthogonal.setLayoutStyle(OrthogonalLayouter.UNIFORM_STYLE);
167 break;
168 case 3:
169 orthogonal.setLayoutStyle(OrthogonalLayouter.BOX_STYLE);
170 break;
171 case 4:
172 orthogonal.setLayoutStyle(OrthogonalLayouter.MIXED_STYLE);
173 break;
174 case 5:
175 orthogonal.setLayoutStyle(OrthogonalLayouter.FIXED_MIXED_STYLE);
176 break;
177 case 6:
178 orthogonal.setLayoutStyle(OrthogonalLayouter.FIXED_BOX_STYLE);
179 break;
180 }
181 orthogonal.setGrid(op.getInt(GRID));
182 orthogonal.setUseLengthReduction(
183 op.getBool(LENGTH_REDUCTION));
184 orthogonal.setUseCrossingPostprocessing(
185 op.getBool(CROSSING_POSTPROCESSING));
186 orthogonal.setPerceivedBendsOptimizationEnabled(
187 op.getBool(PERCEIVED_BENDS_POSTPROCESSING));
188 orthogonal.setUseRandomization(
189 op.getBool(USE_RANDOMIZATION));
190 orthogonal.setUseFaceMaximization(
191 op.getBool(USE_FACE_MAXIMIZATION));
192 orthogonal.setUseSketchDrawing(op.getBool(USE_EXISTING_DRAWING_AS_SKETCH));
193
194
195
199 String el = op.getString(EDGE_LABELING);
200 if(!el.equals(NONE))
201 {
202 setupEdgeLabelModel(el, op.getString(EDGE_LABEL_MODEL));
203 if(el.equals(GENERIC))
204 {
205 GreedyMISLabeling la = new GreedyMISLabeling();
206 la.setPlaceNodeLabels(false);
207 la.setPlaceEdgeLabels(true);
208 la.setProfitModel(new LabelRanking());
209 orthogonal.setLabelLayouter(la);
210 orthogonal.setLabelLayouterEnabled(true);
211 }
212 else if(el.equals(INTEGRATED))
213 {
214 orthogonal.setLabelLayouter(new LabelLayoutTranslator());
215 orthogonal.setLabelLayouterEnabled(true);
216 }
217 }
218 else
219 {
220 orthogonal.setLabelLayouterEnabled(false);
221 }
222
223 Graph2D graph = getGraph2D();
224 Layouter layouter = orthogonal;
225 LayoutStage preStage = null;
226
227 if(HierarchyManager.containsGroupNodes(graph) && !op.get(GROUP_POLICY).equals(IGNORE_GROUPS))
228 {
229 GroupLayoutConfigurator glc = new GroupLayoutConfigurator(graph);
230
231 glc.prepareAutoBoundsFeatures();
232 glc.prepareGroupDataProviders();
233 glc.prepareGroupNodeInsets();
234
235 FixedGroupLayoutStage fgl = null;
236 if(op.get(GROUP_POLICY).equals(FIX_GROUPS))
237 {
238 fgl = new FixedGroupLayoutStage();
239 fgl.setInterEdgeRoutingStyle(FixedGroupLayoutStage.ROUTING_STYLE_ORTHOGONAL);
240 orthogonal.prependStage(fgl);
241 preStage = fgl;
242 }
243 else
244 {
245 OrthogonalGroupLayouter ogl = new OrthogonalGroupLayouter();
246 ogl.setLabelLayouterEnabled(orthogonal.isLabelLayouterEnabled());
247 ogl.setLabelLayouter(orthogonal.getLabelLayouter());
248
249 ogl.setGrid(op.getInt(GRID));
250 ogl.setLayoutQuality(op.getDouble(GROUP_LAYOUT_QUALITY));
251 layouter = ogl;
252 }
253
254 try
255 {
256 launchLayouter(layouter);
257 }
258 finally
259 {
260 glc.restoreAutoBoundsFeatures();
261 glc.restoreGroupDataProviders();
262 glc.restoreGroupNodeInsets();
263 if(preStage != null) orthogonal.removeStage(preStage);
264 }
265 }
266 else
267 {
268 try {
269 launchLayouter(layouter);
270 }
271 finally {
272 }
273 }
274 }
275
276 void setupEdgeLabelModel(String edgeLabeling, String edgeLabelModel)
277 {
278 if(edgeLabeling.equals(NONE) || edgeLabelModel.equals(AS_IS))
279 {
280 return; }
282
283 if(edgeLabelModel.equals(BEST))
284 {
285 if(edgeLabeling.equals(GENERIC))
286 edgeLabelModel = SIDE_SLIDER;
287 else if(edgeLabeling.equals(INTEGRATED))
288 edgeLabelModel = FREE;
289 }
290
291 byte model = EdgeLabel.SIDE_SLIDER;
292 int preferredSide = LabelLayoutConstants.PLACE_RIGHT_OF_EDGE;
293 if(edgeLabelModel.equals(CENTER_SLIDER))
294 {
295 model = EdgeLabel.CENTER_SLIDER;
296 preferredSide = LabelLayoutConstants.PLACE_ON_EDGE;
297 }
298 else if(edgeLabelModel.equals(FREE))
299 {
300 model = EdgeLabel.FREE;
301 preferredSide = LabelLayoutConstants.PLACE_ON_EDGE;
302 }
303
304 Graph2D graph = getGraph2D();
305 for(EdgeCursor ec = graph.edges(); ec.ok(); ec.next())
306 {
307 Edge e = ec.edge();
308 EdgeRealizer er = graph.getRealizer(e);
309 for(int i = 0; i < er.labelCount(); i++)
310 {
311 EdgeLabel el = er.getLabel(i);
312 el.setModel(model);
313 int prefAlongEdge = el.getPreferredPlacement() & LabelLayoutConstants.PLACEMENT_ALONG_EDGE_MASK;
314 el.setPreferredPlacement((byte)(preferredSide | prefAlongEdge));
315 }
316 }
317 }
318 }
319