1
28 package demo.view.isometry;
29
30 import y.base.DataProvider;
31 import y.base.Edge;
32 import y.base.EdgeCursor;
33 import y.base.EdgeMap;
34 import y.base.Node;
35 import y.base.NodeCursor;
36 import y.geom.OrientedRectangle;
37 import y.geom.YDimension;
38 import y.geom.YInsets;
39 import y.geom.YPoint;
40 import y.layout.AbstractLayoutStage;
41 import y.layout.EdgeLabelLayout;
42 import y.layout.EdgeLayout;
43 import y.layout.LabelLayoutData;
44 import y.layout.LayoutGraph;
45 import y.layout.Layouter;
46 import y.layout.NodeLabelLayout;
47 import y.layout.NodeLayout;
48 import y.layout.grouping.GroupingKeys;
49 import y.util.DataProviderAdapter;
50 import y.util.Maps;
51
52 import java.awt.geom.Rectangle2D;
53
54
59 class IsometryTransformationLayoutStage extends AbstractLayoutStage {
60
61
65 public static final String TRANSFORMATION_DATA_DPKEY = "com.yworks.isometry.transformation_data_dpkey";
66
67 private static final int GROUP_NODE_INSET = 20;
68
69 private boolean fromSketchMode;
70
71 public IsometryTransformationLayoutStage(final Layouter coreLayouter) {
72 this(coreLayouter, false);
73 }
74
75 public IsometryTransformationLayoutStage(final Layouter coreLayouter, final boolean fromSketchMode) {
76 super(coreLayouter);
77 this.fromSketchMode = fromSketchMode;
78 }
79
80 public boolean canLayout(final LayoutGraph graph) {
81 return canLayoutCore(graph);
82 }
83
84
90 public void doLayout(final LayoutGraph graph) {
91 final DataProvider oldGroupNodeInsets = graph.getDataProvider(GroupingKeys.GROUP_NODE_INSETS_DPKEY);
95 graph.addDataProvider(
96 GroupingKeys.GROUP_NODE_INSETS_DPKEY, new DataProviderAdapter() {
97 public Object get(final Object dataHolder) {
98 double labelHeight = 0;
99 if (dataHolder instanceof Node) {
100 final Node node = (Node) dataHolder;
101 final NodeLabelLayout[] labels = graph.getNodeLabelLayout(node);
102 labelHeight = labels[0].getBox().getHeight();
103 }
104 return new YInsets(GROUP_NODE_INSET, GROUP_NODE_INSET, GROUP_NODE_INSET + labelHeight, GROUP_NODE_INSET);
105 }
106 });
107
108
112 final DataProvider oldMinimumNodeSizes = graph.getDataProvider(GroupingKeys.MINIMUM_NODE_SIZE_DPKEY);
113 graph.addDataProvider(GroupingKeys.MINIMUM_NODE_SIZE_DPKEY, new DataProviderAdapter() {
114 public Object get(Object dataHolder) {
115 if (dataHolder instanceof Node) {
116 Node node = (Node) dataHolder;
117 final NodeLabelLayout label = graph.getNodeLabelLayout(node)[0];
118 return new YDimension(
119 (int) label.getBox().getWidth() + IsometryGroupPainter.ICON_WIDTH + IsometryGroupPainter.ICON_GAP * 2, 0);
120 }
121 return null;
122 }
123 });
124
125 transformGraph(graph, false, isFromSketchMode());
127
128 doLayoutCore(graph);
130
131 transformGraph(graph, true, isFromSketchMode());
133
134 graph.removeDataProvider(GroupingKeys.GROUP_NODE_INSETS_DPKEY);
136 if (oldGroupNodeInsets != null) {
137 graph.addDataProvider(GroupingKeys.GROUP_NODE_INSETS_DPKEY, oldGroupNodeInsets);
138 }
139 graph.removeDataProvider(GroupingKeys.MINIMUM_NODE_SIZE_DPKEY);
140 if (oldMinimumNodeSizes != null) {
141 graph.addDataProvider(GroupingKeys.MINIMUM_NODE_SIZE_DPKEY, oldMinimumNodeSizes);
142 }
143 }
144
145
152 private static void transformGraph(final LayoutGraph graph, final boolean toView, final boolean fromSketchMode) {
153 final EdgeMap sourcePoints = Maps.createHashedEdgeMap();
156 final EdgeMap targetPoints = Maps.createHashedEdgeMap();
157 for (EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
158 final Edge edge = ec.edge();
159 sourcePoints.set(edge, graph.getSourcePointAbs(edge));
160 targetPoints.set(edge, graph.getTargetPointAbs(edge));
161 }
162
163 final double[] corners = new double[16];
164 final Rectangle2D.Double bounds = new Rectangle2D.Double();
165
166 final DataProvider transformationData = graph.getDataProvider(TRANSFORMATION_DATA_DPKEY);
168 for (NodeCursor nc = graph.nodes(); nc.ok(); nc.next()) {
169 final Node node = nc.node();
170 final NodeLayout nodeLayout = graph.getNodeLayout(node);
171 final IsometryData data = (IsometryData) transformationData.get(node);
172
173 if (toView) {
174 final double oldWidth = nodeLayout.getWidth();
175 final double oldHeight = nodeLayout.getHeight();
176 final double oldCenterX = nodeLayout.getX() + oldWidth * 0.5;
177 final double oldCenterY = nodeLayout.getY() + oldHeight * 0.5;
178 data.setWidth(oldWidth);
180 data.setDepth(oldHeight);
181
182 data.calculateCorners(corners);
183 IsometryData.calculateViewBounds(corners, bounds);
184 final double newWidth = bounds.getWidth();
185 final double newHeight = bounds.getHeight();
186 final double newCenterX = IsometryData.toViewX(oldCenterX, oldCenterY);
187 final double newCenterY = IsometryData.toViewY(oldCenterX, oldCenterY) - data.getHeight() * 0.5;
188 nodeLayout.setSize(newWidth, newHeight);
189 nodeLayout.setLocation(newCenterX - newWidth * 0.5, newCenterY - newHeight * 0.5);
190 } else {
191 final double oldCenterX = nodeLayout.getX() + nodeLayout.getWidth() * 0.5;
192 final double oldCenterY = nodeLayout.getY() + nodeLayout.getHeight() * 0.5 + data.getHeight() * 0.5;
193 final double newCenterX = IsometryData.toLayoutX(oldCenterX, oldCenterY);
194 final double newCenterY = IsometryData.toLayoutY(oldCenterX, oldCenterY);
195 final double newWidth = data.getWidth();
196 final double newHeight = data.getDepth();
197 nodeLayout.setSize(newWidth, newHeight);
198 if (fromSketchMode) {
199 nodeLayout.setLocation(newCenterX - newWidth * 0.5, newCenterY - newHeight * 0.5);
200 }
201 }
202 }
203
204 for (EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
206 final Edge edge = ec.edge();
207 final EdgeLayout edgeLayout = graph.getEdgeLayout(edge);
208 for (int i = 0; i < edgeLayout.pointCount(); i++) {
209 final YPoint point = edgeLayout.getPoint(i);
210 final YPoint transformedPoint = transformPoint(point, toView, fromSketchMode);
211 edgeLayout.setPoint(i, transformedPoint.getX(), transformedPoint.getY());
212 }
213
214 graph.setSourcePointAbs(edge, transformPoint((YPoint) sourcePoints.get(edge), toView, fromSketchMode));
216 graph.setTargetPointAbs(edge, transformPoint((YPoint) targetPoints.get(edge), toView, fromSketchMode));
217 }
218
219 if (toView) {
220 for (EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
221 final Edge edge = ec.edge();
222 final DataProvider edgeLabelMap = graph.getDataProvider(LabelLayoutData.EDGE_LABEL_LAYOUT_KEY);
223 final EdgeLabelLayout[] labels = graph.getEdgeLabelLayout(edge);
224 final LabelLayoutData[] labelLayoutData = (LabelLayoutData[]) edgeLabelMap.get(edge);
225 final EdgeLayout edgeLayout = graph.getEdgeLayout(edge);
226 final NodeLayout sourceLayout = graph.getNodeLayout(edge.source());
227 final NodeLayout targetLayout = graph.getNodeLayout(edge.target());
228 if (labelLayoutData != null) {
229 for (int i = 0; i < labels.length; i++) {
230 final EdgeLabelLayout label = labels[i];
231 final LabelLayoutData labelData = labelLayoutData[i];
232 final double oldWidth = labelData.getWidth();
233 final double oldHeight = labelData.getHeight();
234 final double oldCenterX = labelData.getX() + oldWidth * 0.5;
235 final double oldCenterY = labelData.getY() + oldHeight * 0.5;
236 final IsometryData data = (IsometryData) transformationData.get(label);
238 final OrientedRectangle labelBounds = labelData.getBounds();
239 data.setHorizontal(labelBounds.getUpY() == -1 || labelBounds.getUpY() == 1);
240 data.setWidth(oldWidth);
241 data.setDepth(oldHeight);
242
243 data.calculateCorners(corners);
244 IsometryData.calculateViewBounds(corners, bounds);
245 final double newWidth = bounds.getWidth();
246 final double newHeight = bounds.getHeight();
247 final double newCenterX = IsometryData.toViewX(oldCenterX, oldCenterY);
248 final double newCenterY = IsometryData.toViewY(oldCenterX, oldCenterY) - data.getHeight() * 0.5;
249
250 final OrientedRectangle newBounds = new OrientedRectangle(newCenterX - newWidth * 0.5,
251 newCenterY + newHeight * 0.5, newWidth, newHeight);
252 final Object parameter = label.getLabelModel().createModelParameter(newBounds, edgeLayout, sourceLayout, targetLayout);
253 final OrientedRectangle labelPlacement = label.getLabelModel().getLabelPlacement(newBounds.getSize(), edgeLayout, sourceLayout, targetLayout, parameter);
254 label.setModelParameter(parameter);
255 label.getOrientedBox().adoptValues(labelPlacement);
256 }
257 }
258 }
259 graph.removeDataProvider(LabelLayoutData.EDGE_LABEL_LAYOUT_KEY);
260 } else {
261 final EdgeMap edgeLabelMap = Maps.createHashedEdgeMap();
262 for (EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
263 final Edge edge = ec.edge();
264 final EdgeLabelLayout[] labels = graph.getEdgeLabelLayout(edge);
265 final LabelLayoutData[] labelLayoutData = new LabelLayoutData[labels.length];
266 for (int i = 0; i < labels.length; i++) {
267 final EdgeLabelLayout label = labels[i];
268 final IsometryData data = (IsometryData) transformationData.get(label);
269 if (!data.isHorizontal()) {
270 labelLayoutData[i] = new LabelLayoutData(data.getDepth(), data.getWidth());
271 } else {
272 labelLayoutData[i] = new LabelLayoutData(data.getWidth(), data.getDepth());
273 }
274 labelLayoutData[i].setPreferredPlacementDescriptor(label.getPreferredPlacementDescriptor());
275 }
276 edgeLabelMap.set(edge, labelLayoutData);
277 }
278 graph.addDataProvider(LabelLayoutData.EDGE_LABEL_LAYOUT_KEY, edgeLabelMap);
279 }
280 }
281
282
289 private static YPoint transformPoint(final YPoint point, final boolean toView, final boolean fromSketchMode) {
290 final double x = point.getX();
291 final double y = point.getY();
292
293 if (toView) {
294 return new YPoint(IsometryData.toViewX(x, y), IsometryData.toViewY(x, y));
295 } else {
296 if (fromSketchMode) {
297 return new YPoint(IsometryData.toLayoutX(x, y), IsometryData.toLayoutY(x, y));
298 } else {
299 return point;
300 }
301 }
302 }
303
304
312 public boolean isFromSketchMode() {
313 return fromSketchMode;
314 }
315
316
325 public void setFromSketchMode(boolean fromSketchMode) {
326 this.fromSketchMode = fromSketchMode;
327 }
328 }
329