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