1
14 package demo.module;
15
16
17 import y.base.DataMap;
18 import y.base.DataProvider;
19 import y.base.Edge;
20 import y.base.EdgeCursor;
21 import y.base.NodeCursor;
22 import y.layout.CanonicMultiStageLayouter;
23 import y.layout.LabelLayoutConstants;
24 import y.layout.LabelRanking;
25 import y.layout.LayoutOrientation;
26 import y.layout.OrientationLayouter;
27 import y.layout.PortConstraint;
28 import y.layout.PortConstraintKeys;
29 import y.layout.hierarchic.AsIsLayerer;
30 import y.layout.hierarchic.BFSLayerer;
31 import y.layout.hierarchic.IncrementalHierarchicLayouter;
32 import y.layout.hierarchic.incremental.EdgeLayoutDescriptor;
33 import y.layout.hierarchic.incremental.IncrementalHintsFactory;
34 import y.layout.hierarchic.incremental.NodeLayoutDescriptor;
35 import y.layout.hierarchic.incremental.OldLayererWrapper;
36 import y.layout.hierarchic.incremental.SimplexNodePlacer;
37 import y.layout.hierarchic.incremental.TopLevelGroupToSwimlaneStage;
38 import y.layout.labeling.GreedyMISLabeling;
39 import y.option.ConstraintManager;
40 import y.option.ConstraintManager.Condition;
41 import y.option.DefaultEditorFactory;
42 import y.option.EnumOptionItem;
43 import y.option.OptionGroup;
44 import y.option.OptionHandler;
45 import y.option.OptionItem;
46 import y.util.DataProviderAdapter;
47 import y.util.Maps;
48 import y.view.EdgeLabel;
49 import y.view.EdgeRealizer;
50 import y.view.Graph2D;
51 import y.view.Selections;
52 import y.view.hierarchy.GroupLayoutConfigurator;
53 import y.module.LayoutModule;
54
55
62 public class IncrementalHierarchicLayoutModule extends LayoutModule {
63 private static final String INCREMENTAL_HIERARCHIC = "INCREMENTAL_HIERARCHIC";
64
65 private static final String GENERAL = "GENERAL";
66 private static final String INTERACTION = "INTERACTION";
67 private static final String SELECTED_ELEMENTS_INCREMENTALLY = "SELECTED_ELEMENTS_INCREMENTALLY";
68 private static final String USE_DRAWING_AS_SKETCH = "USE_DRAWING_AS_SKETCH";
69 private static final String ORIENTATION = "ORIENTATION";
70 private static final String RIGHT_TO_LEFT = "RIGHT_TO_LEFT";
71 private static final String BOTTOM_TO_TOP = "BOTTOM_TO_TOP";
72 private static final String LEFT_TO_RIGHT = "LEFT_TO_RIGHT";
73 private static final String TOP_TO_BOTTOM = "TOP_TO_BOTTOM";
74 private static final String LAYOUT_COMPONENTS_SEPARATELY = "LAYOUT_COMPONENTS_SEPARATELY";
75 private static final String SYMMETRIC_PLACEMENT = "SYMMETRIC_PLACEMENT";
76 private static final String MINIMUM_DISTANCES = "MINIMUM_DISTANCES";
77 private static final String NODE_TO_NODE_DISTANCE = "NODE_TO_NODE_DISTANCE";
78 private static final String NODE_TO_EDGE_DISTANCE = "NODE_TO_EDGE_DISTANCE";
79 private static final String EDGE_TO_EDGE_DISTANCE = "EDGE_TO_EDGE_DISTANCE";
80 private static final String MINIMUM_LAYER_DISTANCE = "MINIMUM_LAYER_DISTANCE";
81
82 private static final String EDGE_SETTINGS = "EDGE_SETTINGS";
83 private static final String EDGE_ROUTING = "EDGE_ROUTING";
84 private static final String EDGE_ROUTING_ORTHOGONAL = "EDGE_ROUTING_ORTHOGONAL";
85 private static final String EDGE_ROUTING_POLYLINE = "EDGE_ROUTING_POLYLINE";
86 private static final String BACKLOOP_ROUTING = "BACKLOOP_ROUTING";
87 private static final String MINIMUM_FIRST_SEGMENT_LENGTH = "MINIMUM_FIRST_SEGMENT_LENGTH";
88 private static final String MINIMUM_LAST_SEGMENT_LENGTH = "MINIMUM_LAST_SEGMENT_LENGTH";
89 private static final String MINIMUM_EDGE_LENGTH = "MINIMUM_EDGE_LENGTH";
90 private static final String MINIMUM_EDGE_DISTANCE = "MINIMUM_EDGE_DISTANCE";
91 private static final String MINIMUM_SLOPE = "MINIMUM_SLOPE";
92 private static final String PC_OPTIMIZATION_ENABLED = "PC_OPTIMIZATION_ENABLED";
93
94 private static final String RANKS = "RANKS";
95 private static final String RANKING_POLICY = "RANKING_POLICY";
96 private static final String HIERARCHICAL_OPTIMAL = "HIERARCHICAL_OPTIMAL";
97 private static final String HIERARCHICAL_TIGHT_TREE_HEURISTIC = "HIERARCHICAL_TIGHT_TREE_HEURISTIC";
98 private static final String HIERARCHICAL_TOPMOST = "HIERARCHICAL_TOPMOST";
99 private static final String BFS_LAYERS = "BFS_LAYERS";
100 private static final String FROM_SKETCH = "FROM_SKETCH";
101 private static final String LAYER_ALIGNMENT = "LAYER_ALIGNMENT";
102 private static final String TOP = "TOP";
103 private static final String CENTER = "CENTER";
104 private static final String BOTTOM = "BOTTOM";
105 private static final String FROM_SKETCH_PROPERTIES = "FROM_SKETCH_PROPERTIES";
106 private static final String SCALE = "SCALE";
107 private static final String HALO = "HALO";
108 private static final String MINIMUM_SIZE = "MINIMUM_SIZE";
109 private static final String MAXIMUM_SIZE = "MAXIMUM_SIZE";
110
111
112 private static final String LABELING = "LABELING";
113 private static final String NODE_PROPERTIES = "NODE_PROPERTIES";
114 private static final String CONSIDER_NODE_LABELS = "CONSIDER_NODE_LABELS";
115 private static final String EDGE_PROPERTIES = "EDGE_PROPERTIES";
116 private static final String EDGE_LABELING = "EDGE_LABELING";
117 private static final String EDGE_LABELING_NONE = "EDGE_LABELING_NONE";
118 private static final String EDGE_LABELING_HIERARCHIC = "EDGE_LABELING_HIERARCHIC";
119 private static final String EDGE_LABELING_GENERIC = "EDGE_LABELING_GENERIC";
120 private static final String EDGE_LABEL_MODEL = "EDGE_LABEL_MODEL";
121 private static final String EDGE_LABEL_MODEL_FREE = "EDGE_LABEL_MODEL_FREE";
122 private static final String EDGE_LABEL_MODEL_BEST = "EDGE_LABEL_MODEL_BEST";
123 private static final String EDGE_LABEL_MODEL_AS_IS = "EDGE_LABEL_MODEL_AS_IS";
124 private static final String EDGE_LABEL_MODEL_SIDE_SLIDER = "EDGE_LABEL_MODEL_SIDE_SLIDER";
125 private static final String EDGE_LABEL_MODEL_CENTER_SLIDER = "EDGE_LABEL_MODEL_CENTER_SLIDER";
126
127 private static final String GROUPING = "GROUPING";
128 private static final String SWIMLANES = "SWIMLANES";
129 private static final String TREAT_ROOT_GROUPS_AS_SWIMLANES = "TREAT_ROOT_GROUPS_AS_SWIMLANES";
130 private static final String USE_ORDER_FROM_SKETCH = "USE_ORDER_FROM_SKETCH";
131 private static final String SWIMLANE_SPACING = "SWIMLANE_SPACING";
132 private static final String GROUP_LAYERING_STRATEGY = "GROUP_LAYERING_STRATEGY";
133 private static final String GLOBAL_LAYERING = "GLOBAL_LAYERING";
134 private static final String RECURSIVE_LAYERING = "RECURSIVE_LAYERING";
135 private static final String GROUP_ALIGNMENT = "GROUP_ALIGNMENT";
136 private static final String GROUP_ALIGN_TOP = "GROUP_ALIGN_TOP";
137 private static final String GROUP_ALIGN_CENTER = "GROUP_ALIGN_CENTER";
138 private static final String GROUP_ALIGN_BOTTOM = "GROUP_ALIGN_BOTTOM";
139
140 private static final String GROUP_ENABLE_COMPACTION = "GROUP_ENABLE_COMPACTION";
141 private static final String GROUP_HORIZONTAL_COMPACTION = "GROUP_HORIZONTAL_COMPACTION";
142 private static final String GROUP_HORIZONTAL_COMPACTION_NONE = "GROUP_HORIZONTAL_COMPACTION_NONE";
143 private static final String GROUP_HORIZONTAL_COMPACTION_MAX = "GROUP_HORIZONTAL_COMPACTION_MAX";
144
145 private static final Object[] edgeRoutingEnum = new Object[]{EDGE_ROUTING_ORTHOGONAL, EDGE_ROUTING_POLYLINE};
146
147 private static final Object[] orientEnum = {TOP_TO_BOTTOM, LEFT_TO_RIGHT, BOTTOM_TO_TOP, RIGHT_TO_LEFT};
148
149 private static final Object[] alignmentEnum = {TOP, CENTER, BOTTOM};
150 private static final String[] rankingPolicies = {HIERARCHICAL_OPTIMAL, HIERARCHICAL_TIGHT_TREE_HEURISTIC, BFS_LAYERS,
151 FROM_SKETCH, HIERARCHICAL_TOPMOST};
152
153 private static final String[] edgeLabeling = {EDGE_LABELING_NONE, EDGE_LABELING_GENERIC, EDGE_LABELING_HIERARCHIC};
154
155 private static final String[] edgeLabelModel = {
156 EDGE_LABEL_MODEL_BEST,
157 EDGE_LABEL_MODEL_AS_IS,
158 EDGE_LABEL_MODEL_CENTER_SLIDER,
159 EDGE_LABEL_MODEL_SIDE_SLIDER,
160 EDGE_LABEL_MODEL_FREE,
161 };
162
163 private static final Object[] groupStrategyEnum = {GLOBAL_LAYERING, RECURSIVE_LAYERING};
164 private static final Object[] groupAlignmentEnum = {GROUP_ALIGN_TOP, GROUP_ALIGN_CENTER, GROUP_ALIGN_BOTTOM};
165 private static final Object[] groupHorizCompactionEnum = {GROUP_HORIZONTAL_COMPACTION_NONE, GROUP_HORIZONTAL_COMPACTION_MAX};
166
167 public IncrementalHierarchicLayoutModule() {
168 super(INCREMENTAL_HIERARCHIC, "yFiles Layout Team", "A sophisticated hierarchic layout algorithm");
169 setPortIntersectionCalculatorEnabled(true);
170 }
171
172 public OptionHandler createOptionHandler() {
173 OptionHandler op = new OptionHandler(getModuleName());
174
175 OptionGroup og;
176
177 op.useSection(GENERAL);
178
179 og = new OptionGroup();
180 og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, INTERACTION);
181
182 og.addItem(op.addBool(SELECTED_ELEMENTS_INCREMENTALLY, false));
183 OptionItem useDrawingItem = og.addItem(op.addBool(USE_DRAWING_AS_SKETCH, false));
184
185 op.addEnum(ORIENTATION, orientEnum, 0);
186
187 op.addBool(LAYOUT_COMPONENTS_SEPARATELY, false);
188 op.addBool(SYMMETRIC_PLACEMENT, true);
189
190
191 og = new OptionGroup();
192 og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, MINIMUM_DISTANCES);
193 og.addItem(op.addDouble(NODE_TO_NODE_DISTANCE, 30.0d));
194 og.addItem(op.addDouble(NODE_TO_EDGE_DISTANCE, 15.0d));
195 og.addItem(op.addDouble(EDGE_TO_EDGE_DISTANCE, 15.0d));
196 og.addItem(op.addDouble(MINIMUM_LAYER_DISTANCE, 10.0d));
197
198 op.useSection(EDGE_SETTINGS);
199
200 EnumOptionItem eoi = op.addEnum(EDGE_ROUTING, edgeRoutingEnum, 0);
201 eoi.setAttribute(DefaultEditorFactory.ATTRIBUTE_ENUM_STYLE,
202 DefaultEditorFactory.STYLE_RADIO_BUTTONS);
203 eoi.setAttribute(DefaultEditorFactory.ATTRIBUTE_ENUM_ALIGNMENT,
204 DefaultEditorFactory.ALIGNMENT_VERTICAL);
205
206 op.addBool(BACKLOOP_ROUTING, false);
207 op.addDouble(MINIMUM_FIRST_SEGMENT_LENGTH, 10.0d);
208 op.addDouble(MINIMUM_LAST_SEGMENT_LENGTH, 15.0d);
209 op.addDouble(MINIMUM_EDGE_LENGTH, 20.0d);
210 op.addDouble(MINIMUM_EDGE_DISTANCE, 15.0d);
211
212 ConstraintManager cm = new ConstraintManager(op);
213 cm.setEnabledOnValueEquals(eoi, EDGE_ROUTING_POLYLINE,
214 op.addDouble(MINIMUM_SLOPE, 0.25d, 0.0d, 5.0d, 2));
215
216 op.addBool(PC_OPTIMIZATION_ENABLED, false);
217
218 op.useSection(RANKS);
219 op.addEnum(RANKING_POLICY, rankingPolicies, 0);
220 op.addEnum(LAYER_ALIGNMENT, alignmentEnum, 1);
221
222 og = new OptionGroup();
223 og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, FROM_SKETCH_PROPERTIES);
224 og.addItem(op.addDouble(SCALE, 1.0d, 0.0d, 5.0d, 1));
225 og.addItem(op.addDouble(HALO, 0.0d));
226 og.addItem(op.addDouble(MINIMUM_SIZE, 0.0d));
227 og.addItem(op.addDouble(MAXIMUM_SIZE, 1000.0d));
228
229 Condition c =
230 cm.createConditionValueEquals(USE_DRAWING_AS_SKETCH, Boolean.FALSE).and(
231 cm.createConditionValueEquals(SELECTED_ELEMENTS_INCREMENTALLY, Boolean.FALSE));
232 cm.setEnabledOnCondition(c, op.getItem(RANKING_POLICY));
233
234 c = c.inverse().or(cm.createConditionValueEquals(RANKING_POLICY, FROM_SKETCH));
235 cm.setEnabledOnCondition(c, og);
236
237 op.useSection(LABELING);
238 og = new OptionGroup();
239 og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, NODE_PROPERTIES);
240 og.addItem(op.addBool(CONSIDER_NODE_LABELS, true));
241 og = new OptionGroup();
242 og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, EDGE_PROPERTIES);
243 og.addItem(op.addEnum(EDGE_LABELING, edgeLabeling, 0));
244 cm.setEnabledOnValueEquals(op.getItem(EDGE_LABELING), EDGE_LABELING_NONE,
245 og.addItem(op.addEnum(EDGE_LABEL_MODEL, edgeLabelModel, 0)), true);
246
247 op.useSection(GROUPING);
248 OptionItem groupLayeringItem = op.addEnum(GROUP_LAYERING_STRATEGY, groupStrategyEnum, 0);
249 OptionItem layerCompactionItem = op.addBool(GROUP_ENABLE_COMPACTION, true);
250 OptionItem groupAlignementItem = op.addEnum(GROUP_ALIGNMENT, groupAlignmentEnum, 0);
251 cm.setEnabledOnValueEquals(useDrawingItem, Boolean.FALSE, groupLayeringItem);
252 cm.setEnabledOnValueEquals(groupLayeringItem, RECURSIVE_LAYERING, layerCompactionItem);
253 cm.setEnabledOnValueEquals(groupLayeringItem, RECURSIVE_LAYERING, groupAlignementItem);
254 cm.setEnabledOnCondition(cm.createConditionValueEquals(groupLayeringItem, RECURSIVE_LAYERING).and(
255 cm.createConditionValueEquals(layerCompactionItem, Boolean.TRUE).inverse()), groupAlignementItem);
256
257 cm.setEnabledOnCondition(cm.createConditionValueEquals(groupLayeringItem, RECURSIVE_LAYERING).and(
258 cm.createConditionValueEquals(useDrawingItem, Boolean.FALSE)), layerCompactionItem);
259 op.addEnum(GROUP_HORIZONTAL_COMPACTION, groupHorizCompactionEnum, 1);
260
261 op.useSection(SWIMLANES);
262 final OptionItem swimlaneOption = op.addBool(TREAT_ROOT_GROUPS_AS_SWIMLANES, false);
263 final OptionItem fromSketchOption = op.addBool(USE_ORDER_FROM_SKETCH, false);
264 final OptionItem spacingOption = op.addDouble(SWIMLANE_SPACING, 0.0d);
265 cm.setEnabledOnValueEquals(swimlaneOption, Boolean.TRUE, fromSketchOption);
266 cm.setEnabledOnValueEquals(swimlaneOption, Boolean.TRUE, spacingOption);
267 return op;
268 }
269
270 public void mainrun() {
271 CanonicMultiStageLayouter layouter = null;
272 Graph2D graph = getGraph2D();
273
274 OptionHandler op = getOptionHandler();
275
276 final IncrementalHierarchicLayouter ihl = new IncrementalHierarchicLayouter();
277 layouter = ihl;
278
279 DataMap incrementalElements = null;
281 boolean fromSketch = op.getBool(USE_DRAWING_AS_SKETCH);
282 boolean incrementalLayout = op.getBool(SELECTED_ELEMENTS_INCREMENTALLY);
283 boolean selectedElements = !Selections.isEdgeSelectionEmpty(graph) || !Selections.isNodeSelectionEmpty(graph);
284
285 if (incrementalLayout && selectedElements) {
286 incrementalElements = Maps.createHashedDataMap();
288 ihl.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_INCREMENTAL);
290 final IncrementalHintsFactory ihf = ihl.createIncrementalHintsFactory();
291
292 for (NodeCursor nc = graph.selectedNodes(); nc.ok(); nc.next()) {
293 incrementalElements.set(nc.node(), ihf.createLayerIncrementallyHint(nc.node()));
294 }
295
296 for (EdgeCursor ec = graph.selectedEdges(); ec.ok(); ec.next()) {
297 incrementalElements.set(ec.edge(), ihf.createSequenceIncrementallyHint(ec.edge()));
298 }
299 graph.addDataProvider(IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY, incrementalElements);
300 } else if (fromSketch) {
301 ihl.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_INCREMENTAL);
302 } else {
303 ihl.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_FROM_SCRATCH);
304 }
305
306 ((SimplexNodePlacer) ihl.getNodePlacer()).setBaryCenterModeEnabled(op.getBool(SYMMETRIC_PLACEMENT));
308
309 if (GROUP_HORIZONTAL_COMPACTION_NONE.equals(op.getString(GROUP_HORIZONTAL_COMPACTION))) {
310 ((SimplexNodePlacer) ihl.getNodePlacer()).setGroupCompactionStrategy(SimplexNodePlacer.GROUP_COMPACTION_NONE);
311 } else if (GROUP_HORIZONTAL_COMPACTION_MAX.equals(op.getString(GROUP_HORIZONTAL_COMPACTION))) {
312 ((SimplexNodePlacer) ihl.getNodePlacer()).setGroupCompactionStrategy(SimplexNodePlacer.GROUP_COMPACTION_MAX);
313 }
314
315
316 ihl.setComponentLayouterEnabled(op.getBool(LAYOUT_COMPONENTS_SEPARATELY));
317
318 ihl.setMinimumLayerDistance(op.getDouble(MINIMUM_LAYER_DISTANCE));
319 ihl.setNodeToEdgeDistance(op.getDouble(NODE_TO_EDGE_DISTANCE));
320 ihl.setNodeToNodeDistance(op.getDouble(NODE_TO_NODE_DISTANCE));
321 ihl.setEdgeToEdgeDistance(op.getDouble(EDGE_TO_EDGE_DISTANCE));
322
323 final NodeLayoutDescriptor nld = ihl.getNodeLayoutDescriptor();
324 final EdgeLayoutDescriptor eld = ihl.getEdgeLayoutDescriptor();
325
326 eld.setOrthogonallyRouted(op.getEnum(EDGE_ROUTING) == 0);
327 eld.setMinimumFirstSegmentLength(op.getDouble(MINIMUM_FIRST_SEGMENT_LENGTH));
328 eld.setMinimumLastSegmentLength(op.getDouble(MINIMUM_LAST_SEGMENT_LENGTH));
329
330 eld.setMinimumDistance(op.getDouble(MINIMUM_EDGE_DISTANCE));
331 eld.setMinimumLength(op.getDouble(MINIMUM_EDGE_LENGTH));
332
333 eld.setMinimumSlope(op.getDouble(MINIMUM_SLOPE));
334
335 eld.setSourcePortOptimizationEnabled(op.getBool(PC_OPTIMIZATION_ENABLED));
336 eld.setTargetPortOptimizationEnabled(op.getBool(PC_OPTIMIZATION_ENABLED));
337
338 nld.setMinimumDistance(Math.min(ihl.getNodeToNodeDistance(), ihl.getNodeToEdgeDistance()));
339 nld.setMinimumLayerHeight(0);
340
341 if (op.get(LAYER_ALIGNMENT).equals(TOP)) {
342 nld.setLayerAlignment(0.0);
343 } else if (op.get(LAYER_ALIGNMENT).equals(CENTER)) {
344 nld.setLayerAlignment(0.5);
345 } else if (op.get(LAYER_ALIGNMENT).equals(BOTTOM)) {
346 nld.setLayerAlignment(1.0);
347 }
348
349 final OrientationLayouter ol = (OrientationLayouter) ihl.getOrientationLayouter();
350 if (op.get(ORIENTATION).equals(TOP_TO_BOTTOM)) {
351 ol.setOrientation(OrientationLayouter.TOP_TO_BOTTOM);
352 } else if (op.get(ORIENTATION).equals(LEFT_TO_RIGHT)) {
353 ol.setOrientation(OrientationLayouter.LEFT_TO_RIGHT);
354 } else if (op.get(ORIENTATION).equals(BOTTOM_TO_TOP)) {
355 ol.setOrientation(OrientationLayouter.BOTTOM_TO_TOP);
356 } else if (op.get(ORIENTATION).equals(RIGHT_TO_LEFT)) {
357 ol.setOrientation(OrientationLayouter.RIGHT_TO_LEFT);
358 }
359
360 final String el = op.getString(EDGE_LABELING);
361 if (!el.equals(EDGE_LABELING_NONE)) {
362 setupEdgeLabelModel(el, op.getString(EDGE_LABEL_MODEL));
363 if (el.equals(EDGE_LABELING_GENERIC)) {
364 GreedyMISLabeling la = new GreedyMISLabeling();
365 la.setPlaceNodeLabels(false);
366 la.setPlaceEdgeLabels(true);
367 la.setProfitModel(new LabelRanking());
368 ihl.setLabelLayouter(la);
369 ihl.setLabelLayouterEnabled(true);
370 } else if (el.equals(EDGE_LABELING_HIERARCHIC)) {
371 ihl.setIntegratedEdgeLabelingEnabled(true);
372 }
373 } else {
374 ihl.setIntegratedEdgeLabelingEnabled(false);
375 }
376
377 if (op.getBool(CONSIDER_NODE_LABELS)) {
378 ihl.setConsiderNodeLabelsEnabled(true);
379 ihl.getNodeLayoutDescriptor().setNodeLabelMode(NodeLayoutDescriptor.NODE_LABEL_MODE_CONSIDER_FOR_DRAWING);
380 } else {
381 ihl.setConsiderNodeLabelsEnabled(false);
382 }
383
384 DataProvider oldSdp = null;
385 DataProvider oldTdp = null;
386
387 if (op.getBool(BACKLOOP_ROUTING)) {
388 PortConstraint spc = null, tpc = null;
389 switch (ol.getOrientation()) {
390 case LayoutOrientation.TOP_TO_BOTTOM:
391 spc = PortConstraint.create(PortConstraint.SOUTH);
392 tpc = PortConstraint.create(PortConstraint.NORTH);
393 break;
394 case LayoutOrientation.LEFT_TO_RIGHT:
395 spc = PortConstraint.create(PortConstraint.EAST);
396 tpc = PortConstraint.create(PortConstraint.WEST);
397 break;
398 case LayoutOrientation.RIGHT_TO_LEFT:
399 spc = PortConstraint.create(PortConstraint.WEST);
400 tpc = PortConstraint.create(PortConstraint.EAST);
401 break;
402 case LayoutOrientation.BOTTOM_TO_TOP:
403 spc = PortConstraint.create(PortConstraint.NORTH);
404 tpc = PortConstraint.create(PortConstraint.SOUTH);
405 break;
406 }
407
408 oldSdp = graph.getDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY);
409 oldTdp = graph.getDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY);
410
411 DataProvider sdp = new BackloopConstraintDP(spc, oldSdp);
412 DataProvider tdp = new BackloopConstraintDP(tpc, oldTdp);
413
414 if (oldSdp != null) {
415 graph.removeDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY);
416 }
417 if (oldTdp != null) {
418 graph.removeDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY);
419 }
420
421 graph.addDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY, sdp);
422 graph.addDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY, tdp);
423 }
424
425
426 final String rp = op.getString(RANKING_POLICY);
427
428 if (rp.equals(FROM_SKETCH)) {
429 ihl.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_FROM_SKETCH);
430 } else if (rp.equals(HIERARCHICAL_OPTIMAL)) {
431 ihl.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_HIERARCHICAL_OPTIMAL);
432 } else if (rp.equals(HIERARCHICAL_TIGHT_TREE_HEURISTIC)) {
433 ihl.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_HIERARCHICAL_TIGHT_TREE);
434 } else if (rp.equals(HIERARCHICAL_TOPMOST)) {
435 ihl.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_HIERARCHICAL_TOPMOST);
436 } else if (rp.equals(BFS_LAYERS)) {
437 ihl.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_BFS);
438 getGraph2D().addDataProvider(BFSLayerer.CORE_NODES, Selections.createSelectionNodeMap(getGraph2D()));
439 }
440
441 Object layerer = (ihl.getLayoutMode() == IncrementalHierarchicLayouter.LAYOUT_MODE_FROM_SCRATCH) ?
443 ihl.getFromScratchLayerer() : ihl.getFixedElementsLayerer();
444
445 if (layerer instanceof OldLayererWrapper) {
446 y.layout.hierarchic.Layerer coreLayerer = ((OldLayererWrapper) layerer).getOldLayerer();
447 if (coreLayerer instanceof AsIsLayerer) {
448 AsIsLayerer ail = (AsIsLayerer) coreLayerer;
449 ail.setNodeHalo(op.getDouble(HALO));
450 ail.setNodeScalingFactor(op.getDouble(SCALE));
451 ail.setMinimumNodeSize(op.getDouble(MINIMUM_SIZE));
452 ail.setMaximumNodeSize(op.getDouble(MAXIMUM_SIZE));
453 }
454 }
455
456 if (!fromSketch && op.getString(GROUP_LAYERING_STRATEGY).equals(RECURSIVE_LAYERING)) {
457 byte alignmentPolicy = IncrementalHierarchicLayouter.POLICY_ALIGN_GROUPS_TOP;
458 if (op.getString(GROUP_ALIGNMENT).equals(GROUP_ALIGN_CENTER)) {
459 alignmentPolicy = IncrementalHierarchicLayouter.POLICY_ALIGN_GROUPS_CENTER;
460 } else if (op.getString(GROUP_ALIGNMENT).equals(GROUP_ALIGN_BOTTOM)) {
461 alignmentPolicy = IncrementalHierarchicLayouter.POLICY_ALIGN_GROUPS_BOTTOM;
462 }
463 ihl.setGroupCompactionEnabled(op.getBool(GROUP_ENABLE_COMPACTION));
464 ihl.setGroupAlignmentPolicy(alignmentPolicy);
465 ihl.setRecursiveGroupLayeringEnabled(true);
466 } else {
467 ihl.setRecursiveGroupLayeringEnabled(false);
468 }
469
470 if (op.getBool(SWIMLANES, TREAT_ROOT_GROUPS_AS_SWIMLANES)){
471 final TopLevelGroupToSwimlaneStage stage = new TopLevelGroupToSwimlaneStage();
472 stage.setFromSketchSwimlaneOrderingEnabled(op.getBool(SWIMLANES, USE_ORDER_FROM_SKETCH));
473 stage.setSpacing(op.getDouble(SWIMLANES, SWIMLANE_SPACING));
474 ihl.appendStage(stage);
475 }
476
477 GroupLayoutConfigurator glc = new GroupLayoutConfigurator(graph);
479 try {
480 glc.prepareAll();
482 launchLayouter(layouter);
484 } finally {
485 glc.restoreAll();
487
488 if (incrementalElements != null) {
490 graph.removeDataProvider(IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY);
491 incrementalElements = null;
492 }
493
494 if (op.getBool(BACKLOOP_ROUTING)) {
495 graph.removeDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY);
496 if (oldSdp != null) {
497 graph.addDataProvider(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_KEY, oldSdp);
498 }
499 graph.removeDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY);
500 if (oldTdp != null) {
501 graph.addDataProvider(PortConstraintKeys.TARGET_PORT_CONSTRAINT_KEY, oldTdp);
502 }
503 }
504 }
505 }
506
507 void setupEdgeLabelModel(String edgeLabeling, String edgeLabelModel) {
508 if (edgeLabeling.equals(EDGE_LABELING_NONE) || edgeLabelModel.equals(EDGE_LABEL_MODEL_AS_IS)) {
509 return; }
511
512 if (edgeLabelModel.equals(EDGE_LABEL_MODEL_BEST)) {
513 if (edgeLabeling.equals(EDGE_LABELING_GENERIC)) {
514 edgeLabelModel = EDGE_LABEL_MODEL_SIDE_SLIDER;
515 } else if (edgeLabeling.equals(EDGE_LABELING_HIERARCHIC)) {
516 edgeLabelModel = EDGE_LABEL_MODEL_FREE;
517 }
518 }
519
520 byte model = EdgeLabel.SIDE_SLIDER;
521 int preferredSide = LabelLayoutConstants.PLACE_RIGHT_OF_EDGE;
522 if (edgeLabelModel.equals(EDGE_LABEL_MODEL_CENTER_SLIDER)) {
523 model = EdgeLabel.CENTER_SLIDER;
524 preferredSide = LabelLayoutConstants.PLACE_ON_EDGE;
525 } else if (edgeLabelModel.equals(EDGE_LABEL_MODEL_FREE)) {
526 model = EdgeLabel.FREE;
527 preferredSide = LabelLayoutConstants.PLACE_ON_EDGE;
528 }
529
530 Graph2D graph = getGraph2D();
531 for (EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
532 Edge e = ec.edge();
533 EdgeRealizer er = graph.getRealizer(e);
534 for (int i = 0; i < er.labelCount(); i++) {
535 EdgeLabel el = er.getLabel(i);
536 el.setModel(model);
537 int prefAlongEdge = el.getPreferredPlacement() & LabelLayoutConstants.PLACEMENT_ALONG_EDGE_MASK;
538 el.setPreferredPlacement((byte) (preferredSide | prefAlongEdge));
539 }
540 }
541 }
542
543
544 static final class BackloopConstraintDP extends DataProviderAdapter {
545 private PortConstraint pc;
546 private DataProvider delegate;
547 private static final PortConstraint anySide = PortConstraint.create(PortConstraint.ANY_SIDE);
548
549 BackloopConstraintDP(PortConstraint pc, DataProvider delegate) {
550 this.pc = pc;
551 this.delegate = delegate;
552 }
553
554 public Object get(Object o) {
555 if (delegate != null) {
556 Object delegateResult = delegate.get(o);
557 if (delegateResult != null) {
558 return delegateResult;
559 }
560 }
561 Edge e = (Edge) o;
562 if (e.isSelfLoop()) {
563 return anySide;
564 } else {
565 return pc;
566 }
567 }
568 }
569 }