Xcos: be compatible with Scilab 5.5.2 zcos files 52/18552/2
Clément DAVID [Thu, 22 Sep 2016 09:26:09 +0000 (11:26 +0200)]
To ease transition from Xcos 5 to Xcos 6, the ZCOS file format is
compatible. To have the same rendering on both version, the encoding of
some values (style rotation) have to be set in a special manner.

Port geometry is still discarded as it is no more present on the Port
model. The user have to manually resize each block to enforce a port
layouting on Scilab 5 after openning a Scilab 6 saved file.

Change-Id: I4b05946ab017000ef454cba88cac866c4b945dcf

scilab/CHANGES.md
scilab/modules/graph/src/java/org/scilab/modules/graph/shape/SvgShape.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/block/actions/RegionToSuperblockAction.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/codec/BasicPortCodec.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/scicos/BlockGraphicElement.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/writer/CustomWriter.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/port/Orientation.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/utils/BlockPositioning.java

index 79b355f..ec813f0 100644 (file)
@@ -192,6 +192,7 @@ Xcos
 ----
 
 * Major rewrite of the data structures, huge models should load and save faster. The memory usage on diagram edition is also slightly reduced.
+* ZCOS and XCOS file formats have evolved to reduce the duplicated information. Scilab 5.5.2 is able to open the newly saved files but the ports have to be repositioned manually.
 * Implicit fixed-size step ODE solver added: Crank-Nicolson 2(3). Added to the CVode package, it also benefits from the CVode rootfinding feature.
 
 
index b24dd10..5b0b541 100644 (file)
@@ -76,8 +76,8 @@ public class SvgShape extends mxLabelShape {
      */
     @Override
     public Rectangle getImageBounds(mxGraphics2DCanvas canvas, mxCellState state) {
-        final double rotation = mxUtils.getDouble(state.getStyle(),
-                                mxConstants.STYLE_ROTATION, 0);
+        final int rotation = (int) mxUtils.getDouble(state.getStyle(),
+                             mxConstants.STYLE_ROTATION, 0);
         final AffineTransform transform = new AffineTransform();
         transform.rotate(Math.toRadians(rotation), state.getCenterX(),
                          state.getCenterY());
index 5ca8a24..12d7700 100644 (file)
@@ -464,9 +464,9 @@ public class RegionToSuperblockAction extends VertexSelectionDependantAction {
 
                 final boolean mirrored = Boolean.TRUE.toString().equals(styleMap.get(XcosConstants.STYLE_MIRROR));
                 final boolean flipped = Boolean.TRUE.toString().equals(styleMap.get(XcosConstants.STYLE_FLIP));
-                final double doubleRotation = Double.valueOf(styleMap.getOrDefault(XcosConstants.STYLE_ROTATION, "0"));
+                final int intRotation = Double.valueOf(styleMap.getOrDefault(XcosConstants.STYLE_ROTATION, "0")).intValue();
 
-                angleCounter += doubleRotation;
+                angleCounter += intRotation;
                 if (flipped) {
                     flipCounter++;
                 }
@@ -484,7 +484,7 @@ public class RegionToSuperblockAction extends VertexSelectionDependantAction {
         controller.getObjectProperty(superBlock.getUID(), superBlock.getKind(), ObjectProperties.STYLE, style);
         StyleMap styleMap = new StyleMap(style[0]);
 
-        styleMap.put(XcosConstants.STYLE_ROTATION, Double.toString(BlockPositioning.roundAngle(angleCounter / selection.length)));
+        styleMap.put(XcosConstants.STYLE_ROTATION, Integer.toString(BlockPositioning.roundAngle(angleCounter / selection.length)));
         if (flipCounter > halfSize) {
             styleMap.put(XcosConstants.STYLE_FLIP, Boolean.toString(true));
         }
index d6b9453..6483b1e 100644 (file)
@@ -214,12 +214,12 @@ public class BasicPortCodec extends XcosObjectCodec {
      */
     private void updateRotationFromOrientation(StyleMap map, BasicPort obj) {
         final Orientation orientation = obj.getOrientation();
-        double rotation = 0;
+        int rotation = 0;
         boolean flipped = false;
         boolean mirrored = false;
 
         if (map.get(mxConstants.STYLE_ROTATION) != null) {
-            rotation = Double.parseDouble(map.get(mxConstants.STYLE_ROTATION));
+            rotation = Double.valueOf(map.get(mxConstants.STYLE_ROTATION)).intValue();
         } else {
             rotation = 0;
         }
@@ -238,7 +238,7 @@ public class BasicPortCodec extends XcosObjectCodec {
         // Calculate the rotation for this kind of port.
         rotation = orientation.getAbsoluteAngle(obj.getClass(), flipped, mirrored);
 
-        map.put(mxConstants.STYLE_ROTATION, Double.toString(rotation));
+        map.put(mxConstants.STYLE_ROTATION, Integer.toString(rotation));
     }
 }
 // CSON: ClassDataAbstractionCoupling
index 47dfb3f..a8b0972 100644 (file)
@@ -396,11 +396,11 @@ final class BlockGraphicElement extends BlockPartsElement {
         /*
          * Rotation management
          */
-        double theta = ((ScilabDouble) data.get(FLIP_INDEX + 1)).getRealPart()[0][0];
+        int theta = (int) ((ScilabDouble) data.get(FLIP_INDEX + 1)).getRealPart()[0][0];
         if (theta != 0) {
             // convert to a valid value
             theta = BlockPositioning.roundAngle(-theta);
-            styleMap.put(mxConstants.STYLE_ROTATION, Double.toString(theta));
+            styleMap.put(mxConstants.STYLE_ROTATION, Integer.toString(theta));
         }
 
         controller.setObjectProperty(into.getUID(), into.getKind(), ObjectProperties.STYLE, styleMap.toString());
index 20a7c86..56c620c 100644 (file)
@@ -44,17 +44,6 @@ public class CustomWriter extends ScilabWriter {
         switch (kind) {
             case DIAGRAM:
                 shared.stream.writeStartDocument();
-
-                /*
-                 * Add a version comment at startup
-                 */
-
-                final Package p = Package.getPackage("org.scilab.modules.xcos");
-                String comment = new StringBuilder().append(Xcos.TRADENAME).append(SEP).append(Xcos.VERSION).append(SEP)
-                .append(p.getSpecificationVersion()).append(SEP).append(p.getImplementationVersion()).toString();
-                shared.stream.writeComment(comment);
-                shared.stream.writeCharacters("\n");
-
                 shared.stream.writeStartElement(HandledElement.XcosDiagram.name());
 
                 /*
@@ -124,6 +113,16 @@ public class CustomWriter extends ScilabWriter {
         shared.stream.writeAttribute("title", str[0]);
 
         /*
+         * Add a version comment at the top layer
+         */
+        if (kind == Kind.DIAGRAM) {
+            final Package p = Package.getPackage("org.scilab.modules.xcos");
+            String comment = new StringBuilder().append(Xcos.TRADENAME).append(SEP).append(Xcos.VERSION).append(SEP)
+            .append(p.getSpecificationVersion()).append(SEP).append(p.getImplementationVersion()).toString();
+            shared.stream.writeComment(comment);
+        }
+
+        /*
          * encode some content then the children
          */
         shared.rawDataWriter.write(uid, kind);
index 256d258..d718ac9 100644 (file)
@@ -51,9 +51,9 @@ public enum Orientation {
      *            The block mirror state
      * @return The value of the angle.
      */
-    public double getRelativeAngle(double blockAngle, Class <? extends BasicPort > klass, boolean flipped, boolean mirrored) {
-        final double orientation = getOrientationAngle();
-        final double base = getBaseAngle(klass, orientation);
+    public int getRelativeAngle(int blockAngle, Class <? extends BasicPort > klass, boolean flipped, boolean mirrored) {
+        final int orientation = getOrientationAngle();
+        final int base = getBaseAngle(klass, orientation);
 
         return getFlippedAndMirroredAngle(base + blockAngle, flipped, mirrored);
     }
@@ -67,10 +67,10 @@ public enum Orientation {
      *            the mirror status
      * @return the real angle
      */
-    public double getAbsoluteAngle(Class <? extends BasicPort > klass,
+    public int getAbsoluteAngle(Class <? extends BasicPort > klass,
     boolean flipped, boolean mirrored) {
-        final double orientation = getOrientationAngle();
-        final double base = getBaseAngle(klass, orientation);
+        final int orientation = getOrientationAngle();
+        final int base = getBaseAngle(klass, orientation);
 
         return getFlippedAndMirroredAngle(base, flipped, mirrored);
     }
@@ -86,8 +86,8 @@ public enum Orientation {
      *            the mirror status
      * @return the updated angle.
      */
-    private double getFlippedAndMirroredAngle(double base, boolean flipped, boolean mirrored) {
-        double angle = base;
+    private int getFlippedAndMirroredAngle(int base, boolean flipped, boolean mirrored) {
+        int angle = base;
 
         switch (this) {
             case NORTH:
@@ -129,7 +129,7 @@ public enum Orientation {
      *            calculated orientation angle
      * @return updated angle
      */
-    private double getBaseAngle(Class <? extends BasicPort > klass, double orientationAngle) {
+    private int getBaseAngle(Class <? extends BasicPort > klass, int orientationAngle) {
         final boolean isOutput = OutputPort.class.isAssignableFrom(klass)
                                  || CommandPort.class.isAssignableFrom(klass);
 
index 9e6aa86..3c933e9 100644 (file)
@@ -45,9 +45,9 @@ public final class BlockPositioning {
      */
     public static final double DEFAULT_GRIDSIZE = Double.MIN_NORMAL;
     /** The rotation step of the clockwise and anticlockwise rotation */
-    public static final double ROTATION_STEP = 90;
+    public static final int ROTATION_STEP = 90;
     /** The max valid rotation value (always 360 degres) */
-    public static final double MAX_ROTATION = 360;
+    public static final int MAX_ROTATION = 360;
 
     /** This class is a static singleton, thus it must not be instantiated */
     private BlockPositioning() {
@@ -264,8 +264,8 @@ public final class BlockPositioning {
 
         final boolean mirrored = Boolean.TRUE.toString().equals(styleMap.get(XcosConstants.STYLE_MIRROR));
         final boolean flipped = Boolean.TRUE.toString().equals(styleMap.get(XcosConstants.STYLE_FLIP));
-        final double doubleRotation = Double.valueOf(styleMap.getOrDefault(XcosConstants.STYLE_ROTATION, "0"));
-        final int angle = (((int) Math.round(doubleRotation)) % 360 + 360) % 360;
+        final int intRotation = Double.valueOf(styleMap.getOrDefault(XcosConstants.STYLE_ROTATION, "0")).intValue();
+        final int angle = ((Math.round(intRotation)) % 360 + 360) % 360;
 
         List<BasicPort> working = ports;
 
@@ -377,8 +377,8 @@ public final class BlockPositioning {
 
         final boolean mirrored = Boolean.TRUE.toString().equals(styleMap.get(XcosConstants.STYLE_MIRROR));
         final boolean flipped = Boolean.TRUE.toString().equals(styleMap.get(XcosConstants.STYLE_FLIP));
-        final double doubleRotation = Double.valueOf(styleMap.getOrDefault(XcosConstants.STYLE_ROTATION, "0"));
-        final int angle = (((int) Math.round(doubleRotation)) % 360 + 360) % 360;
+        final int intRotation = Double.valueOf(styleMap.getOrDefault(XcosConstants.STYLE_ROTATION, "0")).intValue();
+        final int angle = ((Math.round(intRotation)) % 360 + 360) % 360;
 
         final int childrenCount = block.getChildCount();
         for (int i = 0; i < childrenCount; ++i) {
@@ -390,7 +390,7 @@ public final class BlockPositioning {
 
                 /* Apply angle */
                 final mxIGraphModel model = diag.getModel();
-                final String rot = Double.toString(orientation.getRelativeAngle(angle, port.getClass(), flipped, mirrored));
+                final String rot = Integer.toString(orientation.getRelativeAngle(angle, port.getClass(), flipped, mirrored));
                 mxStyleUtils.setCellStyles(model, new Object[] { port }, XcosConstants.STYLE_ROTATION, rot);
 
                 diag.getModel().endUpdate();
@@ -476,7 +476,7 @@ public final class BlockPositioning {
         controller.getObjectProperty(block.getUID(), Kind.BLOCK, ObjectProperties.STYLE, style);
 
         StyleMap styleMap = new StyleMap(style[0]);
-        styleMap.put(XcosConstants.STYLE_ROTATION, Double.toString(getNextAntiClockwiseAngle(styleMap)));
+        styleMap.put(XcosConstants.STYLE_ROTATION, Integer.toString(getNextAntiClockwiseAngle(styleMap)));
 
         controller.setObjectProperty(block.getUID(), Kind.BLOCK, ObjectProperties.STYLE, styleMap.toString());
         updateBlockView(diag, block);
@@ -489,10 +489,10 @@ public final class BlockPositioning {
      *            the data to parse
      * @return The angle value
      */
-    public static double getNextAntiClockwiseAngle(StyleMap styleMap) {
-        final double doubleRotation = Double.valueOf(styleMap.getOrDefault(XcosConstants.STYLE_ROTATION, "0"));
+    public static int getNextAntiClockwiseAngle(StyleMap styleMap) {
+        final int intRotation = Double.valueOf(styleMap.getOrDefault(XcosConstants.STYLE_ROTATION, "0")).intValue();
 
-        double angle = (doubleRotation - ROTATION_STEP + MAX_ROTATION) % MAX_ROTATION;
+        int angle = (intRotation - ROTATION_STEP + MAX_ROTATION) % MAX_ROTATION;
         return angle;
     }
 
@@ -503,9 +503,9 @@ public final class BlockPositioning {
      *            the data to parse
      * @return The angle value
      */
-    public static double getNextClockwiseAngle(StyleMap styleMap) {
-        final double doubleRotation = Double.valueOf(styleMap.getOrDefault(XcosConstants.STYLE_ROTATION, "0"));
-        double angle = (doubleRotation + ROTATION_STEP) % MAX_ROTATION;
+    public static int getNextClockwiseAngle(StyleMap styleMap) {
+        final int intRotation = Double.valueOf(styleMap.getOrDefault(XcosConstants.STYLE_ROTATION, "0")).intValue();
+        int angle = (intRotation + ROTATION_STEP) % MAX_ROTATION;
         return angle;
     }
 
@@ -516,15 +516,15 @@ public final class BlockPositioning {
      *            the non valid value
      * @return the nearest graph valid value
      */
-    public static double roundAngle(double angle) {
-        double ret = angle;
+    public static int roundAngle(int angle) {
+        int ret = angle;
         if (angle < 0 || angle > MAX_ROTATION) {
             ret = (angle + MAX_ROTATION) % MAX_ROTATION;
         }
 
         for (int i = 0; i < (MAX_ROTATION / ROTATION_STEP); i++) {
-            double min = i * ROTATION_STEP;
-            double max = (i + 1) * ROTATION_STEP;
+            int min = i * ROTATION_STEP;
+            int max = (i + 1) * ROTATION_STEP;
 
             if (ret < (min + max) / 2) {
                 ret = min;