1
28 package demo.layout.module;
29
30 import y.module.LayoutModule;
31 import y.module.YModule;
32
33 import y.base.DataMap;
34 import y.base.Edge;
35 import y.base.EdgeCursor;
36 import y.base.Node;
37 import y.base.NodeCursor;
38 import y.base.NodeMap;
39 import y.geom.YPoint;
40 import y.layout.LabelLayoutConstants;
41 import y.layout.LabelRanking;
42 import y.layout.OrientationLayouter;
43 import y.layout.PreferredPlacementDescriptor;
44 import y.layout.hierarchic.AsIsLayerer;
45 import y.layout.hierarchic.BFSLayerer;
46 import y.layout.hierarchic.IncrementalHierarchicLayouter;
47 import y.layout.hierarchic.incremental.EdgeLayoutDescriptor;
48 import y.layout.hierarchic.incremental.HierarchicLayouter;
49 import y.layout.hierarchic.incremental.IncrementalHintsFactory;
50 import y.layout.hierarchic.incremental.NodeLayoutDescriptor;
51 import y.layout.hierarchic.incremental.OldLayererWrapper;
52 import y.layout.hierarchic.incremental.RoutingStyle;
53 import y.layout.hierarchic.incremental.SimplexNodePlacer;
54 import y.layout.hierarchic.incremental.TopLevelGroupToSwimlaneStage;
55 import y.layout.labeling.GreedyMISLabeling;
56 import y.option.ConstraintManager;
57 import y.option.ConstraintManager.Condition;
58 import y.option.DoubleOptionItem;
59 import y.option.EnumOptionItem;
60 import y.option.OptionGroup;
61 import y.option.OptionHandler;
62 import y.option.OptionItem;
63 import y.util.DataProviderAdapter;
64 import y.util.Maps;
65 import y.view.Arrow;
66 import y.view.EdgeLabel;
67 import y.view.EdgeRealizer;
68 import y.view.Graph2D;
69 import y.view.Selections;
70 import y.view.hierarchy.HierarchyManager;
71
72
80 public class IncrementalHierarchicLayoutModule extends LayoutModule {
81 protected static final String MODULE_INCREMENTAL_HIERARCHIC = "INCREMENTAL_HIERARCHIC";
83
84 protected static final String SECTION_GENERAL = "GENERAL";
86 protected static final String TITLE_INTERACTION = "INTERACTION";
88 protected static final String ITEM_SELECTED_ELEMENTS_INCREMENTALLY = "SELECTED_ELEMENTS_INCREMENTALLY";
89 protected static final String ITEM_USE_DRAWING_AS_SKETCH = "USE_DRAWING_AS_SKETCH";
90 protected static final String ITEM_ORIENTATION = "ORIENTATION";
91 protected static final String VALUE_TOP_TO_BOTTOM = "TOP_TO_BOTTOM";
92 protected static final String VALUE_LEFT_TO_RIGHT = "LEFT_TO_RIGHT";
93 protected static final String VALUE_BOTTOM_TO_TOP = "BOTTOM_TO_TOP";
94 protected static final String VALUE_RIGHT_TO_LEFT = "RIGHT_TO_LEFT";
95 protected static final String ITEM_LAYOUT_COMPONENTS_SEPARATELY = "LAYOUT_COMPONENTS_SEPARATELY";
96 protected static final String ITEM_SYMMETRIC_PLACEMENT = "SYMMETRIC_PLACEMENT";
97 protected static final String ITEM_MAXIMAL_DURATION = "MAXIMAL_DURATION";
98 protected static final String TITLE_MINIMUM_DISTANCES = "MINIMUM_DISTANCES";
99 protected static final String ITEM_NODE_TO_NODE_DISTANCE = "NODE_TO_NODE_DISTANCE";
100 protected static final String ITEM_NODE_TO_EDGE_DISTANCE = "NODE_TO_EDGE_DISTANCE";
101 protected static final String ITEM_EDGE_TO_EDGE_DISTANCE = "EDGE_TO_EDGE_DISTANCE";
102 protected static final String ITEM_MINIMUM_LAYER_DISTANCE = "MINIMUM_LAYER_DISTANCE";
103
104 protected static final String SECTION_EDGE_SETTINGS = "EDGE_SETTINGS";
106 protected static final String ITEM_EDGE_ROUTING = "EDGE_ROUTING";
108 protected static final String VALUE_EDGE_ROUTING_ORTHOGONAL = "EDGE_ROUTING_ORTHOGONAL";
109 protected static final String VALUE_EDGE_ROUTING_POLYLINE = "EDGE_ROUTING_POLYLINE";
110 protected static final String VALUE_EDGE_ROUTING_OCTILINEAR = "EDGE_ROUTING_OCTILINEAR";
111 protected static final String ITEM_BACKLOOP_ROUTING = "BACKLOOP_ROUTING";
112 protected static final String ITEM_BACKLOOP_ROUTING_SELFLOOPS = "BACKLOOP_ROUTING_SELFLOOPS";
113 protected static final String ITEM_AUTOMATIC_EDGE_GROUPING_ENABLED = "AUTOMATIC_EDGE_GROUPING_ENABLED";
114 protected static final String ITEM_MINIMUM_FIRST_SEGMENT_LENGTH = "MINIMUM_FIRST_SEGMENT_LENGTH";
115 protected static final String ITEM_MINIMUM_LAST_SEGMENT_LENGTH = "MINIMUM_LAST_SEGMENT_LENGTH";
116 protected static final String ITEM_MINIMUM_EDGE_LENGTH = "MINIMUM_EDGE_LENGTH";
117 protected static final String ITEM_MINIMUM_EDGE_DISTANCE = "MINIMUM_EDGE_DISTANCE";
118 protected static final String ITEM_MINIMUM_SLOPE = "MINIMUM_SLOPE";
119 protected static final String ITEM_PC_OPTIMIZATION_ENABLED = "PC_OPTIMIZATION_ENABLED";
120 protected static final String ITEM_EDGE_STRAIGHTENING_OPTIMIZATION_ENABLED = "EDGE_STRAIGHTENING_OPTIMIZATION_ENABLED";
121 protected static final String ITEM_RECURSIVE_EDGE_ROUTING = "RECURSIVE_EDGE_ROUTING";
122 protected static final String VALUE_RECURSIVE_EDGE_ROUTING_OFF = "RECURSIVE_EDGE_ROUTING_OFF";
123 protected static final String VALUE_RECURSIVE_EDGE_ROUTING_DIRECTED = "RECURSIVE_EDGE_ROUTING_DIRECTED";
124 protected static final String VALUE_RECURSIVE_EDGE_ROUTING_UNDIRECTED = "RECURSIVE_EDGE_ROUTING_UNDIRECTED";
125 protected static final String ITEM_CONSIDER_EDGE_THICKNESS = "CONSIDER_EDGE_THICKNESS";
126 protected static final String ITEM_CONSIDER_EDGE_DIRECTION = "CONSIDER_EDGE_DIRECTION";
127
128 protected static final String SECTION_RANKS = "RANKS";
130 protected static final String ITEM_RANKING_POLICY = "RANKING_POLICY";
132 protected static final String VALUE_HIERARCHICAL_OPTIMAL = "HIERARCHICAL_OPTIMAL";
133 protected static final String VALUE_HIERARCHICAL_TIGHT_TREE_HEURISTIC = "HIERARCHICAL_TIGHT_TREE_HEURISTIC";
134 protected static final String VALUE_BFS_LAYERS = "BFS_LAYERS";
135 protected static final String VALUE_FROM_SKETCH = "FROM_SKETCH";
136 protected static final String VALUE_HIERARCHICAL_TOPMOST = "HIERARCHICAL_TOPMOST";
137 protected static final String ITEM_LAYER_ALIGNMENT = "LAYER_ALIGNMENT";
138 protected static final String VALUE_TOP = "TOP";
139 protected static final String VALUE_CENTER = "CENTER";
140 protected static final String VALUE_BOTTOM = "BOTTOM";
141 protected static final String ITEM_COMPONENT_ARRANGEMENT_POLICY = "COMPONENT_ARRANGEMENT_POLICY";
142 protected static final String VALUE_POLICY_COMPACT = "POLICY_COMPACT";
143 protected static final String VALUE_POLICY_TOPMOST = "POLICY_TOPMOST";
144 protected static final String TITLE_FROM_SKETCH_PROPERTIES = "FROM_SKETCH_PROPERTIES";
145 protected static final String ITEM_SCALE = "SCALE";
146 protected static final String ITEM_HALO = "HALO";
147 protected static final String ITEM_MINIMUM_SIZE = "MINIMUM_SIZE";
148 protected static final String ITEM_MAXIMUM_SIZE = "MAXIMUM_SIZE";
149 protected static final String ITEM_NODE_COMPACTION_ENABLED = "NODE_COMPACTION_ENABLED";
150
151 protected static final String SECTION_LABELING = "LABELING";
153 protected static final String TITLE_NODE_PROPERTIES = "NODE_PROPERTIES";
155 protected static final String ITEM_CONSIDER_NODE_LABELS = "CONSIDER_NODE_LABELS";
156 protected static final String TITLE_EDGE_PROPERTIES = "EDGE_PROPERTIES";
157 protected static final String ITEM_EDGE_LABELING = "EDGE_LABELING";
158 protected static final String VALUE_EDGE_LABELING_NONE = "EDGE_LABELING_NONE";
159 protected static final String VALUE_EDGE_LABELING_GENERIC = "EDGE_LABELING_GENERIC";
160 protected static final String VALUE_EDGE_LABELING_HIERARCHIC = "EDGE_LABELING_HIERARCHIC";
161 protected static final String ITEM_EDGE_LABEL_MODEL = "EDGE_LABEL_MODEL";
162 protected static final String VALUE_EDGE_LABEL_MODEL_BEST = "EDGE_LABEL_MODEL_BEST";
163 protected static final String VALUE_EDGE_LABEL_MODEL_AS_IS = "EDGE_LABEL_MODEL_AS_IS";
164 protected static final String VALUE_EDGE_LABEL_MODEL_CENTER_SLIDER = "EDGE_LABEL_MODEL_CENTER_SLIDER";
165 protected static final String VALUE_EDGE_LABEL_MODEL_SIDE_SLIDER = "EDGE_LABEL_MODEL_SIDE_SLIDER";
166 protected static final String VALUE_EDGE_LABEL_MODEL_FREE = "EDGE_LABEL_MODEL_FREE";
167 protected static final String ITEM_COMPACT_EDGE_LABEL_PLACEMENT = "COMPACT_EDGE_LABEL_PLACEMENT";
168
169 protected static final String SECTION_GROUPING = "GROUPING";
171 protected static final String ITEM_GROUP_LAYERING_STRATEGY = "GROUP_LAYERING_STRATEGY";
173 protected static final String VALUE_GLOBAL_LAYERING = "GLOBAL_LAYERING";
174 protected static final String VALUE_RECURSIVE_LAYERING = "RECURSIVE_LAYERING";
175 protected static final String ITEM_GROUP_ENABLE_COMPACTION = "GROUP_ENABLE_COMPACTION";
176 protected static final String ITEM_GROUP_ALIGNMENT = "GROUP_ALIGNMENT";
177 protected static final String VALUE_GROUP_ALIGN_TOP = "GROUP_ALIGN_TOP";
178 protected static final String VALUE_GROUP_ALIGN_CENTER = "GROUP_ALIGN_CENTER";
179 protected static final String VALUE_GROUP_ALIGN_BOTTOM = "GROUP_ALIGN_BOTTOM";
180 protected static final String ITEM_GROUP_HORIZONTAL_COMPACTION = "GROUP_HORIZONTAL_COMPACTION";
181 protected static final String VALUE_GROUP_HORIZONTAL_COMPACTION_NONE = "GROUP_HORIZONTAL_COMPACTION_NONE";
182 protected static final String VALUE_GROUP_HORIZONTAL_COMPACTION_MAX = "GROUP_HORIZONTAL_COMPACTION_MAX";
183
184 protected static final String SECTION_SWIMLANES = "SWIMLANES";
186 protected static final String ITEM_TREAT_ROOT_GROUPS_AS_SWIMLANES = "TREAT_ROOT_GROUPS_AS_SWIMLANES";
188 protected static final String ITEM_USE_ORDER_FROM_SKETCH = "USE_ORDER_FROM_SKETCH";
189 protected static final String ITEM_SWIMLANE_SPACING = "SWIMLANE_SPACING";
190
191 private static final String SECTION_GRID = "GRID";
193 private static final String ITEM_GRID_ENABLED = "GRID_ENABLED";
195 private static final String ITEM_GRID_SPACING = "GRID_SPACING";
196 private static final String ITEM_GRID_PORT_ASSIGNMENT = "GRID_PORT_ASSIGNMENT";
197 private static final String VALUE_GRID_PORT_ASSIGNMENT_DEFAULT = "GRID_PORT_ASSIGNMENT_DEFAULT";
198 private static final String VALUE_GRID_PORT_ASSIGNMENT_ON_GRID = "GRID_PORT_ASSIGNMENT_ON_GRID";
199 private static final String VALUE_GRID_PORT_ASSIGNMENT_ON_SUBGRID = "GRID_PORT_ASSIGNMENT_ON_SUBGRID";
200
201
204 public IncrementalHierarchicLayoutModule() {
205 super(MODULE_INCREMENTAL_HIERARCHIC);
206 setPortIntersectionCalculatorEnabled(true);
207 }
208
209
213 protected OptionHandler createOptionHandler() {
214 final OptionHandler options = new OptionHandler(getModuleName());
215 final ConstraintManager optionConstraints = new ConstraintManager(options);
216
217 options.useSection(SECTION_GENERAL);
219 final OptionGroup interactionGroup = new OptionGroup();
221 interactionGroup.setAttribute(OptionGroup.ATTRIBUTE_TITLE, TITLE_INTERACTION);
222 final OptionItem itemSelectedElementsIncrementally = interactionGroup.addItem(
224 options.addBool(ITEM_SELECTED_ELEMENTS_INCREMENTALLY, false));
225 final OptionItem itemUseDrawingAsSketch = interactionGroup.addItem(
226 options.addBool(ITEM_USE_DRAWING_AS_SKETCH, false));
227
228 options.addEnum(ITEM_ORIENTATION, new String[]{
231 VALUE_TOP_TO_BOTTOM,
232 VALUE_LEFT_TO_RIGHT,
233 VALUE_BOTTOM_TO_TOP,
234 VALUE_RIGHT_TO_LEFT
235 }, 0);
236 options.addBool(ITEM_LAYOUT_COMPONENTS_SEPARATELY, false);
237 final OptionItem itemSymmetricPlacement = options.addBool(ITEM_SYMMETRIC_PLACEMENT, true);
238 options.addInt(ITEM_MAXIMAL_DURATION, 5);
239
240 final OptionGroup distancesGroup = new OptionGroup();
242 distancesGroup.setAttribute(OptionGroup.ATTRIBUTE_TITLE, TITLE_MINIMUM_DISTANCES);
243 distancesGroup.addItem(options.addDouble(ITEM_NODE_TO_NODE_DISTANCE, 30.0d));
245 distancesGroup.addItem(options.addDouble(ITEM_NODE_TO_EDGE_DISTANCE, 15.0d));
246 distancesGroup.addItem(options.addDouble(ITEM_EDGE_TO_EDGE_DISTANCE, 15.0d));
247 distancesGroup.addItem(options.addDouble(ITEM_MINIMUM_LAYER_DISTANCE, 10.0d));
248
249 options.useSection(SECTION_EDGE_SETTINGS);
251 final EnumOptionItem itemEdgeRouting = options.addEnum(ITEM_EDGE_ROUTING, new String[]{
253 VALUE_EDGE_ROUTING_ORTHOGONAL,
254 VALUE_EDGE_ROUTING_POLYLINE,
255 VALUE_EDGE_ROUTING_OCTILINEAR
256 }, 0);
257 final OptionItem itemBackloopRouting = options.addBool(ITEM_BACKLOOP_ROUTING, false);
258 final OptionItem itemBackloopRoutingSelfloops = options.addBool(ITEM_BACKLOOP_ROUTING_SELFLOOPS, false);
259 options.addBool(ITEM_AUTOMATIC_EDGE_GROUPING_ENABLED, false);
260 options.addDouble(ITEM_MINIMUM_FIRST_SEGMENT_LENGTH, 10.0d);
261 options.addDouble(ITEM_MINIMUM_LAST_SEGMENT_LENGTH, 15.0d);
262 options.addDouble(ITEM_MINIMUM_EDGE_LENGTH, 20.0d);
263 options.addDouble(ITEM_MINIMUM_EDGE_DISTANCE, 15.0d);
264 options.addBool(ITEM_PC_OPTIMIZATION_ENABLED, false);
265 final OptionItem itemEdgeStraighteningOptimization =
266 options.addBool(ITEM_EDGE_STRAIGHTENING_OPTIMIZATION_ENABLED, false);
267 final OptionItem itemMinimumSlope = options.addDouble(ITEM_MINIMUM_SLOPE, 0.25d, 0.0d, 5.0d, 2);
268 final OptionItem recursiveEdgeRouting = options.addEnum(ITEM_RECURSIVE_EDGE_ROUTING, new String[]{
269 VALUE_RECURSIVE_EDGE_ROUTING_OFF,
270 VALUE_RECURSIVE_EDGE_ROUTING_DIRECTED,
271 VALUE_RECURSIVE_EDGE_ROUTING_UNDIRECTED
272 }, 0);
273 options.addBool(ITEM_CONSIDER_EDGE_THICKNESS, true);
274 options.addBool(ITEM_CONSIDER_EDGE_DIRECTION, true);
275
276 final Condition constraint =
278 optionConstraints.createConditionValueEquals(itemUseDrawingAsSketch, Boolean.FALSE).and(
279 optionConstraints.createConditionValueEquals(itemSelectedElementsIncrementally, Boolean.FALSE));
280 optionConstraints.setEnabledOnCondition(constraint, recursiveEdgeRouting);
281
282 optionConstraints.setEnabledOnValueEquals(itemSymmetricPlacement, Boolean.FALSE,
284 itemEdgeStraighteningOptimization);
285 optionConstraints.setEnabledOnValueEquals(itemBackloopRouting, Boolean.TRUE, itemBackloopRoutingSelfloops);
286 optionConstraints.setEnabledOnValueEquals(itemEdgeRouting, VALUE_EDGE_ROUTING_POLYLINE, itemMinimumSlope);
287
288 options.useSection(SECTION_RANKS);
290 final EnumOptionItem itemRankingPolicy = options.addEnum(ITEM_RANKING_POLICY, new String[]{
292 VALUE_HIERARCHICAL_OPTIMAL,
293 VALUE_HIERARCHICAL_TIGHT_TREE_HEURISTIC,
294 VALUE_BFS_LAYERS,
295 VALUE_FROM_SKETCH,
296 VALUE_HIERARCHICAL_TOPMOST
297 }, 0);
298 options.addEnum(ITEM_LAYER_ALIGNMENT, new String[]{
299 VALUE_TOP,
300 VALUE_CENTER,
301 VALUE_BOTTOM
302 }, 1);
303 options.addBool(ITEM_NODE_COMPACTION_ENABLED, false);
304 options.addEnum(ITEM_COMPONENT_ARRANGEMENT_POLICY, new String[]{
305 VALUE_POLICY_COMPACT,
306 VALUE_POLICY_TOPMOST
307 }, 1);
308
309 final OptionGroup sketchPropertyGroup = new OptionGroup();
311 sketchPropertyGroup.setAttribute(OptionGroup.ATTRIBUTE_TITLE, TITLE_FROM_SKETCH_PROPERTIES);
312 sketchPropertyGroup.addItem(options.addDouble(ITEM_SCALE, 1.0d, 0.0d, 5.0d, 1));
314 sketchPropertyGroup.addItem(options.addDouble(ITEM_HALO, 0.0d));
315 final OptionItem itemMinimumSize = sketchPropertyGroup.addItem(options.addDouble(ITEM_MINIMUM_SIZE, 0.0d));
316 itemMinimumSize.setAttribute(DoubleOptionItem.ATTRIBUTE_MIN_VALUE, new Double(0.0));
317 final OptionItem itemMaximumSize = sketchPropertyGroup.addItem(options.addDouble(ITEM_MAXIMUM_SIZE, 1000.0d));
318 itemMaximumSize.setAttribute(DoubleOptionItem.ATTRIBUTE_MIN_VALUE, new Double(0.0));
319 Condition c =
321 optionConstraints.createConditionValueEquals(itemUseDrawingAsSketch, Boolean.FALSE).and(
322 optionConstraints.createConditionValueEquals(itemSelectedElementsIncrementally, Boolean.FALSE));
323 optionConstraints.setEnabledOnCondition(c, itemRankingPolicy);
324 c = c.inverse().or(optionConstraints.createConditionValueEquals(itemRankingPolicy, VALUE_FROM_SKETCH));
325 optionConstraints.setEnabledOnCondition(c, sketchPropertyGroup);
326
327 options.useSection(SECTION_LABELING);
329 final OptionGroup nodePropertyGroup = new OptionGroup();
331 nodePropertyGroup.setAttribute(OptionGroup.ATTRIBUTE_TITLE, TITLE_NODE_PROPERTIES);
332 nodePropertyGroup.addItem(options.addBool(ITEM_CONSIDER_NODE_LABELS, true));
334
335 final OptionGroup edgePropertyGroup = new OptionGroup();
337 edgePropertyGroup.setAttribute(OptionGroup.ATTRIBUTE_TITLE, TITLE_EDGE_PROPERTIES);
338 final EnumOptionItem itemEdgeLabeling = options.addEnum(ITEM_EDGE_LABELING, new String[]{
340 VALUE_EDGE_LABELING_NONE,
341 VALUE_EDGE_LABELING_GENERIC,
342 VALUE_EDGE_LABELING_HIERARCHIC
343 }, 0);
344 edgePropertyGroup.addItem(itemEdgeLabeling);
345 final OptionItem itemEdgeLabelModel = edgePropertyGroup.addItem(
346 options.addEnum(ITEM_EDGE_LABEL_MODEL, new String[]{
347 VALUE_EDGE_LABEL_MODEL_BEST,
348 VALUE_EDGE_LABEL_MODEL_AS_IS,
349 VALUE_EDGE_LABEL_MODEL_CENTER_SLIDER,
350 VALUE_EDGE_LABEL_MODEL_SIDE_SLIDER,
351 VALUE_EDGE_LABEL_MODEL_FREE,
352 }, 0));
353 final OptionItem itemEdgeLabelPlacement = options.addBool(ITEM_COMPACT_EDGE_LABEL_PLACEMENT, true);
354 optionConstraints.setEnabledOnValueEquals(itemEdgeLabeling, VALUE_EDGE_LABELING_NONE, itemEdgeLabelModel, true);
356 optionConstraints.setEnabledOnValueEquals(itemEdgeLabeling, VALUE_EDGE_LABELING_HIERARCHIC,
357 edgePropertyGroup.addItem(itemEdgeLabelPlacement));
358
359 options.useSection(SECTION_GROUPING);
361 final EnumOptionItem itemGroupLayeringStrategy = options.addEnum(ITEM_GROUP_LAYERING_STRATEGY, new String[]{
363 VALUE_GLOBAL_LAYERING,
364 VALUE_RECURSIVE_LAYERING
365 }, 0);
366 final OptionItem itemGroupEnableCompaction = options.addBool(ITEM_GROUP_ENABLE_COMPACTION, true);
367 final EnumOptionItem itemGroupAlignment = options.addEnum(ITEM_GROUP_ALIGNMENT, new String[]{
368 VALUE_GROUP_ALIGN_TOP,
369 VALUE_GROUP_ALIGN_CENTER,
370 VALUE_GROUP_ALIGN_BOTTOM
371 }, 0);
372 options.addEnum(ITEM_GROUP_HORIZONTAL_COMPACTION, new String[]{
373 VALUE_GROUP_HORIZONTAL_COMPACTION_NONE,
374 VALUE_GROUP_HORIZONTAL_COMPACTION_MAX
375 }, 1);
376 optionConstraints.setEnabledOnValueEquals(itemUseDrawingAsSketch, Boolean.FALSE, itemGroupLayeringStrategy);
378 optionConstraints.setEnabledOnValueEquals(itemGroupLayeringStrategy, VALUE_RECURSIVE_LAYERING, itemGroupEnableCompaction);
379 optionConstraints.setEnabledOnValueEquals(itemGroupLayeringStrategy, VALUE_RECURSIVE_LAYERING, itemGroupAlignment);
380 optionConstraints.setEnabledOnCondition(
381 optionConstraints.createConditionValueEquals(itemGroupLayeringStrategy, VALUE_RECURSIVE_LAYERING).and(
382 optionConstraints.createConditionValueEquals(itemGroupEnableCompaction, Boolean.TRUE).inverse()
383 ), itemGroupAlignment);
384 optionConstraints.setEnabledOnCondition(
385 optionConstraints.createConditionValueEquals(itemGroupLayeringStrategy, VALUE_RECURSIVE_LAYERING).and(
386 optionConstraints.createConditionValueEquals(itemUseDrawingAsSketch, Boolean.FALSE)
387 ), itemGroupEnableCompaction);
388
389 options.useSection(SECTION_SWIMLANES);
391 final OptionItem swimlaneOption = options.addBool(ITEM_TREAT_ROOT_GROUPS_AS_SWIMLANES, false);
393 final OptionItem fromSketchOption = options.addBool(ITEM_USE_ORDER_FROM_SKETCH, false);
394 final OptionItem spacingOption = options.addDouble(ITEM_SWIMLANE_SPACING, 0.0d);
395 spacingOption.setAttribute(DoubleOptionItem.ATTRIBUTE_MIN_VALUE, new Double(0.0));
396 optionConstraints.setEnabledOnValueEquals(swimlaneOption, Boolean.TRUE, fromSketchOption);
398 optionConstraints.setEnabledOnValueEquals(swimlaneOption, Boolean.TRUE, spacingOption);
399
400 options.useSection(SECTION_GRID);
402 final OptionItem grid = options.addBool(ITEM_GRID_ENABLED, false);
404 final OptionItem gridSpacing = options.addDouble(ITEM_GRID_SPACING, 10, 1, 100, 1);
405 final OptionItem portAssignment = options.addEnum(ITEM_GRID_PORT_ASSIGNMENT, new String[]{
406 VALUE_GRID_PORT_ASSIGNMENT_DEFAULT,
407 VALUE_GRID_PORT_ASSIGNMENT_ON_GRID,
408 VALUE_GRID_PORT_ASSIGNMENT_ON_SUBGRID,
409 }, 0);
410 optionConstraints.setEnabledOnValueEquals(grid, Boolean.TRUE, gridSpacing);
411 optionConstraints.setEnabledOnValueEquals(grid, Boolean.TRUE, portAssignment);
412
413 return options;
414 }
415
416
420 protected void mainrun() {
421 final IncrementalHierarchicLayouter hierarchic = new IncrementalHierarchicLayouter();
422
423 final OptionHandler options = getOptionHandler();
424 configure(hierarchic, options);
425
426 final Graph2D graph = getGraph2D();
427
428 final boolean incrementalLayout = options.getBool(ITEM_SELECTED_ELEMENTS_INCREMENTALLY);
429 final boolean selectedElements = graph.selectedEdges().ok() || graph.selectedNodes().ok();
430 if (incrementalLayout && selectedElements) {
431 final DataMap incrementalElements = Maps.createHashedDataMap();
434
435 final IncrementalHintsFactory ihf = hierarchic.createIncrementalHintsFactory();
436
437 final HierarchyManager hm = graph.getHierarchyManager();
438 for (NodeCursor nc = graph.selectedNodes(); nc.ok(); nc.next()) {
439 final Node n = nc.node();
440 if (hm != null && hm.isGroupNode(n)) {
441 incrementalElements.set(n, ihf.createIncrementalGroupHint(n));
442 } else {
443 incrementalElements.set(n, ihf.createLayerIncrementallyHint(n));
444 }
445 }
446
447 for (EdgeCursor ec = graph.selectedEdges(); ec.ok(); ec.next()) {
448 incrementalElements.set(ec.edge(), ihf.createSequenceIncrementallyHint(ec.edge()));
449 }
450 backupDataProvider(graph, IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY);
452 graph.addDataProvider(IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY, incrementalElements);
453 }
454
455 final boolean gridEnabled = options.getBool(ITEM_GRID_ENABLED);
456 if (gridEnabled) {
457 backupDataProvider(graph, HierarchicLayouter.NODE_LAYOUT_DESCRIPTOR_DPKEY);
459
460 final String portAssignment = options.getString(ITEM_GRID_PORT_ASSIGNMENT);
461 final byte gridPortAssignment;
462 if (VALUE_GRID_PORT_ASSIGNMENT_ON_GRID.equals(portAssignment)) {
463 gridPortAssignment = NodeLayoutDescriptor.PORT_ASSIGNMENT_ON_GRID;
464 } else if (VALUE_GRID_PORT_ASSIGNMENT_ON_SUBGRID.equals(portAssignment)) {
465 gridPortAssignment = NodeLayoutDescriptor.PORT_ASSIGNMENT_ON_SUBGRID;
466 } else {
467 gridPortAssignment = NodeLayoutDescriptor.PORT_ASSIGNMENT_DEFAULT;
468 }
469
470 final NodeLayoutDescriptor nld = hierarchic.getNodeLayoutDescriptor();
471 graph.addDataProvider(HierarchicLayouter.NODE_LAYOUT_DESCRIPTOR_DPKEY, new DataProviderAdapter() {
472 public Object get(Object dataHolder) {
473 if (dataHolder instanceof Node) {
474 final Node node = (Node) dataHolder;
475 final NodeLayoutDescriptor descriptor = new NodeLayoutDescriptor();
477 descriptor.setLayerAlignment(nld.getLayerAlignment());
478 descriptor.setMinimumDistance(nld.getMinimumDistance());
479 descriptor.setMinimumLayerHeight(nld.getMinimumLayerHeight());
480 descriptor.setNodeLabelMode(nld.getNodeLabelMode());
481 descriptor.setGridReference(new YPoint(0.0, (nld.getLayerAlignment() - 0.5) * graph.getHeight(node)));
483 descriptor.setPortAssignment(gridPortAssignment);
484 return descriptor;
485 }
486 return null;
487 }
488 });
489 }
490
491 final boolean recursiveRouting = options.get(ITEM_RECURSIVE_EDGE_ROUTING) != VALUE_RECURSIVE_EDGE_ROUTING_OFF;
493 if (recursiveRouting) {
494 backupDataProvider(graph, IncrementalHierarchicLayouter.FOLDER_NODES_DPKEY);
496 final NodeMap node2IsFolder = Maps.createHashedNodeMap();
497 final HierarchyManager hm = graph.getHierarchyManager();
498 for (NodeCursor nc = graph.nodes(); nc.ok(); nc.next()) {
499 final Node node = nc.node();
500 if (hm.isFolderNode(node)) {
501 node2IsFolder.setBool(node, true);
502 }
503 }
504 graph.addDataProvider(IncrementalHierarchicLayouter.FOLDER_NODES_DPKEY, node2IsFolder);
505 }
506
507 prepareGraph(graph, options);
508 try {
509 launchLayouter(hierarchic);
511 } finally {
512 restoreGraph(graph, options);
513
514 if (gridEnabled) {
515 restoreDataProvider(graph, HierarchicLayouter.NODE_LAYOUT_DESCRIPTOR_DPKEY);
517 }
518
519 if (incrementalLayout && selectedElements) {
520 restoreDataProvider(graph, IncrementalHierarchicLayouter.INCREMENTAL_HINTS_DPKEY);
522 }
523
524 if (recursiveRouting) {
525 restoreDataProvider(graph, IncrementalHierarchicLayouter.FOLDER_NODES_DPKEY);
527 }
528 }
529 }
530
531
541 protected void prepareGraph(final Graph2D graph, final OptionHandler options) {
542 if (options.getString(ITEM_RANKING_POLICY).equals(VALUE_BFS_LAYERS)) {
543 backupDataProvider(graph, BFSLayerer.CORE_NODES);
545 graph.addDataProvider(BFSLayerer.CORE_NODES, Selections.createSelectionNodeMap(graph));
546 }
547 if (options.getBool(ITEM_CONSIDER_EDGE_THICKNESS)) {
548 backupDataProvider(graph, IncrementalHierarchicLayouter.EDGE_THICKNESS_DPKEY);
550 graph.addDataProvider(
551 IncrementalHierarchicLayouter.EDGE_THICKNESS_DPKEY,
552 new EdgeWidthProvider(graph));
553 }
554 if (options.getBool(ITEM_CONSIDER_EDGE_DIRECTION)) {
555 backupDataProvider(graph, IncrementalHierarchicLayouter.EDGE_DIRECTEDNESS_DPKEY);
557 graph.addDataProvider(
558 IncrementalHierarchicLayouter.EDGE_DIRECTEDNESS_DPKEY,
559 new EdgeDirectednessProvider(graph));
560 }
561 final String el = options.getString(ITEM_EDGE_LABELING);
562 if (!el.equals(VALUE_EDGE_LABELING_NONE)) {
563 setupEdgeLabelModel(graph, el, options.getString(ITEM_EDGE_LABEL_MODEL));
564 }
565 }
566
567
573 protected void restoreGraph(final Graph2D graph, final OptionHandler options) {
574 if (options.getBool(ITEM_CONSIDER_EDGE_THICKNESS)) {
575 restoreDataProvider(graph, IncrementalHierarchicLayouter.EDGE_THICKNESS_DPKEY);
577 }
578 if (options.getBool(ITEM_CONSIDER_EDGE_DIRECTION)) {
579 restoreDataProvider(graph, IncrementalHierarchicLayouter.EDGE_DIRECTEDNESS_DPKEY);
581 }
582 if (options.getString(ITEM_RANKING_POLICY).equals(VALUE_BFS_LAYERS)) {
583 restoreDataProvider(graph, BFSLayerer.CORE_NODES);
585 }
586 }
587
588
597 protected void configure(final IncrementalHierarchicLayouter hierarchic, final OptionHandler options) {
598 final Graph2D graph = getGraph2D();
599
600 boolean incrementalLayout = options.getBool(ITEM_SELECTED_ELEMENTS_INCREMENTALLY);
601 boolean selectedElements = graph.selectedEdges().ok() || graph.selectedNodes().ok();
602 final boolean isIncrementalModeEnabled = (incrementalLayout && selectedElements) || options.getBool(ITEM_USE_DRAWING_AS_SKETCH);
604 if (isIncrementalModeEnabled) {
605 hierarchic.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_INCREMENTAL);
606 } else {
607 hierarchic.setLayoutMode(IncrementalHierarchicLayouter.LAYOUT_MODE_FROM_SCRATCH);
608 }
609
610 final SimplexNodePlacer np = (SimplexNodePlacer) hierarchic.getNodePlacer();
612 np.setBaryCenterModeEnabled(options.getBool(ITEM_SYMMETRIC_PLACEMENT));
613 np.setEdgeStraighteningOptimizationEnabled(
614 options.getBool(ITEM_EDGE_STRAIGHTENING_OPTIMIZATION_ENABLED));
615
616 if (VALUE_GROUP_HORIZONTAL_COMPACTION_NONE.equals(options.getString(ITEM_GROUP_HORIZONTAL_COMPACTION))) {
617 np.setGroupCompactionStrategy(SimplexNodePlacer.GROUP_COMPACTION_NONE);
618 } else if (VALUE_GROUP_HORIZONTAL_COMPACTION_MAX.equals(options.getString(ITEM_GROUP_HORIZONTAL_COMPACTION))) {
619 np.setGroupCompactionStrategy(SimplexNodePlacer.GROUP_COMPACTION_MAX);
620 }
621
622 hierarchic.setComponentLayouterEnabled(options.getBool(ITEM_LAYOUT_COMPONENTS_SEPARATELY));
623 hierarchic.setMinimumLayerDistance(options.getDouble(ITEM_MINIMUM_LAYER_DISTANCE));
624 hierarchic.setNodeToEdgeDistance(options.getDouble(ITEM_NODE_TO_EDGE_DISTANCE));
625 hierarchic.setNodeToNodeDistance(options.getDouble(ITEM_NODE_TO_NODE_DISTANCE));
626 hierarchic.setEdgeToEdgeDistance(options.getDouble(ITEM_EDGE_TO_EDGE_DISTANCE));
627 hierarchic.setAutomaticEdgeGroupingEnabled(options.getBool(ITEM_AUTOMATIC_EDGE_GROUPING_ENABLED));
628
629 final EdgeLayoutDescriptor eld = hierarchic.getEdgeLayoutDescriptor();
630 if (options.get(ITEM_EDGE_ROUTING) == VALUE_EDGE_ROUTING_OCTILINEAR) {
631 eld.setRoutingStyle(new RoutingStyle(RoutingStyle.EDGE_STYLE_OCTILINEAR));
632 } else if (options.get(ITEM_EDGE_ROUTING) == VALUE_EDGE_ROUTING_POLYLINE) {
633 eld.setRoutingStyle(new RoutingStyle(RoutingStyle.EDGE_STYLE_POLYLINE));
634 } else {
635 eld.setRoutingStyle(new RoutingStyle(RoutingStyle.EDGE_STYLE_ORTHOGONAL));
636 }
637
638 eld.setMinimumFirstSegmentLength(options.getDouble(ITEM_MINIMUM_FIRST_SEGMENT_LENGTH));
639 eld.setMinimumLastSegmentLength(options.getDouble(ITEM_MINIMUM_LAST_SEGMENT_LENGTH));
640 eld.setMinimumDistance(options.getDouble(ITEM_MINIMUM_EDGE_DISTANCE));
641 eld.setMinimumLength(options.getDouble(ITEM_MINIMUM_EDGE_LENGTH));
642 eld.setMinimumSlope(options.getDouble(ITEM_MINIMUM_SLOPE));
643 eld.setSourcePortOptimizationEnabled(options.getBool(ITEM_PC_OPTIMIZATION_ENABLED));
644 eld.setTargetPortOptimizationEnabled(options.getBool(ITEM_PC_OPTIMIZATION_ENABLED));
645
646 if (!isIncrementalModeEnabled && options.get(ITEM_RECURSIVE_EDGE_ROUTING) == VALUE_RECURSIVE_EDGE_ROUTING_DIRECTED) {
647 eld.setRecursiveEdgeStyle(EdgeLayoutDescriptor.RECURSIVE_EDGE_STYLE_DIRECTED);
648 } else if (!isIncrementalModeEnabled && options.get(ITEM_RECURSIVE_EDGE_ROUTING) == VALUE_RECURSIVE_EDGE_ROUTING_UNDIRECTED) {
649 eld.setRecursiveEdgeStyle(EdgeLayoutDescriptor.RECURSIVE_EDGE_STYLE_UNDIRECTED);
650 } else {
651 eld.setRecursiveEdgeStyle(EdgeLayoutDescriptor.RECURSIVE_EDGE_STYLE_OFF);
652 }
653
654 final NodeLayoutDescriptor nld = hierarchic.getNodeLayoutDescriptor();
655 nld.setMinimumDistance(Math.min(hierarchic.getNodeToNodeDistance(), hierarchic.getNodeToEdgeDistance()));
656 nld.setMinimumLayerHeight(0);
657 if (options.get(ITEM_LAYER_ALIGNMENT).equals(VALUE_TOP)) {
658 nld.setLayerAlignment(0.0);
659 } else if (options.get(ITEM_LAYER_ALIGNMENT).equals(VALUE_CENTER)) {
660 nld.setLayerAlignment(0.5);
661 } else if (options.get(ITEM_LAYER_ALIGNMENT).equals(VALUE_BOTTOM)) {
662 nld.setLayerAlignment(1.0);
663 }
664
665 if (options.get(ITEM_ORIENTATION).equals(VALUE_TOP_TO_BOTTOM)) {
666 hierarchic.setLayoutOrientation(OrientationLayouter.TOP_TO_BOTTOM);
667 } else if (options.get(ITEM_ORIENTATION).equals(VALUE_LEFT_TO_RIGHT)) {
668 hierarchic.setLayoutOrientation(OrientationLayouter.LEFT_TO_RIGHT);
669 } else if (options.get(ITEM_ORIENTATION).equals(VALUE_BOTTOM_TO_TOP)) {
670 hierarchic.setLayoutOrientation(OrientationLayouter.BOTTOM_TO_TOP);
671 } else if (options.get(ITEM_ORIENTATION).equals(VALUE_RIGHT_TO_LEFT)) {
672 hierarchic.setLayoutOrientation(OrientationLayouter.RIGHT_TO_LEFT);
673 }
674
675 configureLabeling(hierarchic, options);
676
677 if (options.getBool(ITEM_CONSIDER_NODE_LABELS)) {
678 hierarchic.setConsiderNodeLabelsEnabled(true);
679 hierarchic.getNodeLayoutDescriptor().setNodeLabelMode(NodeLayoutDescriptor.NODE_LABEL_MODE_CONSIDER_FOR_DRAWING);
680 } else {
681 hierarchic.setConsiderNodeLabelsEnabled(false);
682 }
683
684 final String rp = options.getString(ITEM_RANKING_POLICY);
685 if (rp.equals(VALUE_FROM_SKETCH)) {
686 hierarchic.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_FROM_SKETCH);
687 } else if (rp.equals(VALUE_HIERARCHICAL_OPTIMAL)) {
688 hierarchic.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_HIERARCHICAL_OPTIMAL);
689 } else if (rp.equals(VALUE_HIERARCHICAL_TIGHT_TREE_HEURISTIC)) {
690 hierarchic.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_HIERARCHICAL_TIGHT_TREE);
691 } else if (rp.equals(VALUE_HIERARCHICAL_TOPMOST)) {
692 hierarchic.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_HIERARCHICAL_TOPMOST);
693 } else if (rp.equals(VALUE_BFS_LAYERS)) {
694 hierarchic.setFromScratchLayeringStrategy(IncrementalHierarchicLayouter.LAYERING_STRATEGY_BFS);
695 }
696
697 if (options.getString(ITEM_COMPONENT_ARRANGEMENT_POLICY).equals(VALUE_POLICY_COMPACT)) {
698 hierarchic.setComponentArrangementPolicy(IncrementalHierarchicLayouter.COMPONENT_ARRANGEMENT_COMPACT);
699 } else {
700 hierarchic.setComponentArrangementPolicy(IncrementalHierarchicLayouter.COMPONENT_ARRANGEMENT_TOPMOST);
701 }
702
703 ((SimplexNodePlacer) hierarchic.getNodePlacer()).setNodeCompactionEnabled(options.getBool(ITEM_NODE_COMPACTION_ENABLED));
704
705 Object layerer = (hierarchic.getLayoutMode() == IncrementalHierarchicLayouter.LAYOUT_MODE_FROM_SCRATCH) ?
707 hierarchic.getFromScratchLayerer() : hierarchic.getFixedElementsLayerer();
708 if (layerer instanceof OldLayererWrapper) {
709 layerer = ((OldLayererWrapper) layerer).getOldLayerer();
710 }
711 if (layerer instanceof AsIsLayerer) {
712 AsIsLayerer ail = (AsIsLayerer) layerer;
713 ail.setNodeHalo(options.getDouble(ITEM_HALO));
714 ail.setNodeScalingFactor(options.getDouble(ITEM_SCALE));
715 ail.setMinimumNodeSize(options.getDouble(ITEM_MINIMUM_SIZE));
716 ail.setMaximumNodeSize(options.getDouble(ITEM_MAXIMUM_SIZE));
717 }
718
719 if (!options.getBool(ITEM_USE_DRAWING_AS_SKETCH) &&
720 options.getString(ITEM_GROUP_LAYERING_STRATEGY).equals(VALUE_RECURSIVE_LAYERING)) {
721 byte alignmentPolicy = IncrementalHierarchicLayouter.POLICY_ALIGN_GROUPS_TOP;
722 if (options.getString(ITEM_GROUP_ALIGNMENT).equals(VALUE_GROUP_ALIGN_CENTER)) {
723 alignmentPolicy = IncrementalHierarchicLayouter.POLICY_ALIGN_GROUPS_CENTER;
724 } else if (options.getString(ITEM_GROUP_ALIGNMENT).equals(VALUE_GROUP_ALIGN_BOTTOM)) {
725 alignmentPolicy = IncrementalHierarchicLayouter.POLICY_ALIGN_GROUPS_BOTTOM;
726 }
727 hierarchic.setGroupCompactionEnabled(options.getBool(ITEM_GROUP_ENABLE_COMPACTION));
728 hierarchic.setGroupAlignmentPolicy(alignmentPolicy);
729 hierarchic.setRecursiveGroupLayeringEnabled(true);
730 } else {
731 hierarchic.setRecursiveGroupLayeringEnabled(false);
732 }
733
734 if (options.getBool(SECTION_SWIMLANES, ITEM_TREAT_ROOT_GROUPS_AS_SWIMLANES)) {
735 final TopLevelGroupToSwimlaneStage stage = new TopLevelGroupToSwimlaneStage();
736 stage.setFromSketchSwimlaneOrderingEnabled(options.getBool(SECTION_SWIMLANES, ITEM_USE_ORDER_FROM_SKETCH));
737 stage.setSpacing(options.getDouble(SECTION_SWIMLANES, ITEM_SWIMLANE_SPACING));
738 hierarchic.appendStage(stage);
739 }
740
741 hierarchic.setBackloopRoutingEnabled(options.getBool(ITEM_BACKLOOP_ROUTING));
742 hierarchic.setBackloopRoutingForSelfloopsEnabled(options.getBool(ITEM_BACKLOOP_ROUTING_SELFLOOPS));
743 hierarchic.setMaximalDuration(options.getInt(ITEM_MAXIMAL_DURATION) * 1000);
744
745
746 final boolean gridEnabled = options.getBool(ITEM_GRID_ENABLED);
747 if (gridEnabled) {
748 hierarchic.setGridSpacing(options.getDouble(ITEM_GRID_SPACING));
749 }
750 }
751
752 private void configureLabeling(final IncrementalHierarchicLayouter hierarchic, final OptionHandler options) {
753 final String el = options.getString(ITEM_EDGE_LABELING);
754 if (!el.equals(VALUE_EDGE_LABELING_NONE)) {
755 if (el.equals(VALUE_EDGE_LABELING_GENERIC)) {
756 final GreedyMISLabeling la = new GreedyMISLabeling();
757 la.setPlaceNodeLabels(false);
758 la.setPlaceEdgeLabels(true);
759 la.setAutoFlippingEnabled(true);
760 la.setProfitModel(new LabelRanking());
761 hierarchic.prependStage(la);
763 } else if (el.equals(VALUE_EDGE_LABELING_HIERARCHIC)) {
764 final boolean compactEdgeLabelPlacement = options.getBool(ITEM_COMPACT_EDGE_LABEL_PLACEMENT);
765 if (hierarchic.getNodePlacer() instanceof SimplexNodePlacer) {
766 ((SimplexNodePlacer) hierarchic.getNodePlacer()).setLabelCompactionEnabled(compactEdgeLabelPlacement);
767 }
768 hierarchic.setIntegratedEdgeLabelingEnabled(true);
769 }
770 } else {
771 hierarchic.setIntegratedEdgeLabelingEnabled(false);
772 }
773 }
774
775 private void setupEdgeLabelModel(final Graph2D graph, final String edgeLabeling, String edgeLabelModel) {
776 if (edgeLabeling.equals(VALUE_EDGE_LABELING_NONE) || edgeLabelModel.equals(VALUE_EDGE_LABEL_MODEL_AS_IS)) {
777 return; }
779
780 if (edgeLabelModel.equals(VALUE_EDGE_LABEL_MODEL_BEST)) {
781 if (edgeLabeling.equals(VALUE_EDGE_LABELING_GENERIC)) {
782 edgeLabelModel = VALUE_EDGE_LABEL_MODEL_SIDE_SLIDER;
783 } else if (edgeLabeling.equals(VALUE_EDGE_LABELING_HIERARCHIC)) {
784 edgeLabelModel = VALUE_EDGE_LABEL_MODEL_FREE;
785 }
786 }
787
788 byte model = EdgeLabel.SIDE_SLIDER;
789 byte preferredSide = LabelLayoutConstants.PLACE_RIGHT_OF_EDGE;
790 if (edgeLabelModel.equals(VALUE_EDGE_LABEL_MODEL_CENTER_SLIDER)) {
791 model = EdgeLabel.CENTER_SLIDER;
792 preferredSide = LabelLayoutConstants.PLACE_ON_EDGE;
793 } else if (edgeLabelModel.equals(VALUE_EDGE_LABEL_MODEL_FREE)) {
794 model = EdgeLabel.FREE;
795 preferredSide = LabelLayoutConstants.PLACE_ON_EDGE;
796 }
797
798 assignLabelModel(graph, model, preferredSide, !edgeLabelModel.equals(VALUE_EDGE_LABEL_MODEL_FREE));
799 }
800
801 private void assignLabelModel(
802 final Graph2D graph,
803 final byte model,
804 final byte preferredSide,
805 final boolean setPreferredSize
806 ) {
807 for (EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
808 final Edge e = ec.edge();
809 EdgeRealizer er = graph.getRealizer(e);
810 for (int i = 0; i < er.labelCount(); i++) {
811 final EdgeLabel el = er.getLabel(i);
812 el.setModel(model);
813 if (setPreferredSize) {
814 setPreferredSide(el, preferredSide);
815 }
816 }
817 }
818 }
819
820
821 private void setPreferredSide(final EdgeLabel el, final byte preferredSide) {
822 final PreferredPlacementDescriptor oldDescriptor =
823 el.getPreferredPlacementDescriptor();
824 if (oldDescriptor.getSideOfEdge() != preferredSide) {
825 final PreferredPlacementDescriptor newDescriptor =
826 new PreferredPlacementDescriptor(oldDescriptor);
827 newDescriptor.setSideOfEdge(preferredSide);
828 el.setPreferredPlacementDescriptor(newDescriptor);
829 }
830 }
831
832
833 private static final class EdgeDirectednessProvider extends DataProviderAdapter {
834 final Graph2D graph;
835
836 EdgeDirectednessProvider(final Graph2D graph) {
837 this.graph = graph;
838 }
839
840 public double getDouble(final Object dataHolder) {
841 try {
842 final EdgeRealizer realizer = graph.getRealizer((Edge) dataHolder);
843 if (realizer.getSourceArrow() == Arrow.NONE && realizer.getTargetArrow() != Arrow.NONE) {
844 return 1;
846 } else if (realizer.getTargetArrow() == Arrow.NONE && realizer.getSourceArrow() != Arrow.NONE) {
847 return -1;
849 } else {
850 return 0;
852 }
853 } catch (Exception e) {
854 return 1;
856 }
857 }
858 }
859
860 private static final class EdgeWidthProvider extends DataProviderAdapter {
861 final Graph2D graph;
862
863 EdgeWidthProvider( final Graph2D graph ) {
864 this.graph = graph;
865 }
866
867 public double getDouble( final Object dataHolder ) {
868 try {
869 final EdgeRealizer er = graph.getRealizer((Edge) dataHolder);
870 return er.getLineType().getLineWidth();
871 } catch (Exception e) {
872 return 0;
873 }
874 }
875 }
876 }
877