1
14 package demo.view.flowchart.painters;
15
16 import demo.view.flowchart.layout.FlowchartElements;
17 import demo.view.flowchart.layout.FlowchartLayouter;
18 import y.base.DataMap;
19 import y.base.Edge;
20 import y.base.EdgeCursor;
21 import y.base.EdgeMap;
22 import y.base.Node;
23 import y.base.NodeCursor;
24 import y.base.NodeMap;
25 import y.layout.IntersectionCalculator;
26 import y.util.Maps;
27 import y.view.EdgeRealizer;
28 import y.view.GenericNodeRealizer;
29 import y.view.Graph2D;
30 import y.view.NodeRealizer;
31 import y.view.NodeRealizerIntersectionCalculator;
32 import y.view.YLabel;
33 import y.view.hierarchy.GroupNodeRealizer;
34 import y.view.tabular.TableGroupNodeRealizer;
35
36 import java.util.Collection;
37 import java.util.HashSet;
38
39
44 public class FlowchartLayoutConfigurator {
45 private final Collection nodeActivityElements;
46 private final Collection nodeAnnotationElements;
47 private final Collection nodeDataElements;
48 private final Collection nodeEndElements;
49 private final Collection nodeEventElements;
50 private final Collection nodeGatewayElements;
51 private final Collection nodeReferenceElements;
52 private final Collection nodeStartElements;
53
54 private boolean portIntersectionDataProviderCreationEnabled;
55 private int preferredPositiveBranchDirection;
56 private int preferredNegativeBranchDirection;
57 private int adjustedPositiveBranchDirection;
58 private int adjustedNegativeBranchDirection;
59 private String negativeBranchLabel;
60 private String positiveBranchLabel;
61
62
65 public FlowchartLayoutConfigurator() {
66 portIntersectionDataProviderCreationEnabled = false;
67 setPositiveBranchLabel("Yes");
68 setNegativeBranchLabel("No");
69 setPreferredPositiveBranchDirection(FlowchartLayouter.DIRECTION_WITH_THE_FLOW);
70 setPreferredNegativeBranchDirection(FlowchartLayouter.DIRECTION_FLATWISE);
71
72 nodeActivityElements = new HashSet();
73 nodeActivityElements.add(FlowchartRealizerConstants.FLOWCHART_PROCESS_CONFIG_NAME);
74 nodeActivityElements.add(FlowchartRealizerConstants.FLOWCHART_PREDEFINED_PROCESS_CONFIG_NAME);
75 nodeActivityElements.add(FlowchartRealizerConstants.FLOWCHART_LOOP_LIMIT_CONFIG_NAME);
76 nodeActivityElements.add(FlowchartRealizerConstants.FLOWCHART_LOOP_LIMIT_END_CONFIG_NAME);
77
78 nodeAnnotationElements = new HashSet();
79 nodeAnnotationElements.add(FlowchartRealizerConstants.FLOWCHART_ANNOTATION_CONFIG_NAME);
80
81 nodeDataElements = new HashSet();
82 nodeDataElements.add(FlowchartRealizerConstants.FLOWCHART_CARD_CONFIG_NAME);
83 nodeDataElements.add(FlowchartRealizerConstants.FLOWCHART_CLOUD_TYPE_CONFIG_NAME);
84 nodeDataElements.add(FlowchartRealizerConstants.FLOWCHART_DATA_CONFIG_NAME);
85 nodeDataElements.add(FlowchartRealizerConstants.FLOWCHART_DATABASE_CONFIG_NAME);
86 nodeDataElements.add(FlowchartRealizerConstants.FLOWCHART_DIRECT_DATA_CONFIG_NAME);
87 nodeDataElements.add(FlowchartRealizerConstants.FLOWCHART_DOCUMENT_CONFIG_NAME);
88 nodeDataElements.add(FlowchartRealizerConstants.FLOWCHART_INTERNAL_STORAGE_CONFIG_NAME);
89 nodeDataElements.add(FlowchartRealizerConstants.FLOWCHART_MANUAL_INPUT_CONFIG_NAME);
90 nodeDataElements.add(FlowchartRealizerConstants.FLOWCHART_PAPER_TYPE_CONFIG_NAME);
91 nodeDataElements.add(FlowchartRealizerConstants.FLOWCHART_STORED_DATA_CONFIG_NAME);
92 nodeDataElements.add(FlowchartRealizerConstants.FLOWCHART_SEQUENTIAL_DATA_CONFIG_NAME);
93
94 nodeGatewayElements = new HashSet();
95 nodeGatewayElements.add(FlowchartRealizerConstants.FLOWCHART_DECISION_CONFIG_NAME);
96
97 nodeEndElements = new HashSet();
98 nodeEndElements.add(FlowchartRealizerConstants.FLOWCHART_TERMINATOR_CONFIG_NAME);
99
100 nodeEventElements = new HashSet();
101 nodeEventElements.add(FlowchartRealizerConstants.FLOWCHART_DELAY_CONFIG_NAME);
102 nodeEventElements.add(FlowchartRealizerConstants.FLOWCHART_DISPLAY_CONFIG_NAME);
103 nodeEventElements.add(FlowchartRealizerConstants.FLOWCHART_MANUAL_OPERATION_CONFIG_NAME);
104 nodeEventElements.add(FlowchartRealizerConstants.FLOWCHART_PREPARATION_CONFIG_NAME);
105
106 nodeReferenceElements = new HashSet();
107 nodeReferenceElements.add(FlowchartRealizerConstants.FLOWCHART_ON_PAGE_REFERENCE_CONFIG_NAME);
108 nodeReferenceElements.add(FlowchartRealizerConstants.FLOWCHART_OFF_PAGE_REFERENCE_CONFIG_NAME);
109
110 nodeStartElements = new HashSet();
111 nodeStartElements.add(FlowchartRealizerConstants.FLOWCHART_START1_CONFIG_NAME);
112 nodeStartElements.add(FlowchartRealizerConstants.FLOWCHART_START2_CONFIG_NAME);
113 }
114
115
120 public String getNegativeBranchLabel() {
121 return negativeBranchLabel;
122 }
123
124
129 public void setNegativeBranchLabel(String label) {
130 this.negativeBranchLabel = label;
131 }
132
133
138
139 public String getPositiveBranchLabel() {
140 return positiveBranchLabel;
141 }
142
143
148 public void setPositiveBranchLabel(String label) {
149 this.positiveBranchLabel = label;
150 }
151
152
157 public int getPreferredNegativeBranchDirection() {
158 return preferredNegativeBranchDirection;
159 }
160
161
166 public void setPreferredNegativeBranchDirection(int direction) {
167 preferredNegativeBranchDirection = direction;
168 adjustedPositiveBranchDirection = calculateAdjustedPositiveBranchDirection();
169 adjustedNegativeBranchDirection = calculateAdjustedNegativeBranchDirection();
170 }
171
172
177 public int getPreferredPositiveBranchDirection() {
178 return preferredPositiveBranchDirection;
179 }
180
181
186 public void setPreferredPositiveBranchDirection(int direction) {
187 preferredPositiveBranchDirection = direction;
188 adjustedPositiveBranchDirection = calculateAdjustedPositiveBranchDirection();
189 adjustedNegativeBranchDirection = calculateAdjustedNegativeBranchDirection();
190 }
191
192
198 protected int getAdjustedNegativeBranchDirection() {
199 return adjustedNegativeBranchDirection;
200 }
201
202
208 protected int getAdjustedPositiveBranchDirection() {
209 return adjustedPositiveBranchDirection;
210 }
211
212
218 public boolean isPortIntersectionDataProviderCreationEnabled() {
219 return portIntersectionDataProviderCreationEnabled;
220 }
221
222
227 public void setPortIntersectionDataProviderCreationEnabled(boolean enabled) {
228 this.portIntersectionDataProviderCreationEnabled = enabled;
229 }
230
231
236 public void prepareAll(final Graph2D graph) {
237 if (portIntersectionDataProviderCreationEnabled) {
238 graph.addDataProvider(IntersectionCalculator.SOURCE_INTERSECTION_CALCULATOR_DPKEY,
239 new NodeRealizerIntersectionCalculator(graph, true));
240 graph.addDataProvider(IntersectionCalculator.TARGET_INTERSECTION_CALCULATOR_DPKEY,
241 new NodeRealizerIntersectionCalculator(graph, false));
242 }
243
244 final DataMap branchMap = Maps.createHashedDataMap();
245 graph.addDataProvider(FlowchartLayouter.PREFERRED_DIRECTION_KEY, branchMap);
246
247 final NodeMap nodeTypeMap = Maps.createHashedNodeMap();
248 graph.addDataProvider(FlowchartLayouter.NODE_TYPE_DPKEY, nodeTypeMap);
249
250 for (NodeCursor nc = graph.nodes(); nc.ok(); nc.next()) {
251 final Node node = nc.node();
252 nodeTypeMap.setInt(node, (int) getType(graph.getRealizer(node)));
253 }
254
255 final EdgeMap edgeTypeMap = Maps.createHashedEdgeMap();
256 graph.addDataProvider(FlowchartLayouter.EDGE_TYPE_DPKEY, edgeTypeMap);
257
258 for (EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
259 final Edge edge = ec.edge();
260 final EdgeRealizer realizer = graph.getRealizer(edge);
261
262 edgeTypeMap.setInt(edge, (int) getType(realizer));
263 branchMap.setInt(edge, getBranchType(realizer));
264 }
265 }
266
267
272 public void restoreAll(final Graph2D graph) {
273 if (portIntersectionDataProviderCreationEnabled) {
274 graph.removeDataProvider(IntersectionCalculator.SOURCE_INTERSECTION_CALCULATOR_DPKEY);
275 graph.removeDataProvider(IntersectionCalculator.TARGET_INTERSECTION_CALCULATOR_DPKEY);
276 }
277 graph.removeDataProvider(FlowchartLayouter.NODE_TYPE_DPKEY);
278 graph.removeDataProvider(FlowchartLayouter.EDGE_TYPE_DPKEY);
279 graph.removeDataProvider(FlowchartLayouter.PREFERRED_DIRECTION_KEY);
280 }
281
282
287 protected byte getType(EdgeRealizer realizer) {
288 final NodeRealizer sourceRealizer = realizer.getSourceRealizer();
289 final NodeRealizer targetRealizer = realizer.getTargetRealizer();
290 if (sourceRealizer != null && getType(sourceRealizer) == FlowchartElements.NODE_TYPE_ANNOTATION
291 || targetRealizer != null && getType(targetRealizer) == FlowchartElements.NODE_TYPE_ANNOTATION) {
292 return FlowchartElements.EDGE_TYPE_MESSAGE_FLOW;
293 } else {
294 return FlowchartElements.EDGE_TYPE_SEQUENCE_FLOW;
295 }
296 }
297
298
303 protected byte getType(NodeRealizer realizer) {
304 if (realizer instanceof TableGroupNodeRealizer) {
305 return FlowchartElements.NODE_TYPE_POOL;
306 } else if (realizer instanceof GroupNodeRealizer) {
307 return FlowchartElements.NODE_TYPE_GROUP;
308 } else if (realizer instanceof GenericNodeRealizer) {
309 final String configuration = ((GenericNodeRealizer) realizer).getConfiguration();
310 if (nodeActivityElements.contains(configuration)) {
311 return FlowchartElements.NODE_TYPE_PROCESS;
312 } else if (nodeDataElements.contains(configuration)) {
313 return FlowchartElements.NODE_TYPE_DATA;
314 } else if (nodeAnnotationElements.contains(configuration)) {
315 return FlowchartElements.NODE_TYPE_ANNOTATION;
316 } else if (nodeGatewayElements.contains(configuration)) {
317 return FlowchartElements.NODE_TYPE_DECISION;
318 } else if (nodeEndElements.contains(configuration)) {
319 return FlowchartElements.NODE_TYPE_END_EVENT;
320 } else if (nodeEventElements.contains(configuration)) {
321 return FlowchartElements.NODE_TYPE_EVENT;
322 } else if (nodeReferenceElements.contains(configuration)) {
323 return FlowchartElements.NODE_TYPE_PROCESS;
324 } else if (nodeStartElements.contains(configuration)) {
325 return FlowchartElements.NODE_TYPE_START_EVENT;
326 }
327 }
328
329 return FlowchartElements.TYPE_INVALID;
330 }
331
332
337 protected int getBranchType(EdgeRealizer realizer) {
338 if (isPositiveBranch(realizer)) {
339 return getAdjustedPositiveBranchDirection();
340 } else if (isNegativeBranch(realizer)) {
341 return getAdjustedNegativeBranchDirection();
342 } else {
343 return FlowchartLayouter.DIRECTION_UNDEFINED;
344 }
345 }
346
347
354 protected boolean isPositiveBranch(EdgeRealizer realizer) {
355 return (int) getType(realizer.getSourceRealizer()) == (int) FlowchartElements.NODE_TYPE_DECISION
356 && realizer.labelCount() > 0 && isMatchingLabelText(realizer.getLabel(0), positiveBranchLabel);
357 }
358
359
366 protected boolean isNegativeBranch(EdgeRealizer realizer) {
367 return (int) getType(realizer.getSourceRealizer()) == (int) FlowchartElements.NODE_TYPE_DECISION
368 && realizer.labelCount() > 0 && isMatchingLabelText(realizer.getLabel(0), negativeBranchLabel);
369 }
370
371
374 private static boolean isMatchingLabelText(YLabel label, String text) {
375 final String labelText = label != null ? label.getText() : null;
376 return labelText != null && labelText.equalsIgnoreCase(text);
377 }
378
379
383 private int calculateAdjustedNegativeBranchDirection() {
384 final int positiveDir = getAdjustedPositiveBranchDirection();
385 final int negativeDir = preferredNegativeBranchDirection;
386
387 switch (negativeDir) {
388 case FlowchartLayouter.DIRECTION_STRAIGHT:
389 return positiveDir != FlowchartLayouter.DIRECTION_WITH_THE_FLOW ?
390 FlowchartLayouter.DIRECTION_WITH_THE_FLOW : FlowchartLayouter.DIRECTION_FLATWISE;
391
392 case FlowchartLayouter.DIRECTION_FLATWISE:
393 if (positiveDir == FlowchartLayouter.DIRECTION_RIGHT_IN_FLOW) {
394 return FlowchartLayouter.DIRECTION_LEFT_IN_FLOW;
395 } else if (positiveDir == FlowchartLayouter.DIRECTION_LEFT_IN_FLOW) {
396 return FlowchartLayouter.DIRECTION_RIGHT_IN_FLOW;
397 } else {
398 return negativeDir;
399 }
400
401 default:
402 case FlowchartLayouter.DIRECTION_AGAINST_THE_FLOW:
403 return FlowchartLayouter.DIRECTION_UNDEFINED;
404
405 case FlowchartLayouter.DIRECTION_WITH_THE_FLOW:
406 return positiveDir != negativeDir ? negativeDir : FlowchartLayouter.DIRECTION_FLATWISE;
407
408 case FlowchartLayouter.DIRECTION_LEFT_IN_FLOW:
409 return positiveDir != negativeDir ? negativeDir : FlowchartLayouter.DIRECTION_RIGHT_IN_FLOW;
410
411 case FlowchartLayouter.DIRECTION_RIGHT_IN_FLOW:
412 return positiveDir != negativeDir ? negativeDir : FlowchartLayouter.DIRECTION_LEFT_IN_FLOW;
413 }
414 }
415
416
420 private int calculateAdjustedPositiveBranchDirection() {
421 switch (preferredPositiveBranchDirection) {
422 case FlowchartLayouter.DIRECTION_STRAIGHT:
423 return FlowchartLayouter.DIRECTION_WITH_THE_FLOW;
424 case FlowchartLayouter.DIRECTION_AGAINST_THE_FLOW:
425 return FlowchartLayouter.DIRECTION_UNDEFINED;
426 case FlowchartLayouter.DIRECTION_FLATWISE:
427 if (preferredNegativeBranchDirection == FlowchartLayouter.DIRECTION_RIGHT_IN_FLOW) {
428 return FlowchartLayouter.DIRECTION_LEFT_IN_FLOW;
429 } else if (preferredNegativeBranchDirection == FlowchartLayouter.DIRECTION_LEFT_IN_FLOW) {
430 return FlowchartLayouter.DIRECTION_RIGHT_IN_FLOW;
431 } else {
432 return preferredPositiveBranchDirection;
433 }
434 default:
435 return preferredPositiveBranchDirection;
436 }
437 }
438
439 }
440