1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.9. 
4    ** 
5    ** yWorks proprietary/confidential. Use is subject to license terms.
6    **
7    ** Redistribution of this file or of an unauthorized byte-code version
8    ** of this file is strictly forbidden.
9    **
10   ** Copyright (c) 2000-2011 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  package demo.layout.module;
15  
16  import y.module.LayoutModule;
17  import y.module.YModule;
18  
19  
20  import y.base.DataMap;
21  import y.base.Edge;
22  import y.base.EdgeCursor;
23  import y.base.NodeCursor;
24  import y.layout.CanonicMultiStageLayouter;
25  import y.layout.LabelLayoutConstants;
26  import y.layout.LabelRanking;
27  import y.layout.OrientationLayouter;
28  import y.layout.hierarchic.AsIsLayerer;
29  import y.layout.hierarchic.BFSLayerer;
30  import y.layout.hierarchic.IncrementalHierarchicLayouter;
31  import y.layout.hierarchic.incremental.EdgeLayoutDescriptor;
32  import y.layout.hierarchic.incremental.IncrementalHintsFactory;
33  import y.layout.hierarchic.incremental.NodeLayoutDescriptor;
34  import y.layout.hierarchic.incremental.OldLayererWrapper;
35  import y.layout.hierarchic.incremental.SimplexNodePlacer;
36  import y.layout.hierarchic.incremental.TopLevelGroupToSwimlaneStage;
37  import y.layout.labeling.GreedyMISLabeling;
38  import y.option.ConstraintManager;
39  import y.option.ConstraintManager.Condition;
40  import y.option.DefaultEditorFactory;
41  import y.option.DoubleOptionItem;
42  import y.option.EnumOptionItem;
43  import y.option.OptionGroup;
44  import y.option.OptionHandler;
45  import y.option.OptionItem;
46  import y.util.Maps;
47  import y.view.EdgeLabel;
48  import y.view.EdgeRealizer;
49  import y.view.Graph2D;
50  import y.view.Selections;
51  
52  /**
53   * This module represents an interactive configurator and launcher for
54   * {@link y.layout.hierarchic.IncrementalHierarchicLayouter}.
55   *
56   *
57   * @see <a href="http://docs.yworks.com/yfiles/doc/developers-guide/incremental_hierarchical_layouter.html#incremental_hierarchical_stages">Section Applicable Layout Stages</a> in the yFiles for Java Developer's Guide
58   * @see <a href="http://docs.yworks.com/yfiles/doc/developers-guide/layout_advanced_features.html#layout_advanced_features">Section Advanced Layout Concepts</a> in the yFiles for Java Developer's Guide
59   */
60  public class IncrementalHierarchicLayoutModule extends LayoutModule {
61    private static final String INCREMENTAL_HIERARCHIC = "INCREMENTAL_HIERARCHIC";
62  
63    private static final String GENERAL = "GENERAL";
64    private static final String INTERACTION = "INTERACTION";
65    private static final String SELECTED_ELEMENTS_INCREMENTALLY = "SELECTED_ELEMENTS_INCREMENTALLY";
66    private static final String USE_DRAWING_AS_SKETCH = "USE_DRAWING_AS_SKETCH";
67    private static final String ORIENTATION = "ORIENTATION";
68    private static final String RIGHT_TO_LEFT = "RIGHT_TO_LEFT";
69    private static final String BOTTOM_TO_TOP = "BOTTOM_TO_TOP";
70    private static final String LEFT_TO_RIGHT = "LEFT_TO_RIGHT";
71    private static final String TOP_TO_BOTTOM = "TOP_TO_BOTTOM";
72    private static final String LAYOUT_COMPONENTS_SEPARATELY = "LAYOUT_COMPONENTS_SEPARATELY";
73    private static final String SYMMETRIC_PLACEMENT = "SYMMETRIC_PLACEMENT";
74    private static final String MINIMUM_DISTANCES = "MINIMUM_DISTANCES";
75    private static final String NODE_TO_NODE_DISTANCE = "NODE_TO_NODE_DISTANCE";
76    private static final String NODE_TO_EDGE_DISTANCE = "NODE_TO_EDGE_DISTANCE";
77    private static final String EDGE_TO_EDGE_DISTANCE = "EDGE_TO_EDGE_DISTANCE";
78    private static final String MINIMUM_LAYER_DISTANCE = "MINIMUM_LAYER_DISTANCE";
79    private static final String MAXIMAL_DURATION = "MAXIMAL_DURATION";
80  
81    private static final String EDGE_SETTINGS = "EDGE_SETTINGS";
82    private static final String EDGE_ROUTING = "EDGE_ROUTING";
83    private static final String EDGE_ROUTING_ORTHOGONAL = "EDGE_ROUTING_ORTHOGONAL";
84    private static final String EDGE_ROUTING_POLYLINE = "EDGE_ROUTING_POLYLINE";
85    private static final String BACKLOOP_ROUTING = "BACKLOOP_ROUTING";
86    private static final String MINIMUM_FIRST_SEGMENT_LENGTH = "MINIMUM_FIRST_SEGMENT_LENGTH";
87    private static final String MINIMUM_LAST_SEGMENT_LENGTH = "MINIMUM_LAST_SEGMENT_LENGTH";
88    private static final String MINIMUM_EDGE_LENGTH = "MINIMUM_EDGE_LENGTH";
89    private static final String MINIMUM_EDGE_DISTANCE = "MINIMUM_EDGE_DISTANCE";
90    private static final String MINIMUM_SLOPE = "MINIMUM_SLOPE";
91    private static final String PC_OPTIMIZATION_ENABLED = "PC_OPTIMIZATION_ENABLED";
92    private static final String AUTOMATIC_EDGE_GROUPING_ENABLED = "AUTOMATIC_EDGE_GROUPING_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   private static final String COMPONENT_ARRANGEMENT_POLICY = "COMPONENT_ARRANGEMENT_POLICY";
111   private static final String POLICY_TOPMOST = "POLICY_TOPMOST";
112   private static final String POLICY_COMPACT = "POLICY_COMPACT";
113 
114   private static final String LABELING = "LABELING";
115   private static final String NODE_PROPERTIES = "NODE_PROPERTIES";
116   private static final String CONSIDER_NODE_LABELS = "CONSIDER_NODE_LABELS";
117   private static final String EDGE_PROPERTIES = "EDGE_PROPERTIES";
118   private static final String EDGE_LABELING = "EDGE_LABELING";
119   private static final String EDGE_LABELING_NONE = "EDGE_LABELING_NONE";
120   private static final String EDGE_LABELING_HIERARCHIC = "EDGE_LABELING_HIERARCHIC";
121   private static final String EDGE_LABELING_GENERIC = "EDGE_LABELING_GENERIC";
122   private static final String EDGE_LABEL_MODEL = "EDGE_LABEL_MODEL";
123   private static final String EDGE_LABEL_MODEL_FREE = "EDGE_LABEL_MODEL_FREE";
124   private static final String EDGE_LABEL_MODEL_BEST = "EDGE_LABEL_MODEL_BEST";
125   private static final String EDGE_LABEL_MODEL_AS_IS = "EDGE_LABEL_MODEL_AS_IS";
126   private static final String EDGE_LABEL_MODEL_SIDE_SLIDER = "EDGE_LABEL_MODEL_SIDE_SLIDER";
127   private static final String EDGE_LABEL_MODEL_CENTER_SLIDER = "EDGE_LABEL_MODEL_CENTER_SLIDER";
128 
129   private static final String GROUPING = "GROUPING";
130   private static final String SWIMLANES = "SWIMLANES";
131   private static final String TREAT_ROOT_GROUPS_AS_SWIMLANES = "TREAT_ROOT_GROUPS_AS_SWIMLANES";
132   private static final String USE_ORDER_FROM_SKETCH = "USE_ORDER_FROM_SKETCH";
133   private static final String SWIMLANE_SPACING = "SWIMLANE_SPACING";
134   private static final String GROUP_LAYERING_STRATEGY = "GROUP_LAYERING_STRATEGY";
135   private static final String GLOBAL_LAYERING = "GLOBAL_LAYERING";
136   private static final String RECURSIVE_LAYERING = "RECURSIVE_LAYERING";
137   private static final String GROUP_ALIGNMENT = "GROUP_ALIGNMENT";
138   private static final String GROUP_ALIGN_TOP = "GROUP_ALIGN_TOP";
139   private static final String GROUP_ALIGN_CENTER = "GROUP_ALIGN_CENTER";
140   private static final String GROUP_ALIGN_BOTTOM = "GROUP_ALIGN_BOTTOM";
141 
142   private static final String GROUP_ENABLE_COMPACTION = "GROUP_ENABLE_COMPACTION";
143   private static final String GROUP_HORIZONTAL_COMPACTION = "GROUP_HORIZONTAL_COMPACTION";
144   private static final String GROUP_HORIZONTAL_COMPACTION_NONE = "GROUP_HORIZONTAL_COMPACTION_NONE";
145   private static final String GROUP_HORIZONTAL_COMPACTION_MAX = "GROUP_HORIZONTAL_COMPACTION_MAX";
146 
147   private static final Object[] edgeRoutingEnum = new Object[]{EDGE_ROUTING_ORTHOGONAL, EDGE_ROUTING_POLYLINE};
148 
149   private static final Object[] orientEnum = {TOP_TO_BOTTOM, LEFT_TO_RIGHT, BOTTOM_TO_TOP, RIGHT_TO_LEFT};
150 
151   private static final Object[] alignmentEnum = {TOP, CENTER, BOTTOM};
152   private static final Object[] componentAlignmentEnum = {POLICY_COMPACT, POLICY_TOPMOST};
153   private static final String[] rankingPolicies = {HIERARCHICAL_OPTIMAL, HIERARCHICAL_TIGHT_TREE_HEURISTIC, BFS_LAYERS,
154       FROM_SKETCH, HIERARCHICAL_TOPMOST};
155 
156   private static final String[] edgeLabeling = {EDGE_LABELING_NONE, EDGE_LABELING_GENERIC, EDGE_LABELING_HIERARCHIC};
157 
158   private static final String[] edgeLabelModel = {
159       EDGE_LABEL_MODEL_BEST,
160       EDGE_LABEL_MODEL_AS_IS,
161       EDGE_LABEL_MODEL_CENTER_SLIDER,
162       EDGE_LABEL_MODEL_SIDE_SLIDER,
163       EDGE_LABEL_MODEL_FREE,
164   };
165 
166   private static final Object[] groupStrategyEnum = {GLOBAL_LAYERING, RECURSIVE_LAYERING};
167   private static final Object[] groupAlignmentEnum = {GROUP_ALIGN_TOP, GROUP_ALIGN_CENTER, GROUP_ALIGN_BOTTOM};
168   private static final Object[] groupHorizCompactionEnum = {GROUP_HORIZONTAL_COMPACTION_NONE, GROUP_HORIZONTAL_COMPACTION_MAX};
169 
170   public IncrementalHierarchicLayoutModule() {
171     super(INCREMENTAL_HIERARCHIC, "yFiles Layout Team", "A sophisticated hierarchic layout algorithm");
172     setPortIntersectionCalculatorEnabled(true);
173   }
174 
175   public OptionHandler createOptionHandler() {
176     OptionHandler op = new OptionHandler(getModuleName());
177 
178     OptionGroup og;
179 
180     op.useSection(GENERAL);
181 
182     og = new OptionGroup();
183     og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, INTERACTION);
184 
185     og.addItem(op.addBool(SELECTED_ELEMENTS_INCREMENTALLY, false));
186     OptionItem useDrawingItem = og.addItem(op.addBool(USE_DRAWING_AS_SKETCH, false));
187 
188     op.addEnum(ORIENTATION, orientEnum, 0);
189 
190     op.addBool(LAYOUT_COMPONENTS_SEPARATELY, false);
191     op.addBool(SYMMETRIC_PLACEMENT, true);
192     op.addInt(MAXIMAL_DURATION, 5);
193 
194     og = new OptionGroup();
195     og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, MINIMUM_DISTANCES);
196     og.addItem(op.addDouble(NODE_TO_NODE_DISTANCE, 30.0d));
197     og.addItem(op.addDouble(NODE_TO_EDGE_DISTANCE, 15.0d));
198     og.addItem(op.addDouble(EDGE_TO_EDGE_DISTANCE, 15.0d));
199     og.addItem(op.addDouble(MINIMUM_LAYER_DISTANCE, 10.0d));
200 
201     op.useSection(EDGE_SETTINGS);
202 
203     EnumOptionItem eoi = op.addEnum(EDGE_ROUTING, edgeRoutingEnum, 0);
204     eoi.setAttribute(DefaultEditorFactory.ATTRIBUTE_ENUM_STYLE,
205         DefaultEditorFactory.STYLE_RADIO_BUTTONS);
206     eoi.setAttribute(DefaultEditorFactory.ATTRIBUTE_ENUM_ALIGNMENT,
207         DefaultEditorFactory.ALIGNMENT_VERTICAL);
208 
209     op.addBool(BACKLOOP_ROUTING, false);
210     op.addBool(AUTOMATIC_EDGE_GROUPING_ENABLED, false);
211     op.addDouble(MINIMUM_FIRST_SEGMENT_LENGTH, 10.0d);
212     op.addDouble(MINIMUM_LAST_SEGMENT_LENGTH, 15.0d);
213     op.addDouble(MINIMUM_EDGE_LENGTH, 20.0d);
214     op.addDouble(MINIMUM_EDGE_DISTANCE, 15.0d);
215 
216     ConstraintManager cm = new ConstraintManager(op);
217     cm.setEnabledOnValueEquals(eoi, EDGE_ROUTING_POLYLINE,
218         op.addDouble(MINIMUM_SLOPE, 0.25d, 0.0d, 5.0d, 2));
219 
220     op.addBool(PC_OPTIMIZATION_ENABLED, false);
221 
222     op.useSection(RANKS);
223     op.addEnum(RANKING_POLICY, rankingPolicies, 0);
224     op.addEnum(LAYER_ALIGNMENT, alignmentEnum, 1);
225     op.addEnum(COMPONENT_ARRANGEMENT_POLICY, componentAlignmentEnum, 1);
226 
227     og = new OptionGroup();
228     og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, FROM_SKETCH_PROPERTIES);
229     og.addItem(op.addDouble(SCALE, 1.0d, 0.0d, 5.0d, 1));
230     og.addItem(op.addDouble(HALO, 0.0d));
231     og.addItem(op.addDouble(MINIMUM_SIZE, 0.0d));
232     op.getItem(RANKS, MINIMUM_SIZE)
233       .setAttribute(DoubleOptionItem.ATTRIBUTE_MIN_VALUE, new Double(0.0));
234     og.addItem(op.addDouble(MAXIMUM_SIZE, 1000.0d));
235     op.getItem(RANKS, MAXIMUM_SIZE)
236       .setAttribute(DoubleOptionItem.ATTRIBUTE_MIN_VALUE, new Double(0.0));
237 
238     Condition c =
239         cm.createConditionValueEquals(USE_DRAWING_AS_SKETCH, Boolean.FALSE).and(
240             cm.createConditionValueEquals(SELECTED_ELEMENTS_INCREMENTALLY, Boolean.FALSE));
241     cm.setEnabledOnCondition(c, op.getItem(RANKING_POLICY));
242 
243     c = c.inverse().or(cm.createConditionValueEquals(RANKING_POLICY, FROM_SKETCH));
244     cm.setEnabledOnCondition(c, og);
245       
246     op.useSection(LABELING);
247     og = new OptionGroup();
248     og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, NODE_PROPERTIES);
249     og.addItem(op.addBool(CONSIDER_NODE_LABELS, true));
250     og = new OptionGroup();
251     og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, EDGE_PROPERTIES);
252     og.addItem(op.addEnum(EDGE_LABELING, edgeLabeling, 0));
253     cm.setEnabledOnValueEquals(op.getItem(EDGE_LABELING), EDGE_LABELING_NONE,
254         og.addItem(op.addEnum(EDGE_LABEL_MODEL, edgeLabelModel, 0)), true);
255 
256     op.useSection(GROUPING);
257     OptionItem groupLayeringItem = op.addEnum(GROUP_LAYERING_STRATEGY, groupStrategyEnum, 0);
258     OptionItem layerCompactionItem = op.addBool(GROUP_ENABLE_COMPACTION, true);
259     OptionItem groupAlignementItem = op.addEnum(GROUP_ALIGNMENT, groupAlignmentEnum, 0);
260     cm.setEnabledOnValueEquals(useDrawingItem, Boolean.FALSE, groupLayeringItem);
261     cm.setEnabledOnValueEquals(groupLayeringItem, RECURSIVE_LAYERING, layerCompactionItem);
262     cm.setEnabledOnValueEquals(groupLayeringItem, RECURSIVE_LAYERING, groupAlignementItem);
263     cm.setEnabledOnCondition(cm.createConditionValueEquals(groupLayeringItem, RECURSIVE_LAYERING).and(
264         cm.createConditionValueEquals(layerCompactionItem, Boolean.TRUE).inverse()), groupAlignementItem);
265 
266     cm.setEnabledOnCondition(cm.createConditionValueEquals(groupLayeringItem, RECURSIVE_LAYERING).and(
267         cm.createConditionValueEquals(useDrawingItem, Boolean.FALSE)), layerCompactionItem);
268     op.addEnum(GROUP_HORIZONTAL_COMPACTION, groupHorizCompactionEnum, 1);
269 
270     op.useSection(SWIMLANES);
271     final OptionItem swimlaneOption = op.addBool(TREAT_ROOT_GROUPS_AS_SWIMLANES, false);
272     final OptionItem fromSketchOption = op.addBool(USE_ORDER_FROM_SKETCH, false);
273     final OptionItem spacingOption = op.addDouble(SWIMLANE_SPACING, 0.0d);
274     spacingOption.setAttribute(DoubleOptionItem.ATTRIBUTE_MIN_VALUE, new Double(0.0));
275     cm.setEnabledOnValueEquals(swimlaneOption, Boolean.TRUE, fromSketchOption);
276     cm.setEnabledOnValueEquals(swimlaneOption, Boolean.TRUE, spacingOption);
277     return op;
278   }
279 
280   public void mainrun() {
281     CanonicMultiStageLayouter layouter = null;
282     Graph2D graph = getGraph2D();
283 
284     OptionHandler op = getOptionHandler();
285 
286     final IncrementalHierarchicLayouter ihl = new IncrementalHierarchicLayouter();
287     layouter = ihl;
288     
289     //  mark incremental elements if required
290     DataMap incrementalElements = null;
291     boolean fromSketch = op.getBool(USE_DRAWING_AS_SKETCH);
292     boolean incrementalLayout = op.getBool(SELECTED_ELEMENTS_INCREMENTALLY);
293     boolean selectedElements = !Selections.isEdgeSelectionEmpty(graph) || !Selections.isNodeSelectionEmpty(graph);
294 
295     if (incrementalLayout && selectedElements) {
296       // create storage for both nodes and edges
297       incrementalElements = Maps.createHashedDataMap();
298       // configure the mode
299       ihl.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_INCREMENTAL);
300       final IncrementalHintsFactory ihf = ihl.createIncrementalHintsFactory();
301 
302       for (NodeCursor nc = graph.selectedNodes(); nc.ok(); nc.next()) {
303         incrementalElements.set(nc.node(), ihf.createLayerIncrementallyHint(nc.node()));
304       }
305 
306       for (EdgeCursor ec = graph.selectedEdges(); ec.ok(); ec.next()) {
307         incrementalElements.set(ec.edge(), ihf.createSequenceIncrementallyHint(ec.edge()));
308       }
309       graph.addDataProvider(IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY, incrementalElements);
310     } else if (fromSketch) {
311       ihl.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_INCREMENTAL);
312     } else {
313       ihl.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_FROM_SCRATCH);
314     }
315 
316     // cast to implementation simplex
317     ((SimplexNodePlacer) ihl.getNodePlacer()).setBaryCenterModeEnabled(op.getBool(SYMMETRIC_PLACEMENT));    
318 
319     if (GROUP_HORIZONTAL_COMPACTION_NONE.equals(op.getString(GROUP_HORIZONTAL_COMPACTION))) {
320       ((SimplexNodePlacer) ihl.getNodePlacer()).setGroupCompactionStrategy(SimplexNodePlacer.GROUP_COMPACTION_NONE);
321     } else if (GROUP_HORIZONTAL_COMPACTION_MAX.equals(op.getString(GROUP_HORIZONTAL_COMPACTION))) {
322       ((SimplexNodePlacer) ihl.getNodePlacer()).setGroupCompactionStrategy(SimplexNodePlacer.GROUP_COMPACTION_MAX);
323     }
324 
325 
326     ihl.setComponentLayouterEnabled(op.getBool(LAYOUT_COMPONENTS_SEPARATELY));
327 
328     ihl.setMinimumLayerDistance(op.getDouble(MINIMUM_LAYER_DISTANCE));
329     ihl.setNodeToEdgeDistance(op.getDouble(NODE_TO_EDGE_DISTANCE));
330     ihl.setNodeToNodeDistance(op.getDouble(NODE_TO_NODE_DISTANCE));
331     ihl.setEdgeToEdgeDistance(op.getDouble(EDGE_TO_EDGE_DISTANCE));
332     ihl.setAutomaticEdgeGroupingEnabled(op.getBool(AUTOMATIC_EDGE_GROUPING_ENABLED));
333 
334     final NodeLayoutDescriptor nld = ihl.getNodeLayoutDescriptor();
335     final EdgeLayoutDescriptor eld = ihl.getEdgeLayoutDescriptor();
336 
337     eld.setOrthogonallyRouted(op.getEnum(EDGE_ROUTING) == 0);
338     eld.setMinimumFirstSegmentLength(op.getDouble(MINIMUM_FIRST_SEGMENT_LENGTH));
339     eld.setMinimumLastSegmentLength(op.getDouble(MINIMUM_LAST_SEGMENT_LENGTH));
340 
341     eld.setMinimumDistance(op.getDouble(MINIMUM_EDGE_DISTANCE));
342     eld.setMinimumLength(op.getDouble(MINIMUM_EDGE_LENGTH));
343 
344     eld.setMinimumSlope(op.getDouble(MINIMUM_SLOPE));
345 
346     eld.setSourcePortOptimizationEnabled(op.getBool(PC_OPTIMIZATION_ENABLED));
347     eld.setTargetPortOptimizationEnabled(op.getBool(PC_OPTIMIZATION_ENABLED));
348 
349     nld.setMinimumDistance(Math.min(ihl.getNodeToNodeDistance(), ihl.getNodeToEdgeDistance()));
350     nld.setMinimumLayerHeight(0);
351 
352     if (op.get(LAYER_ALIGNMENT).equals(TOP)) {
353       nld.setLayerAlignment(0.0);
354     } else if (op.get(LAYER_ALIGNMENT).equals(CENTER)) {
355       nld.setLayerAlignment(0.5);
356     } else if (op.get(LAYER_ALIGNMENT).equals(BOTTOM)) {
357       nld.setLayerAlignment(1.0);
358     }
359 
360     final OrientationLayouter ol = (OrientationLayouter) ihl.getOrientationLayouter();
361     if (op.get(ORIENTATION).equals(TOP_TO_BOTTOM)) {
362       ol.setOrientation(OrientationLayouter.TOP_TO_BOTTOM);
363     } else if (op.get(ORIENTATION).equals(LEFT_TO_RIGHT)) {
364       ol.setOrientation(OrientationLayouter.LEFT_TO_RIGHT);
365     } else if (op.get(ORIENTATION).equals(BOTTOM_TO_TOP)) {
366       ol.setOrientation(OrientationLayouter.BOTTOM_TO_TOP);
367     } else if (op.get(ORIENTATION).equals(RIGHT_TO_LEFT)) {
368       ol.setOrientation(OrientationLayouter.RIGHT_TO_LEFT);
369     }
370 
371     final String el = op.getString(EDGE_LABELING);
372     if (!el.equals(EDGE_LABELING_NONE)) {
373       setupEdgeLabelModel(el, op.getString(EDGE_LABEL_MODEL));
374       if (el.equals(EDGE_LABELING_GENERIC)) {
375         GreedyMISLabeling la = new GreedyMISLabeling();
376         la.setPlaceNodeLabels(false);
377         la.setPlaceEdgeLabels(true);
378         la.setProfitModel(new LabelRanking());
379         ihl.setLabelLayouter(la);
380         ihl.setLabelLayouterEnabled(true);
381       } else if (el.equals(EDGE_LABELING_HIERARCHIC)) {
382         ihl.setIntegratedEdgeLabelingEnabled(true);
383       }
384     } else {
385       ihl.setIntegratedEdgeLabelingEnabled(false);
386     }
387 
388     if (op.getBool(CONSIDER_NODE_LABELS)) {
389       ihl.setConsiderNodeLabelsEnabled(true);
390       ihl.getNodeLayoutDescriptor().setNodeLabelMode(NodeLayoutDescriptor.NODE_LABEL_MODE_CONSIDER_FOR_DRAWING);
391     } else {
392       ihl.setConsiderNodeLabelsEnabled(false);
393     }
394 
395 
396     final String rp = op.getString(RANKING_POLICY);
397 
398     if (rp.equals(FROM_SKETCH)) {
399       ihl.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_FROM_SKETCH);
400     } else if (rp.equals(HIERARCHICAL_OPTIMAL)) {
401       ihl.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_HIERARCHICAL_OPTIMAL);
402     } else if (rp.equals(HIERARCHICAL_TIGHT_TREE_HEURISTIC)) {
403       ihl.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_HIERARCHICAL_TIGHT_TREE);
404     } else if (rp.equals(HIERARCHICAL_TOPMOST)) {
405       ihl.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_HIERARCHICAL_TOPMOST);
406     } else if (rp.equals(BFS_LAYERS)) {
407       ihl.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_BFS);
408       getGraph2D().addDataProvider(BFSLayerer.CORE_NODES, Selections.createSelectionNodeMap(getGraph2D()));
409     }
410 
411     if (op.getString(COMPONENT_ARRANGEMENT_POLICY).equals(POLICY_COMPACT)) {
412       ihl.setComponentArrangementPolicy(IncrementalHierarchicLayouter.COMPONENT_ARRANGEMENT_COMPACT);
413     } else {
414       ihl.setComponentArrangementPolicy(IncrementalHierarchicLayouter.COMPONENT_ARRANGEMENT_TOPMOST);
415     }
416 
417     //configure AsIsLayerer
418     Object layerer = (ihl.getLayoutMode() == IncrementalHierarchicLayouter.LAYOUT_MODE_FROM_SCRATCH) ?
419         ihl.getFromScratchLayerer() : ihl.getFixedElementsLayerer();
420 
421     if (layerer instanceof OldLayererWrapper) {
422       layerer = ((OldLayererWrapper) layerer).getOldLayerer();
423     }
424     if (layerer instanceof AsIsLayerer) {
425       AsIsLayerer ail = (AsIsLayerer) layerer;
426       ail.setNodeHalo(op.getDouble(HALO));
427       ail.setNodeScalingFactor(op.getDouble(SCALE));
428       ail.setMinimumNodeSize(op.getDouble(MINIMUM_SIZE));
429       ail.setMaximumNodeSize(op.getDouble(MAXIMUM_SIZE));
430     }
431 
432     if (!fromSketch && op.getString(GROUP_LAYERING_STRATEGY).equals(RECURSIVE_LAYERING)) {
433       byte alignmentPolicy = IncrementalHierarchicLayouter.POLICY_ALIGN_GROUPS_TOP;
434       if (op.getString(GROUP_ALIGNMENT).equals(GROUP_ALIGN_CENTER)) {
435         alignmentPolicy = IncrementalHierarchicLayouter.POLICY_ALIGN_GROUPS_CENTER;
436       } else if (op.getString(GROUP_ALIGNMENT).equals(GROUP_ALIGN_BOTTOM)) {
437         alignmentPolicy = IncrementalHierarchicLayouter.POLICY_ALIGN_GROUPS_BOTTOM;
438       }
439       ihl.setGroupCompactionEnabled(op.getBool(GROUP_ENABLE_COMPACTION));
440       ihl.setGroupAlignmentPolicy(alignmentPolicy);
441       ihl.setRecursiveGroupLayeringEnabled(true);
442     } else {
443       ihl.setRecursiveGroupLayeringEnabled(false);
444     }
445 
446     if (op.getBool(SWIMLANES, TREAT_ROOT_GROUPS_AS_SWIMLANES)){
447       final TopLevelGroupToSwimlaneStage stage = new TopLevelGroupToSwimlaneStage();
448       stage.setFromSketchSwimlaneOrderingEnabled(op.getBool(SWIMLANES, USE_ORDER_FROM_SKETCH));
449       stage.setSpacing(op.getDouble(SWIMLANES, SWIMLANE_SPACING));
450       ihl.appendStage(stage);
451     }
452 
453     ihl.setBackloopRoutingEnabled(op.getBool(BACKLOOP_ROUTING));
454     ihl.setMaximalDuration(op.getInt(MAXIMAL_DURATION) * 1000);
455 
456     try {
457       // launch layouter in buffered mode
458       launchLayouter(layouter);
459     } finally {
460       // remove the registered DataProvider instances
461       if (incrementalElements != null) {
462         graph.removeDataProvider(IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY);
463         incrementalElements = null;
464       }
465 
466       }
467     }
468 
469   void setupEdgeLabelModel(String edgeLabeling, String edgeLabelModel) {
470     if (edgeLabeling.equals(EDGE_LABELING_NONE) || edgeLabelModel.equals(EDGE_LABEL_MODEL_AS_IS)) {
471       return; //nothing to do
472     }
473 
474     if (edgeLabelModel.equals(EDGE_LABEL_MODEL_BEST)) {
475       if (edgeLabeling.equals(EDGE_LABELING_GENERIC)) {
476         edgeLabelModel = EDGE_LABEL_MODEL_SIDE_SLIDER;
477       } else if (edgeLabeling.equals(EDGE_LABELING_HIERARCHIC)) {
478         edgeLabelModel = EDGE_LABEL_MODEL_FREE;
479       }
480     }
481 
482     byte model = EdgeLabel.SIDE_SLIDER;
483     int preferredSide = LabelLayoutConstants.PLACE_RIGHT_OF_EDGE;
484     if (edgeLabelModel.equals(EDGE_LABEL_MODEL_CENTER_SLIDER)) {
485       model = EdgeLabel.CENTER_SLIDER;
486       preferredSide = LabelLayoutConstants.PLACE_ON_EDGE;
487     } else if (edgeLabelModel.equals(EDGE_LABEL_MODEL_FREE)) {
488       model = EdgeLabel.FREE;
489       preferredSide = LabelLayoutConstants.PLACE_ON_EDGE;
490     }
491 
492     Graph2D graph = getGraph2D();
493     for (EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
494       Edge e = ec.edge();
495       EdgeRealizer er = graph.getRealizer(e);
496       for (int i = 0; i < er.labelCount(); i++) {
497         EdgeLabel el = er.getLabel(i);
498         el.setModel(model);
499         if (!edgeLabelModel.equals(EDGE_LABEL_MODEL_FREE)) {          
500           int prefAlongEdge = el.getPreferredPlacement() & LabelLayoutConstants.PLACEMENT_ALONG_EDGE_MASK;
501           el.setPreferredPlacement((byte) (preferredSide | prefAlongEdge));
502         }
503       }
504     }
505   }
506 }
507