1
28 package demo.layout.labeling;
29
30 import y.base.Edge;
31 import y.base.EdgeCursor;
32 import y.base.YCursor;
33 import y.layout.LabelLayoutConstants;
34 import y.layout.PreferredPlacementDescriptor;
35 import y.option.MappedListCellRenderer;
36 import y.option.OptionHandler;
37 import y.view.EdgeLabel;
38 import y.view.EdgeRealizer;
39 import y.view.Graph2D;
40 import y.view.YLabel;
41
42 import java.util.ArrayList;
43 import java.util.Iterator;
44 import java.util.LinkedHashMap;
45 import java.util.List;
46 import java.util.Map;
47
48
51 public class PreferredPlacementOptionHandler extends OptionHandler {
52 private static final String EDGE_LABEL_PROPERTIES = "Edge Label Properties";
53 private static final String ITEM_TEXT = "Text";
54 private static final String ITEM_PLACEMENT = "Placement Along the Edge";
55 private static final String ITEM_SIDE = "Side of the Edge";
56 private static final String ITEM_SIDE_REFERENCE = "Side Reference";
57 private static final String ITEM_ANGLE = "Angle (in Degrees)";
58 private static final String ITEM_ANGLE_REFERENCE = "Angle Reference";
59 private static final String ITEM_ANGLE_ROTATION_ON_RIGHT_SIDE = "Angle Rotation on Right Side";
60 private static final String ITEM_ANGLE_OFFSET_ON_RIGHT_SIDE = "Add 180\u00b0 on Right Side";
62 private static final String ITEM_DISTANCE_TO_EDGE = "Distance to Edge";
63
64 private static final Byte DEFAULT_PLACE = new Byte(
65 (byte) LabelLayoutConstants.PLACE_ANYWHERE);
66 private static final Byte DEFAULT_SIDE = new Byte(
67 (byte) LabelLayoutConstants.PLACE_ANYWHERE);
68 private static final Byte DEFAULT_SIDE_REFERENCE = new Byte(
69 (byte) (PreferredPlacementDescriptor.SIDE_IS_RELATIVE_TO_EDGE_FLOW |
70 PreferredPlacementDescriptor.SIDE_IS_ABSOLUTE_WITH_LEFT_IN_NORTH |
71 PreferredPlacementDescriptor.SIDE_IS_ABSOLUTE_WITH_RIGHT_IN_NORTH));
72 private static final Byte DEFAULT_ANGLE_REFERENCE = new Byte(
73 (byte) (PreferredPlacementDescriptor.ANGLE_IS_ABSOLUTE |
74 PreferredPlacementDescriptor.ANGLE_IS_RELATIVE_TO_EDGE_FLOW));
75 private static final Byte DEFAULT_ANGLE_ROTATION_ON_RIGHT_SIDE = new Byte(
76 (byte) (PreferredPlacementDescriptor.ANGLE_ON_RIGHT_SIDE_CO_ROTATING |
77 PreferredPlacementDescriptor.ANGLE_ON_RIGHT_SIDE_COUNTER_ROTATING));
78 private static final Double DEFAULT_ANGLE = new Double(0);
79 private static final Double DEFAULT_DISTANCE_TO_EDGE = new Double(0);
80 private static final Boolean DEFAULT_ANGLE_OFFSET_ON_RIGHT_SIDE = Boolean.FALSE;
81
82
85 public PreferredPlacementOptionHandler() {
86 super(EDGE_LABEL_PROPERTIES);
87
88 addString(ITEM_TEXT, "", 2);
89
90 final Map placementMap = createPlacementsToStringMap();
91 addEnum(
92 ITEM_PLACEMENT,
93 placementMap.keySet().toArray(),
94 DEFAULT_PLACE,
95 new MappedListCellRenderer(placementMap));
96
97 final Map sideMap = createSidesToStringMap();
98 addEnum(
99 ITEM_SIDE,
100 sideMap.keySet().toArray(),
101 DEFAULT_SIDE,
102 new MappedListCellRenderer(sideMap));
103
104 final Map sideInterpretationMap = createSideReferencesToStringMap();
105 addEnum(
106 ITEM_SIDE_REFERENCE,
107 sideInterpretationMap.keySet().toArray(),
108 DEFAULT_SIDE_REFERENCE,
109 new MappedListCellRenderer(sideInterpretationMap));
110
111 addDouble(ITEM_ANGLE, DEFAULT_ANGLE.doubleValue());
112
113 final Map angleReferenceMap = createAngleReferencesToStringMap();
114 addEnum(
115 ITEM_ANGLE_REFERENCE,
116 angleReferenceMap.keySet().toArray(),
117 DEFAULT_ANGLE_REFERENCE,
118 new MappedListCellRenderer(angleReferenceMap));
119
120 final Map angleRotationOnRightSideMap = createAngleRotationsOnRightSideToStringMap();
121 addEnum(
122 ITEM_ANGLE_ROTATION_ON_RIGHT_SIDE,
123 angleRotationOnRightSideMap.keySet().toArray(),
124 DEFAULT_ANGLE_ROTATION_ON_RIGHT_SIDE,
125 new MappedListCellRenderer(angleRotationOnRightSideMap));
126
127 addBool(ITEM_ANGLE_OFFSET_ON_RIGHT_SIDE, DEFAULT_ANGLE_OFFSET_ON_RIGHT_SIDE.booleanValue());
128
129 addDouble(ITEM_DISTANCE_TO_EDGE, DEFAULT_DISTANCE_TO_EDGE.doubleValue());
130 }
131
132
137 public void updateValues(final Graph2D graph) {
138 final Iterator labelIterator = getEdgeLabels(graph).iterator();
139 if (!labelIterator.hasNext()) {
140 return;
141 }
142
143 EdgeLabel edgeLabel = (EdgeLabel) labelIterator.next();
144 PreferredPlacementDescriptor descriptor = edgeLabel.getPreferredPlacementDescriptor();
145
146 final String text = edgeLabel.getText();
148 boolean sameTexts = true;
149 final byte placement = descriptor.getPlaceAlongEdge();
150 boolean samePlacements = true;
151 final byte side = descriptor.getSideOfEdge();
152 boolean sameSides = true;
153 final byte sideReference = descriptor.getSideReference();
154 boolean sameSideReferences = true;
155 final double angle = descriptor.getAngle();
156 boolean sameAngles = true;
157 final byte angleReference = descriptor.getAngleReference();
158 boolean sameAngleReferences = true;
159 final byte angleRotationOnRightSide = descriptor.getAngleRotationOnRightSide();
160 boolean sameAngleRotations = true;
161 final boolean hasAngleOffset = descriptor.isAngleOffsetOnRightSide180();
162 boolean sameAngleOffsets = true;
163 final double distance = descriptor.getDistanceToEdge();
164 boolean sameDistances = true;
165
166 while (labelIterator.hasNext()) {
168 edgeLabel = (EdgeLabel) labelIterator.next();
169 descriptor = edgeLabel.getPreferredPlacementDescriptor();
170
171 if (sameTexts && !text.equals(edgeLabel.getText())) {
172 sameTexts = false;
173 }
174 if (samePlacements && placement != descriptor.getPlaceAlongEdge()) {
175 samePlacements = false;
176 }
177 if (sameSides && side != descriptor.getSideOfEdge()) {
178 sameSides = false;
179 }
180 if (sameSideReferences && sideReference != descriptor.getSideReference()) {
181 sameSideReferences = false;
182 }
183 if (sameAngles && Double.compare(angle, descriptor.getAngle()) != 0) {
184 sameAngles = false;
185 }
186 if (sameAngleReferences &&
187 angleReference != descriptor.getAngleReference()) {
188 sameAngleReferences = false;
189 }
190 if (sameAngleRotations &&
191 angleRotationOnRightSide != descriptor.getAngleRotationOnRightSide()) {
192 sameAngleRotations = false;
193 }
194 if (sameAngleOffsets && hasAngleOffset != descriptor.isAngleOffsetOnRightSide180()) {
195 sameAngleOffsets = false;
196 }
197 if (sameDistances && Double.compare(distance, descriptor.getDistanceToEdge()) != 0) {
198 sameDistances = false;
199 }
200
201 if (!(sameTexts | samePlacements | sameSides | sameSideReferences | sameAngles | sameAngleReferences
202 | sameAngleRotations | sameDistances)) {
203 break;
204 }
205 }
206
207 set(ITEM_TEXT, sameTexts ? text : null);
211 getItem(ITEM_TEXT).setValueUndefined(!sameTexts);
212
213 set(ITEM_PLACEMENT, samePlacements ? new Byte(placement) : DEFAULT_PLACE);
214 getItem(ITEM_PLACEMENT).setValueUndefined(!samePlacements);
215
216 set(ITEM_SIDE, sameSides ? new Byte(side) : DEFAULT_SIDE);
217 getItem(ITEM_SIDE).setValueUndefined(!sameSides);
218
219 set(ITEM_SIDE_REFERENCE, sameSideReferences ? new Byte(sideReference) : DEFAULT_SIDE_REFERENCE);
220 getItem(ITEM_SIDE_REFERENCE).setValueUndefined(!sameSideReferences);
221
222 set(ITEM_ANGLE, sameAngles ? new Double(Math.toDegrees(angle)) : new Double(-1));
223 getItem(ITEM_ANGLE).setValueUndefined(!sameAngles);
224
225 set(ITEM_ANGLE_REFERENCE, sameAngleReferences ? new Byte(angleReference) : DEFAULT_ANGLE_REFERENCE);
226 getItem(ITEM_ANGLE_REFERENCE).setValueUndefined(!sameAngleReferences);
227
228 set(ITEM_ANGLE_ROTATION_ON_RIGHT_SIDE, sameAngleRotations ? new Byte(angleRotationOnRightSide) :
229 DEFAULT_ANGLE_ROTATION_ON_RIGHT_SIDE);
230 getItem(ITEM_ANGLE_ROTATION_ON_RIGHT_SIDE).setValueUndefined(!sameAngleRotations);
231
232 set(ITEM_ANGLE_OFFSET_ON_RIGHT_SIDE, sameAngleOffsets ? hasAngleOffset ? Boolean.TRUE : Boolean.FALSE :
233 DEFAULT_ANGLE_OFFSET_ON_RIGHT_SIDE);
234 getItem(ITEM_ANGLE_ROTATION_ON_RIGHT_SIDE).setValueUndefined(!sameAngleOffsets);
235
236 set(ITEM_DISTANCE_TO_EDGE, sameDistances ? new Double(distance) : new Double(-1));
237 getItem(ITEM_DISTANCE_TO_EDGE).setValueUndefined(!sameDistances);
238 }
239
240
245 public void commitValues(final Graph2D graph) {
246 for (Iterator labelIterator = getEdgeLabels(graph).iterator(); labelIterator.hasNext(); ) {
247 final EdgeLabel edgeLabel = (EdgeLabel) labelIterator.next();
248 final PreferredPlacementDescriptor prototype =
249 edgeLabel.getPreferredPlacementDescriptor();
250
251 final PreferredPlacementDescriptor descriptor =
252 new PreferredPlacementDescriptor(prototype);
253 if (!getItem(ITEM_TEXT).isValueUndefined()) {
254 edgeLabel.setText(getString(ITEM_TEXT));
255 }
256 if (!getItem(ITEM_PLACEMENT).isValueUndefined()) {
257 descriptor.setPlaceAlongEdge(((Byte) get(ITEM_PLACEMENT)).byteValue());
258 }
259 if (!getItem(ITEM_SIDE).isValueUndefined()) {
260 descriptor.setSideOfEdge(((Byte) get(ITEM_SIDE)).byteValue());
261 }
262 if (!getItem(ITEM_SIDE_REFERENCE).isValueUndefined()) {
263 descriptor.setSideReference(((Byte) get(ITEM_SIDE_REFERENCE)).byteValue());
264 }
265 if (!getItem(ITEM_ANGLE).isValueUndefined()) {
266 descriptor.setAngle(Math.toRadians(getDouble(ITEM_ANGLE)));
267 }
268 if (!getItem(ITEM_ANGLE_REFERENCE).isValueUndefined()) {
269 descriptor.setAngleReference(((Byte) get(ITEM_ANGLE_REFERENCE)).byteValue());
270 }
271 if (!getItem(ITEM_ANGLE_ROTATION_ON_RIGHT_SIDE).isValueUndefined()) {
272 descriptor.setAngleRotationOnRightSide(((Byte) get(ITEM_ANGLE_ROTATION_ON_RIGHT_SIDE)).byteValue());
273 }
274 if (!getItem(ITEM_ANGLE_OFFSET_ON_RIGHT_SIDE).isValueUndefined()) {
275 final byte angleOffset = getBool(ITEM_ANGLE_OFFSET_ON_RIGHT_SIDE) ?
276 PreferredPlacementDescriptor.ANGLE_OFFSET_ON_RIGHT_SIDE_180 :
277 PreferredPlacementDescriptor.ANGLE_OFFSET_ON_RIGHT_SIDE_0;
278 descriptor.setAngleOffsetOnRightSide(angleOffset);
279 }
280 if (!getItem(ITEM_DISTANCE_TO_EDGE).isValueUndefined()) {
281 descriptor.setDistanceToEdge(getDouble(ITEM_DISTANCE_TO_EDGE));
282 }
283
284 if (!descriptor.equals(prototype)) {
285 edgeLabel.setPreferredPlacementDescriptor(descriptor);
286 }
287 }
288 }
289
290
297 private List getEdgeLabels(final Graph2D graph) {
298 List labels = getSelectedEdgeLabels(graph);
299 if (labels.isEmpty()) {
300 labels = getAllEdgeLabels(graph);
301 }
302 return labels;
303 }
304
305
311 private List getSelectedEdgeLabels(final Graph2D graph) {
312 final List selectedEdgeLabels = new ArrayList();
313 for (YCursor selectedLabels = graph.selectedLabels(); selectedLabels.ok(); selectedLabels.next()) {
314 final YLabel selectedLabel = (YLabel) selectedLabels.current();
315 if (selectedLabel instanceof EdgeLabel) {
316 selectedEdgeLabels.add(selectedLabel);
317 }
318 }
319 return selectedEdgeLabels;
320 }
321
322
328 private List getAllEdgeLabels(final Graph2D graph) {
329 final List result = new ArrayList();
330 for (EdgeCursor edgeCursor = graph.edges(); edgeCursor.ok(); edgeCursor.next()) {
331 final Edge edge = edgeCursor.edge();
332 final EdgeRealizer edgeRealizer = graph.getRealizer(edge);
333 for (int i = 0, n = edgeRealizer.labelCount(); i < n; i++) {
334 final EdgeLabel edgeLabel = edgeRealizer.getLabel(i);
335 result.add(edgeLabel);
336 }
337 }
338 return result;
339 }
340
341
344 private static Map createPlacementsToStringMap() {
345 final Map result = new LinkedHashMap(6);
346 result.put(new Byte(LabelLayoutConstants.PLACE_AT_SOURCE), "At Source");
347 result.put(new Byte(LabelLayoutConstants.PLACE_AT_CENTER), "At Center");
348 result.put(new Byte(LabelLayoutConstants.PLACE_AT_TARGET), "At Target");
349 result.put(new Byte(LabelLayoutConstants.PLACE_AT_SOURCE_PORT), "At Source Port");
350 result.put(new Byte(LabelLayoutConstants.PLACE_AT_TARGET_PORT), "At Target Port");
351 result.put(DEFAULT_PLACE, "Anywhere");
352 return result;
353 }
354
355
358 private static Map createSidesToStringMap() {
359 final Map result = new LinkedHashMap(4);
360 result.put(new Byte(LabelLayoutConstants.PLACE_LEFT_OF_EDGE), "Left Of Edge");
361 result.put(new Byte(LabelLayoutConstants.PLACE_ON_EDGE), "On Edge");
362 result.put(new Byte(LabelLayoutConstants.PLACE_RIGHT_OF_EDGE), "Right Of Edge");
363 result.put(DEFAULT_SIDE, "Any side");
364 return result;
365 }
366
367
370 private static Map createSideReferencesToStringMap() {
371 final Map result = new LinkedHashMap(3);
372 result.put(new Byte(PreferredPlacementDescriptor.SIDE_IS_RELATIVE_TO_EDGE_FLOW), "Relative to edge flow");
373 result.put(new Byte(PreferredPlacementDescriptor.SIDE_IS_ABSOLUTE_WITH_LEFT_IN_NORTH), "Absolute with left in north");
374 result.put(new Byte(PreferredPlacementDescriptor.SIDE_IS_ABSOLUTE_WITH_RIGHT_IN_NORTH), "Absolute with right in north");
375 return result;
376 }
377
378
381 private static Map createAngleReferencesToStringMap() {
382 final Map result = new LinkedHashMap(2);
383 result.put(new Byte(PreferredPlacementDescriptor.ANGLE_IS_ABSOLUTE), "Absolute");
384 result.put(new Byte(PreferredPlacementDescriptor.ANGLE_IS_RELATIVE_TO_EDGE_FLOW), "Relative to edge");
385 return result;
386 }
387
388
391 private static Map createAngleRotationsOnRightSideToStringMap() {
392 final Map result = new LinkedHashMap(2);
393 result.put(new Byte(PreferredPlacementDescriptor.ANGLE_ON_RIGHT_SIDE_CO_ROTATING), "Co-rotating");
394 result.put(new Byte(PreferredPlacementDescriptor.ANGLE_ON_RIGHT_SIDE_COUNTER_ROTATING), "Counter-rotating");
395 return result;
396 }
397 }
398