* Bug #15456 fixed: Xcos 5.5.x files did not load properly
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / io / sax / JGraphXHandler.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2015-2017 - Scilab Enterprises - Clement DAVID
4  * Copyright (C) 2017 - ESI Group - Clement DAVID
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 package org.scilab.modules.xcos.io.sax;
18
19 import org.scilab.modules.xcos.Kind;
20 import org.scilab.modules.xcos.ObjectProperties;
21 import org.scilab.modules.xcos.graph.model.XcosCell;
22 import org.scilab.modules.xcos.io.HandledElement;
23 import org.xml.sax.Attributes;
24
25 import com.mxgraph.model.mxGeometry;
26 import com.mxgraph.util.mxPoint;
27 import java.nio.DoubleBuffer;
28 import java.nio.LongBuffer;
29 import java.util.ArrayList;
30 import org.scilab.modules.xcos.VectorOfDouble;
31 import org.scilab.modules.xcos.VectorOfScicosID;
32
33 class JGraphXHandler implements ScilabHandler {
34
35     private final XcosSAXHandler saxHandler;
36
37     JGraphXHandler(XcosSAXHandler saxHandler) {
38         this.saxHandler = saxHandler;
39     }
40
41
42
43     @Override
44     public Object startElement(HandledElement found, Attributes atts) {
45         String v;
46
47         switch (found) {
48             case mxCell: {
49                 v = atts.getValue("parent");
50                 if (v != null) {
51                     long parentUID = saxHandler.allChildren.peek().getOrDefault(v, 0l);
52                     if (parentUID != 0) {
53                         return decodeCellAnnotation(parentUID, saxHandler.controller.getKind(parentUID), atts);
54                     }
55                 } else {
56                     Object parent = saxHandler.parents.peek();
57                     if (parent instanceof XcosCell) {
58                         XcosCell cell = ((XcosCell) parent);
59                         if (cell.getUID() != 0) {
60                             return decodeCellAnnotation(cell.getUID(), cell.getKind(), atts);
61                         }
62                     }
63                 }
64                 return null;
65             }
66             case mxGeometry: {
67                 mxGeometry g = new mxGeometry();
68
69                 v = atts.getValue("x");
70                 if (v != null) {
71                     g.setX(Double.valueOf(v));
72                 }
73                 v = atts.getValue("y");
74                 if (v != null) {
75                     g.setY(Double.valueOf(v));
76                 }
77                 v = atts.getValue("width");
78                 if (v != null) {
79                     g.setWidth(Double.valueOf(v));
80                 }
81                 v = atts.getValue("height");
82                 if (v != null) {
83                     g.setHeight(Double.valueOf(v));
84                 }
85
86                 /*
87                  * the MVC only store absolute values, resolve the "relative" geometry flag for Scilab 5.5.2 annotation
88                  */
89                 v = atts.getValue("relative");
90                 if (v != null && v.charAt(0) == '1') {
91                     Object parent = saxHandler.parents.peek();
92                     if (parent instanceof XcosCell) {
93                         XcosCell cell = (XcosCell) parent;
94                         long[] parentUID = {0};
95                         saxHandler.controller.getObjectProperty(cell.getUID(), cell.getKind(), ObjectProperties.RELATED_TO, parentUID);
96
97                         VectorOfDouble parentGeom = new VectorOfDouble(4);
98                         saxHandler.controller.getObjectProperty(parentUID[0], saxHandler.controller.getKind(parentUID[0]), ObjectProperties.GEOMETRY, parentGeom);
99                         g.setX(g.getX() * parentGeom.get(2));
100                         g.setY(g.getY() * parentGeom.get(3));
101                     }
102                 }
103
104                 return g;
105             }
106             case mxPoint: {
107                 mxPoint p = new mxPoint();
108
109                 v = atts.getValue("x");
110                 if (v != null) {
111                     p.setX(Double.valueOf(v));
112                 }
113                 v = atts.getValue("y");
114                 if (v != null) {
115                     p.setY(Double.valueOf(v));
116                 }
117
118                 Object localParent = saxHandler.parents.peek();
119                 if (localParent instanceof mxGeometry) {
120                     mxGeometry parent = (mxGeometry) localParent;
121                     v = atts.getValue("as");
122                     if ("sourcePoint".equals(v)) {
123                         parent.setSourcePoint(p);
124                     } else if ("targetPoint".equals(v)) {
125                         parent.setTargetPoint(p);
126                     }
127                 } else if (localParent instanceof RawDataHandler.RawDataDescriptor) {
128                     RawDataHandler.RawDataDescriptor parent = (RawDataHandler.RawDataDescriptor) localParent;
129                     ((ArrayList) parent.value).add(p);
130                 } else if (localParent instanceof XcosCell) {
131                     // Diagram origin, translate each children
132                     XcosCell parent = (XcosCell) localParent;
133
134                     VectorOfScicosID children = new VectorOfScicosID();
135                     saxHandler.controller.getObjectProperty(parent.getUID(), parent.getKind(), ObjectProperties.CHILDREN, children);
136
137                     VectorOfDouble geometry = new VectorOfDouble(4);
138                     DoubleBuffer geom = geometry.asByteBuffer(0, 4).asDoubleBuffer();
139
140                     LongBuffer childrenUIDs = children.asByteBuffer(0, children.size()).asLongBuffer();
141                     while (childrenUIDs.hasRemaining()) {
142                         long uid = childrenUIDs.get();
143                         Kind kind = saxHandler.controller.getKind(uid);
144
145                         saxHandler.controller.getObjectProperty(uid, kind, ObjectProperties.GEOMETRY, geometry);
146                         geom.put(0, geom.get(0) + p.getX());
147                         geom.put(1, geom.get(1) + p.getY());
148                         saxHandler.controller.setObjectProperty(uid, kind, ObjectProperties.GEOMETRY, geometry);
149
150                         // translate the annotation
151                         long[] annotation = { 0 };
152                         saxHandler.controller.getObjectProperty(uid, kind, ObjectProperties.LABEL, annotation);
153                         if (annotation[0] != 0) {
154                             saxHandler.controller.getObjectProperty(annotation[0], Kind.ANNOTATION, ObjectProperties.GEOMETRY, geometry);
155                             geom.put(0, geom.get(0) + p.getX());
156                             geom.put(1, geom.get(1) + p.getY());
157                             saxHandler.controller.setObjectProperty(annotation[0], Kind.ANNOTATION, ObjectProperties.GEOMETRY, geometry);
158                         }
159
160                         // translate control-points
161                         if (kind == Kind.LINK) {
162                             VectorOfDouble controlPoints = new VectorOfDouble();
163                             saxHandler.controller.getObjectProperty(uid, kind, ObjectProperties.CONTROL_POINTS, controlPoints);
164
165                             DoubleBuffer points = controlPoints.asByteBuffer(0, controlPoints.size()).asDoubleBuffer();
166                             for (int i = 0; i < controlPoints.size(); i += 2) {
167                                 points.put(i, points.get(i) + p.getX());
168                                 points.put(i + 1, points.get(i + 1) + p.getY());
169                             }
170                             saxHandler.controller.setObjectProperty(uid, kind, ObjectProperties.CONTROL_POINTS, controlPoints);
171                         }
172                     }
173
174                 }
175                 return p;
176             }
177             default:
178                 throw new IllegalArgumentException();
179         }
180     }
181
182     private XcosCell decodeCellAnnotation(long parentUID, Kind parentKind, Attributes atts) {
183         Kind kind = Kind.ANNOTATION;
184         final long uid = saxHandler.controller.createObject(kind);
185         String value = atts.getValue("value");
186         if (value != null) {
187             saxHandler.controller.setObjectProperty(uid, kind, ObjectProperties.DESCRIPTION, value);
188         }
189         String style = atts.getValue("style");
190         if (style != null) {
191             saxHandler.controller.setObjectProperty(uid, kind, ObjectProperties.STYLE, style);
192         }
193         String id = atts.getValue("id");
194         if (id != null) {
195             saxHandler.allChildren.peek().put(id, uid);
196         }
197
198         XcosCell label = new XcosCell(saxHandler.controller, uid, kind, value, null, style, id);
199         saxHandler.controller.setObjectProperty(parentUID, parentKind, ObjectProperties.LABEL, label.getUID());
200         saxHandler.controller.setObjectProperty(label.getUID(), label.getKind(), ObjectProperties.RELATED_TO, parentUID);
201
202         return label;
203     }
204
205     @Override
206     public void endElement(HandledElement found) {
207         switch (found) {
208             case mxCell:
209                 break;
210             case mxGeometry: {
211                 // defensive programming
212                 if (!(saxHandler.parents.peek() instanceof mxGeometry)) {
213                     return;
214                 }
215                 mxGeometry g = (mxGeometry) saxHandler.parents.peek();
216                 if (!(saxHandler.parents.peek(1) instanceof XcosCell)) {
217                     return;
218                 }
219                 XcosCell cell = (XcosCell) saxHandler.parents.peek(1);
220
221                 cell.setGeometry(saxHandler.controller, g);
222             }
223             break;
224             case mxPoint:
225                 break;
226             default:
227                 throw new IllegalArgumentException();
228         }
229     }
230 }