1
28 package demo.layout.module;
29
30 import y.module.LayoutModule;
31 import y.module.YModule;
32
33 import y.base.DataProvider;
34 import y.base.Edge;
35 import y.base.EdgeCursor;
36 import y.layout.ComponentLayouter;
37 import y.layout.CompositeLayoutStage;
38 import y.layout.LabelLayoutConstants;
39 import y.layout.LabelLayoutDataRefinement;
40 import y.layout.LabelLayoutTranslator;
41 import y.layout.LabelRanking;
42 import y.layout.OrientationLayouter;
43 import y.layout.PortConstraint;
44 import y.layout.PortConstraintKeys;
45 import y.layout.PreferredPlacementDescriptor;
46 import y.layout.grouping.FixedGroupLayoutStage;
47 import y.layout.grouping.GroupNodeHider;
48 import y.layout.hierarchic.BFSLayerer;
49 import y.layout.hierarchic.ClassicLayerSequencer;
50 import y.layout.hierarchic.HierarchicGroupLayouter;
51 import y.layout.hierarchic.HierarchicLayouter;
52 import y.layout.hierarchic.LayerSequencer;
53 import y.layout.labeling.GreedyMISLabeling;
54 import y.option.ConstraintManager;
55 import y.option.EnumOptionItem;
56 import y.option.OptionHandler;
57 import y.util.DataProviderAdapter;
58 import y.view.EdgeLabel;
59 import y.view.EdgeRealizer;
60 import y.view.Graph2D;
61 import y.view.Selections;
62 import y.view.SmartEdgeLabelModel;
63 import y.view.hierarchy.HierarchyManager;
64
65
71 public class HierarchicLayoutModule extends LayoutModule {
72 protected static final String MODULE_HIERARCHIC = "HIERARCHIC";
74
75 protected static final String SECTION_LAYOUT = "LAYOUT";
77 protected static final String ITEM_MINIMAL_LAYER_DISTANCE = "MINIMAL_LAYER_DISTANCE";
79 protected static final String ITEM_MINIMAL_NODE_DISTANCE = "MINIMAL_NODE_DISTANCE";
80 protected static final String ITEM_MINIMAL_EDGE_DISTANCE = "MINIMAL_EDGE_DISTANCE";
81 protected static final String ITEM_MINIMAL_FIRST_SEGMENT_LENGTH = "MINIMAL_FIRST_SEGMENT_LENGTH";
82 protected static final String ITEM_MAXIMAL_DURATION = "MAXIMAL_DURATION";
83 protected static final String ITEM_ORIENTATION = "ORIENTATION";
84 protected static final String VALUE_TOP_TO_BOTTOM = "TOP_TO_BOTTOM";
85 protected static final String VALUE_LEFT_TO_RIGHT = "LEFT_TO_RIGHT";
86 protected static final String VALUE_BOTTOM_TO_TOP = "BOTTOM_TO_TOP";
87 protected static final String VALUE_RIGHT_TO_LEFT = "RIGHT_TO_LEFT";
88 protected static final String ITEM_NODE_PLACEMENT = "NODE_PLACEMENT";
89 protected static final String VALUE_PENDULUM = "PENDULUM";
90 protected static final String VALUE_LINEAR_SEGMENTS = "LINEAR_SEGMENTS";
91 protected static final String VALUE_POLYLINE = "POLYLINE";
92 protected static final String VALUE_TREE = "TREE";
93 protected static final String VALUE_SIMPLEX = "SIMPLEX";
94 protected static final String VALUE_MEDIAN_SIMPLEX = "MEDIAN_SIMPLEX";
95 protected static final String ITEM_EDGE_ROUTING = "EDGE_ROUTING";
96 protected static final String VALUE_POLYLINE_EDGE = "POLYLINE";
97 protected static final String VALUE_ORTHOGONAL = "ORTHOGONAL";
98 protected static final String ITEM_BACKLOOP_ROUTING = "BACKLOOP_ROUTING";
99 protected static final String ITEM_ACT_ON_SELECTION_ONLY = "ACT_ON_SELECTION_ONLY";
100
101 protected static final String SECTION_NODE_RANK = "NODE_RANK";
103 protected static final String ITEM_RANKING_POLICY = "RANKING_POLICY";
105 protected static final String VALUE_NO_RERANKING = "NO_RERANKING";
106 protected static final String VALUE_DOWNSHIFT_NODES = "DOWNSHIFT_NODES";
107 protected static final String VALUE_TIGHT_TREE = "TIGHT_TREE";
108 protected static final String VALUE_SIMPLEX_RANK = "SIMPLEX";
109 protected static final String VALUE_AS_IS_RANK = "AS_IS";
110 protected static final String VALUE_BFS = "BFS";
111
112 protected static final String SECTION_NODE_ORDER = "NODE_ORDER";
114 protected static final String ITEM_WEIGHT_HEURISTIC = "WEIGHT_HEURISTIC";
116 protected static final String VALUE_BARYCENTER = "BARYCENTER";
117 protected static final String VALUE_MEDIAN = "MEDIAN";
118 protected static final String ITEM_USE_TRANSPOSITION = "USE_TRANSPOSITION";
119 protected static final String ITEM_REMOVE_FALSE_CROSSINGS = "REMOVE_FALSE_CROSSINGS";
120 protected static final String ITEM_RANDOMIZATION_ROUNDS = "RANDOMIZATION_ROUNDS";
121
122 protected static final String SECTION_LABELING = "LABELING";
124 protected static final String ITEM_EDGE_LABELING = "EDGE_LABELING";
126 protected static final String VALUE_NONE = "NONE";
127 protected static final String VALUE_HIERARCHIC = "HIERARCHIC";
128 protected static final String VALUE_GENERIC = "GENERIC";
129 protected static final String ITEM_EDGE_LABEL_MODEL = "EDGE_LABEL_MODEL";
130 protected static final String VALUE_BEST = "BEST";
131 protected static final String VALUE_AS_IS = "AS_IS";
132 protected static final String VALUE_CENTER_SLIDER = "CENTER_SLIDER";
133 protected static final String VALUE_SIDE_SLIDER = "SIDE_SLIDER";
134 protected static final String VALUE_FREE = "FREE";
135
136 protected static final String SECTION_GROUPING = "GROUPING";
138 protected static final String ITEM_GROUP_POLICY = "GROUP_LAYOUT_POLICY";
140 protected static final String VALUE_LAYOUT_GROUPS = "LAYOUT_GROUPS";
141 protected static final String VALUE_FIX_GROUPS = "FIX_GROUPS";
142 protected static final String VALUE_IGNORE_GROUPS = "IGNORE_GROUPS";
143 protected static final String ITEM_ENABLE_GLOBAL_SEQUENCING = "ENABLE_GLOBAL_SEQUENCING";
144
145
148 public HierarchicLayoutModule() {
149 super(MODULE_HIERARCHIC);
150 setPortIntersectionCalculatorEnabled(true);
151 }
152
153
157 protected OptionHandler createOptionHandler() {
158 final OptionHandler options = new OptionHandler(getModuleName());
159 final ConstraintManager optionConstraints = new ConstraintManager(options);
160 final HierarchicGroupLayouter defaults = new HierarchicGroupLayouter();
162 final ClassicLayerSequencer defaultsSequencer = (ClassicLayerSequencer) defaults.getLayerSequencer();
163
164 options.useSection(SECTION_LAYOUT);
166 options.addInt(ITEM_MINIMAL_LAYER_DISTANCE, (int)defaults.getMinimalLayerDistance());
168 options.addInt(ITEM_MINIMAL_NODE_DISTANCE, (int)defaults.getMinimalNodeDistance());
169 options.addInt(ITEM_MINIMAL_EDGE_DISTANCE, (int)defaults.getMinimalEdgeDistance());
170 options.addInt(ITEM_MINIMAL_FIRST_SEGMENT_LENGTH, (int) defaults.getMinimalFirstSegmentLength());
171 options.addInt(ITEM_MAXIMAL_DURATION, 5);
172 options.addEnum(ITEM_ORIENTATION, new String[]{
173 VALUE_TOP_TO_BOTTOM,
174 VALUE_LEFT_TO_RIGHT,
175 VALUE_BOTTOM_TO_TOP,
176 VALUE_RIGHT_TO_LEFT
177 }, 0);
178 options.addEnum(ITEM_NODE_PLACEMENT, new String[]{
179 VALUE_PENDULUM,
180 VALUE_LINEAR_SEGMENTS,
181 VALUE_POLYLINE,
182 VALUE_TREE,
183 VALUE_SIMPLEX,
184 VALUE_MEDIAN_SIMPLEX
185 }, defaults.getLayoutStyle());
186 options.addEnum(ITEM_EDGE_ROUTING, new String[]{
187 VALUE_POLYLINE_EDGE,
188 VALUE_ORTHOGONAL
189 }, defaults.getRoutingStyle());
190 options.addBool(ITEM_BACKLOOP_ROUTING, false);
191 options.addBool(ITEM_ACT_ON_SELECTION_ONLY, false);
192
193 options.useSection(SECTION_NODE_RANK);
195 options.addEnum(ITEM_RANKING_POLICY, new String[]{
197 VALUE_NO_RERANKING,
198 VALUE_DOWNSHIFT_NODES,
199 VALUE_TIGHT_TREE,
200 VALUE_SIMPLEX_RANK,
201 VALUE_AS_IS_RANK,
202 VALUE_BFS
203 }, 2);
204
205 options.useSection(SECTION_NODE_ORDER);
207 options.addEnum(ITEM_WEIGHT_HEURISTIC, new String[]{
209 VALUE_BARYCENTER,
210 VALUE_MEDIAN
211 }, defaultsSequencer.getWeightHeuristic());
212 options.addBool(ITEM_USE_TRANSPOSITION, defaultsSequencer.getUseTransposition());
213 options.addBool(ITEM_REMOVE_FALSE_CROSSINGS, defaults.getRemoveFalseCrossings());
214 options.addInt(ITEM_RANDOMIZATION_ROUNDS, defaultsSequencer.getRandomizationRounds());
215
216 options.useSection(SECTION_LABELING);
218 final EnumOptionItem itemEdgeLabeling = options.addEnum(ITEM_EDGE_LABELING, new String[]{
220 VALUE_NONE,
221 VALUE_HIERARCHIC,
222 VALUE_GENERIC
223 }, 0);
224 final EnumOptionItem itemEdgeLabelModel = options.addEnum(ITEM_EDGE_LABEL_MODEL, new String[]{
225 VALUE_BEST,
226 VALUE_AS_IS,
227 VALUE_CENTER_SLIDER,
228 VALUE_SIDE_SLIDER,
229 VALUE_FREE
230 }, 0);
231 optionConstraints.setEnabledOnValueEquals(itemEdgeLabeling, VALUE_NONE, itemEdgeLabelModel, true);
233
234 options.useSection(SECTION_GROUPING);
236 options.addEnum(ITEM_GROUP_POLICY, new String[]{
238 VALUE_LAYOUT_GROUPS,
239 VALUE_FIX_GROUPS,
240 VALUE_IGNORE_GROUPS
241 }, 0);
242 options.addBool(ITEM_ENABLE_GLOBAL_SEQUENCING, true);
243
244 return options;
245 }
246
247
251 protected void mainrun() {
252 final HierarchicGroupLayouter hierarchic = new HierarchicGroupLayouter();
253
254 final OptionHandler options = getOptionHandler();
255 configure(hierarchic, options);
256
257 final Graph2D graph = getGraph2D();
258
259 prepareGraph(graph, options);
260 try {
261 launchLayouter(hierarchic);
262 } finally {
263 restoreGraph(graph, options);
264 }
265 }
266
267
277 protected void prepareGraph(final Graph2D graph, final OptionHandler options) {
278 String el = options.getString(ITEM_EDGE_LABELING);
279 if (!el.equals(VALUE_NONE)) {
280 setupEdgeLabelModel(graph, el, options.getString(ITEM_EDGE_LABEL_MODEL));
281 }
282
283 if (options.getString(ITEM_RANKING_POLICY).equals(VALUE_BFS)) {
284 backupDataProvider(graph, BFSLayerer.CORE_NODES);
286 graph.addDataProvider(BFSLayerer.CORE_NODES, Selections.createSelectionNodeMap(graph));
287 }
288
289 if (options.getBool(ITEM_BACKLOOP_ROUTING)) {
290 final DataProvider oldSdp = graph.getDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY);
291 final DataProvider oldTdp = graph.getDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY);
292 PortConstraint spc = null, tpc = null;
293 if (options.get(ITEM_ORIENTATION).equals(VALUE_TOP_TO_BOTTOM)) {
294 spc = PortConstraint.create(PortConstraint.SOUTH);
295 tpc = PortConstraint.create(PortConstraint.NORTH);
296 } else if (options.get(ITEM_ORIENTATION).equals(VALUE_LEFT_TO_RIGHT)) {
297 spc = PortConstraint.create(PortConstraint.EAST);
298 tpc = PortConstraint.create(PortConstraint.WEST);
299 } else if (options.get(ITEM_ORIENTATION).equals(VALUE_BOTTOM_TO_TOP)) {
300 spc = PortConstraint.create(PortConstraint.NORTH);
301 tpc = PortConstraint.create(PortConstraint.SOUTH);
302 } else if (options.get(ITEM_ORIENTATION).equals(VALUE_RIGHT_TO_LEFT)) {
303 spc = PortConstraint.create(PortConstraint.WEST);
304 tpc = PortConstraint.create(PortConstraint.EAST);
305 }
306 final DataProvider sdp = new BackloopConstraintDP(spc, oldSdp);
307 final DataProvider tdp = new BackloopConstraintDP(tpc, oldTdp);
308
309 graph.addDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY, sdp);
312 graph.addDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY, tdp);
313 }
314 }
315
316
322 protected void restoreGraph(Graph2D graph, OptionHandler options) {
323 if (options.getBool(ITEM_BACKLOOP_ROUTING)) {
324 final BackloopConstraintDP sdp, tdp;
325 sdp = (BackloopConstraintDP) graph.getDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY);
326 tdp = (BackloopConstraintDP) graph.getDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY);
327
328 final DataProvider oldSdp = sdp.delegate;
331 if (oldSdp != null) {
332 graph.addDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY, oldSdp);
333 } else {
334
335 graph.removeDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY);
336 }
337
338 final DataProvider oldTdp = tdp.delegate;
339 if (oldTdp != null) {
340 graph.addDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY, oldTdp);
341 } else {
342 graph.removeDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY);
343 }
344 }
345
346 if (options.getString(ITEM_RANKING_POLICY).equals(VALUE_BFS)) {
348 restoreDataProvider(graph, BFSLayerer.CORE_NODES);
350 }
351 }
352
353
362 protected void configure(HierarchicGroupLayouter hierarchic, OptionHandler options) {
363 ((ComponentLayouter) hierarchic.getComponentLayouter()).setStyle(ComponentLayouter.STYLE_MULTI_ROWS);
364 hierarchic.setRemoveFalseCrossings(options.getBool(ITEM_REMOVE_FALSE_CROSSINGS));
365 hierarchic.setMaximalDuration(options.getInt(ITEM_MAXIMAL_DURATION) * 1000);
366 hierarchic.setMinimalNodeDistance(options.getInt(ITEM_MINIMAL_NODE_DISTANCE));
367 hierarchic.setMinimalEdgeDistance(options.getInt(ITEM_MINIMAL_EDGE_DISTANCE));
368 hierarchic.setMinimalFirstSegmentLength(options.getInt(ITEM_MINIMAL_FIRST_SEGMENT_LENGTH));
369 hierarchic.setMinimalLayerDistance(options.getInt(ITEM_MINIMAL_LAYER_DISTANCE));
370
371 if (options.get(ITEM_ORIENTATION).equals(VALUE_TOP_TO_BOTTOM)) {
372 hierarchic.setLayoutOrientation(OrientationLayouter.TOP_TO_BOTTOM);
373 } else if (options.get(ITEM_ORIENTATION).equals(VALUE_LEFT_TO_RIGHT)) {
374 hierarchic.setLayoutOrientation(OrientationLayouter.LEFT_TO_RIGHT);
375 } else if (options.get(ITEM_ORIENTATION).equals(VALUE_BOTTOM_TO_TOP)) {
376 hierarchic.setLayoutOrientation(OrientationLayouter.BOTTOM_TO_TOP);
377 } else if (options.get(ITEM_ORIENTATION).equals(VALUE_RIGHT_TO_LEFT)) {
378 hierarchic.setLayoutOrientation(OrientationLayouter.RIGHT_TO_LEFT);
379 }
380
381 hierarchic.setGlobalSequencingActive(options.getBool(SECTION_GROUPING, ITEM_ENABLE_GLOBAL_SEQUENCING));
382
383 configureLabeling(hierarchic, options);
384
385 String ls = options.getString(ITEM_NODE_PLACEMENT);
386 if (ls.equals(VALUE_PENDULUM)) {
387 hierarchic.setLayoutStyle(HierarchicLayouter.PENDULUM);
388 } else if (ls.equals(VALUE_POLYLINE)) {
389 hierarchic.setLayoutStyle(HierarchicLayouter.POLYLINE);
390 } else if (ls.equals(VALUE_LINEAR_SEGMENTS)) {
391 hierarchic.setLayoutStyle(HierarchicLayouter.LINEAR_SEGMENTS);
392 } else if (ls.equals(VALUE_TREE)) {
393 hierarchic.setLayoutStyle(HierarchicLayouter.TREE);
394 } else if (ls.equals(VALUE_SIMPLEX)) {
395 hierarchic.setLayoutStyle(HierarchicLayouter.SIMPLEX);
396 } else if (ls.equals(VALUE_MEDIAN_SIMPLEX)) {
397 hierarchic.setLayoutStyle(HierarchicLayouter.MEDIAN_SIMPLEX);
398 }
399 String rs = options.getString(ITEM_EDGE_ROUTING);
400 if (rs.equals(VALUE_POLYLINE)) {
401 hierarchic.setRoutingStyle(HierarchicLayouter.ROUTE_POLYLINE);
402 } else if (rs.equals(VALUE_ORTHOGONAL)) {
403 hierarchic.setRoutingStyle(HierarchicLayouter.ROUTE_ORTHOGONAL);
404 }
405
406 hierarchic.setSubgraphLayouterEnabled(options.getBool(ITEM_ACT_ON_SELECTION_ONLY));
407
408 String rp = options.getString(ITEM_RANKING_POLICY);
409 if (rp.equals(VALUE_AS_IS_RANK)) {
410 hierarchic.setLayeringStrategy(HierarchicLayouter.LAYERING_FROM_SKETCH);
411 } else if (rp.equals(VALUE_SIMPLEX_RANK)) {
412 hierarchic.setLayeringStrategy(HierarchicLayouter.LAYERING_HIERARCHICAL_OPTIMAL);
413 } else if (rp.equals(VALUE_NO_RERANKING)) {
414 hierarchic.setLayeringStrategy(HierarchicLayouter.LAYERING_HIERARCHICAL_TOPMOST);
415 } else if (rp.equals(VALUE_DOWNSHIFT_NODES)) {
416 hierarchic.setLayeringStrategy(HierarchicLayouter.LAYERING_HIERARCHICAL_DOWNSHIFT);
417 } else if (rp.equals(VALUE_TIGHT_TREE)) {
418 hierarchic.setLayeringStrategy(HierarchicLayouter.LAYERING_HIERARCHICAL_TIGHT_TREE);
419 } else if (rp.equals(VALUE_BFS)) {
420 hierarchic.setLayeringStrategy(HierarchicLayouter.LAYERING_BFS);
421 }
422
423 String wh = options.getString(ITEM_WEIGHT_HEURISTIC);
424
425 LayerSequencer layerSequencer = hierarchic.getLayerSequencer();
426 if (layerSequencer instanceof ClassicLayerSequencer) {
427 ClassicLayerSequencer cls = (ClassicLayerSequencer)layerSequencer;
428 if (wh.equals(VALUE_MEDIAN)) {
429 cls.setWeightHeuristic(ClassicLayerSequencer.MEDIAN_HEURISTIC);
430 } else {
431 cls.setWeightHeuristic(ClassicLayerSequencer.BARYCENTER_HEURISTIC);
432 }
433 cls.setUseTransposition(options.getBool(ITEM_USE_TRANSPOSITION));
434 cls.setRandomizationRounds(options.getInt(SECTION_NODE_ORDER, ITEM_RANDOMIZATION_ROUNDS));
435 hierarchic.setLayerSequencer(cls);
436 }
437
438 if (HierarchyManager.containsGroupNodes(getGraph2D())) {
439 if (options.get(ITEM_GROUP_POLICY).equals(VALUE_IGNORE_GROUPS)) {
440 hierarchic.prependStage(new GroupNodeHider());
441 } else {
442 if (options.get(ITEM_GROUP_POLICY).equals(VALUE_FIX_GROUPS)) {
443 final FixedGroupLayoutStage fixedGroupLayoutStage = new FixedGroupLayoutStage();
444 if (options.get(ITEM_EDGE_ROUTING).equals(VALUE_ORTHOGONAL)) {
445 fixedGroupLayoutStage.setInterEdgeRoutingStyle(FixedGroupLayoutStage.ROUTING_STYLE_ORTHOGONAL);
446 }
447 hierarchic.prependStage(fixedGroupLayoutStage);
448 }
449 }
450 }
451 }
452
453 private void configureLabeling(final HierarchicGroupLayouter hierarchic, final OptionHandler options) {
454 final String el = options.getString(ITEM_EDGE_LABELING);
455 if (!el.equals(VALUE_NONE)) {
456 if (el.equals(VALUE_GENERIC)) {
457 final GreedyMISLabeling la = new GreedyMISLabeling();
458 la.setPlaceNodeLabels(false);
459 la.setPlaceEdgeLabels(true);
460 la.setAutoFlippingEnabled(true);
461 la.setProfitModel(new LabelRanking());
462 hierarchic.setLabelLayouter(la);
463 hierarchic.setLabelLayouterEnabled(true);
464 } else if (el.equals(MODULE_HIERARCHIC)) {
465 CompositeLayoutStage ll = new CompositeLayoutStage();
466 ll.appendStage(new LabelLayoutTranslator());
467 ll.appendStage(new LabelLayoutDataRefinement());
468 hierarchic.setLabelLayouter(ll);
469 hierarchic.setLabelLayouterEnabled(true);
470 }
471 } else {
472 hierarchic.setLabelLayouterEnabled(false);
473 }
474 }
475
476 static final class BackloopConstraintDP extends DataProviderAdapter {
477 private final PortConstraint pc;
478 private final DataProvider delegate;
479 private static final PortConstraint anySide = PortConstraint.create(PortConstraint.ANY_SIDE);
480 BackloopConstraintDP(PortConstraint pc, DataProvider delegate) {
481 this.pc = pc;
482 this.delegate = delegate;
483 }
484
485 public Object get(Object o) {
486 if (delegate != null) {
487 final Object delegateResult = delegate.get(o);
488 if (delegateResult != null) {
489 return delegateResult;
490 }
491 }
492 final Edge e = (Edge)o;
493 if (e.isSelfLoop()) {
494 return anySide;
495 } else {
496 return pc;
497 }
498 }
499 }
500
501 private void setupEdgeLabelModel(final Graph2D graph, final String edgeLabeling, String edgeLabelModel) {
502 if (edgeLabeling.equals(VALUE_NONE) || edgeLabelModel.equals(VALUE_AS_IS)) {
503 return; }
505
506 if (edgeLabelModel.equals(VALUE_BEST)) {
507 if (edgeLabeling.equals(VALUE_GENERIC)) {
508 edgeLabelModel = VALUE_SIDE_SLIDER;
509 } else if (edgeLabeling.equals(MODULE_HIERARCHIC)) {
510 edgeLabelModel = VALUE_FREE;
511 }
512 }
513
514 byte model = EdgeLabel.SIDE_SLIDER;
515 byte preferredSide = LabelLayoutConstants.PLACE_RIGHT_OF_EDGE;
516 if (edgeLabelModel.equals(VALUE_CENTER_SLIDER)) {
517 model = EdgeLabel.CENTER_SLIDER;
518 preferredSide = LabelLayoutConstants.PLACE_ON_EDGE;
519 } else if (edgeLabelModel.equals(VALUE_FREE)) {
520 model = EdgeLabel.FREE;
521 preferredSide = LabelLayoutConstants.PLACE_ON_EDGE;
522 }
523
524 for(EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
525 Edge e = ec.edge();
526 EdgeRealizer er = graph.getRealizer(e);
527 for(int i = 0; i < er.labelCount(); i++) {
528 EdgeLabel el = er.getLabel(i);
529 if (EdgeLabel.FREE != model || !(el.getLabelModel() instanceof SmartEdgeLabelModel)) {
530 el.setModel(model);
534 }
535 setPreferredSide(el, preferredSide);
536 }
537 }
538 }
539
540 private static void setPreferredSide(final EdgeLabel el, final byte preferredSide) {
541 final PreferredPlacementDescriptor oldDescriptor =
542 el.getPreferredPlacementDescriptor();
543 if (oldDescriptor.getSideOfEdge() != preferredSide) {
544 final PreferredPlacementDescriptor newDescriptor =
545 new PreferredPlacementDescriptor(oldDescriptor);
546 newDescriptor.setSideOfEdge(preferredSide);
547 el.setPreferredPlacementDescriptor(newDescriptor);
548 }
549 }
550 }
551