2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010 - DIGITEO - Clement DAVID
4 * Copyright (C) 2011 - Scilab Enterprises - Clement DAVID
6 * Copyright (C) 2012 - 2016 - Scilab Enterprises
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.
17 package org.scilab.modules.xcos.io.scicos;
19 import static java.util.Arrays.asList;
21 import java.util.List;
23 import org.scilab.modules.graph.utils.StyleMap;
24 import org.scilab.modules.types.ScilabBoolean;
25 import org.scilab.modules.types.ScilabDouble;
26 import org.scilab.modules.types.ScilabList;
27 import org.scilab.modules.types.ScilabMList;
28 import org.scilab.modules.types.ScilabString;
29 import org.scilab.modules.types.ScilabTList;
30 import org.scilab.modules.types.ScilabType;
31 import org.scilab.modules.xcos.JavaController;
32 import org.scilab.modules.xcos.ObjectProperties;
33 import org.scilab.modules.xcos.VectorOfDouble;
34 import org.scilab.modules.xcos.block.BasicBlock;
35 import org.scilab.modules.xcos.graph.XcosDiagram;
36 import org.scilab.modules.xcos.io.ScilabTypeCoder;
37 import org.scilab.modules.xcos.io.scicos.ScicosFormatException.WrongElementException;
38 import org.scilab.modules.xcos.io.scicos.ScicosFormatException.WrongStructureException;
39 import org.scilab.modules.xcos.io.scicos.ScicosFormatException.WrongTypeException;
40 import org.scilab.modules.xcos.utils.BlockPositioning;
42 import com.mxgraph.model.mxCell;
43 import com.mxgraph.util.mxConstants;
44 import org.scilab.modules.xcos.utils.XcosConstants;
47 * Protected class which decode graphic fields of a block.
49 * This class is intentionally package-protected to prevent external use.
51 // CSOFF: ClassDataAbstractionCoupling
52 final class BlockGraphicElement extends BlockPartsElement {
54 * "in_style", "out_style" and style have been added on the 5.3-5.4 dev. cycle they are not checked to be compatible with older versions.
56 protected static final List<String> DATA_FIELD_NAMES = asList("graphics", "orig", "sz", "flip", "theta", "exprs", "pin", "pout", "pein", "peout", "gr_i",
57 "id", "in_implicit", "out_implicit");
58 protected static final List<String> DATA_FIELD_NAMES_FULL = asList("graphics", "orig", "sz", "flip", "theta", "exprs", "pin", "pout", "pein", "peout",
59 "gr_i", "id", "in_implicit", "out_implicit", "in_style", "out_style", "in_label", "out_label", "style");
61 private static final int ORIGIN_INDEX = DATA_FIELD_NAMES_FULL.indexOf("orig");
62 private static final int DIMS_INDEX = DATA_FIELD_NAMES_FULL.indexOf("sz");
63 private static final int FLIP_INDEX = DATA_FIELD_NAMES_FULL.indexOf("flip");
64 private static final int EXPRS_INDEX = DATA_FIELD_NAMES_FULL.indexOf("exprs");
65 private static final int ID_INDEX = DATA_FIELD_NAMES_FULL.indexOf("id");
66 private static final int STYLE_INDEX = DATA_FIELD_NAMES_FULL.indexOf("style");
68 private static final int GRAPHICS_INSTRUCTION_SIZE = 8;
69 private static final double DEFAULT_SIZE_FACTOR = 20.0;
71 /** Mutable field to easily get the data through methods */
72 private ScilabMList data;
74 /** In-progress decoded diagram */
75 private final XcosDiagram diag;
77 /** Size factor use to scale Xcos-Scicos dimensions */
78 private final double sizeFactor;
83 public BlockGraphicElement(final JavaController controller) {
84 this(controller, null);
88 * Default constructor with diagram
93 public BlockGraphicElement(final JavaController controller, final XcosDiagram diag) {
99 * Out of a diagram update, use the DEFAULT_SIZE_FACTOR.
102 sizeFactor = DEFAULT_SIZE_FACTOR;
109 * Default constructor with diagram
116 public BlockGraphicElement(final JavaController controller, final XcosDiagram diag, final double sizeFactor) {
120 this.sizeFactor = sizeFactor;
124 * Decode Scicos element into the block.
126 * This decode method doesn't coverage Port management because we need model information to handle it.
131 * the previously instantiated block.
132 * @return the modified into block.
133 * @throws ScicosFormatException
135 * @see org.scilab.modules.xcos.io.scicos.Element#decode(org.scilab.modules.types.ScilabType, java.lang.Object)
138 public BasicBlock decode(ScilabType element, final BasicBlock into) throws ScicosFormatException {
141 throw new IllegalArgumentException();
143 BasicBlock block = into;
145 data = (ScilabMList) element;
149 block = beforeDecode(element, block);
154 decodeDimension(block);
156 decodeFlipAndRotation(block);
159 controller.setObjectProperty(into.getUID(), into.getKind(), ObjectProperties.EXPRS, new ScilabTypeCoder().var2vec(data.get(EXPRS_INDEX)));
161 if (data.size() > STYLE_INDEX && !isEmptyField(data.get(STYLE_INDEX))) {
162 final ScilabString style = (ScilabString) data.get(STYLE_INDEX);
163 final String s = style.getData()[0][0];
165 if (s != null && !s.isEmpty()) {
170 block = afterDecode(element, block);
176 * Validate the current data.
178 * This method doesn't pass the metrics because it perform many test. Therefore all these tests are trivial and the conditioned action only throw an exception.
180 * @throws ScicosFormatException
181 * when there is a validation error.
183 // CSOFF: CyclomaticComplexity
184 // CSOFF: NPathComplexity
186 private void validate() throws ScicosFormatException {
187 if (!canDecode(data)) {
188 throw new WrongElementException();
193 // we test if the structure as enough field
194 if (data.size() < DATA_FIELD_NAMES.size()) {
195 throw new WrongStructureException(DATA_FIELD_NAMES);
199 * Checking the MList header
202 // Check the first field
203 if (!(data.get(field) instanceof ScilabString)) {
204 throw new WrongTypeException(DATA_FIELD_NAMES, field);
206 final String[] header = ((ScilabString) data.get(field)).getData()[0];
208 // Checking for the field names
209 if (header.length < DATA_FIELD_NAMES.size()) {
210 throw new WrongStructureException(DATA_FIELD_NAMES);
212 for (int i = 0; i < DATA_FIELD_NAMES.size(); i++) {
213 if (!header[i].equals(DATA_FIELD_NAMES.get(i))) {
214 throw new WrongStructureException(DATA_FIELD_NAMES);
222 // orig : must contain the coord of the block
224 if (!(data.get(field) instanceof ScilabDouble)) {
225 throw new WrongTypeException(DATA_FIELD_NAMES, field);
228 // sz : must contains the size of the block
230 if (!(data.get(field) instanceof ScilabDouble)) {
231 throw new WrongTypeException(DATA_FIELD_NAMES, field);
236 if (!(data.get(field) instanceof ScilabBoolean)) {
237 throw new WrongTypeException(DATA_FIELD_NAMES, field);
242 if (!(data.get(field) instanceof ScilabDouble)) {
243 throw new WrongTypeException(DATA_FIELD_NAMES, field);
248 if (!(data.get(field) instanceof ScilabString) && !(data.get(field) instanceof ScilabList) && !(data.get(field) instanceof ScilabTList)
249 && !isEmptyField(data.get(field))) {
250 throw new WrongTypeException(DATA_FIELD_NAMES, field);
255 if (!(data.get(field) instanceof ScilabDouble)) {
256 throw new WrongTypeException(DATA_FIELD_NAMES, field);
261 if (!(data.get(field) instanceof ScilabDouble)) {
262 throw new WrongTypeException(DATA_FIELD_NAMES, field);
267 if (!(data.get(field) instanceof ScilabDouble)) {
268 throw new WrongTypeException(DATA_FIELD_NAMES, field);
273 if (!(data.get(field) instanceof ScilabDouble)) {
274 throw new WrongTypeException(DATA_FIELD_NAMES, field);
278 // !! WARNING !! we do not care about gr_i because there are only
279 // block look related.
284 if (!(data.get(field) instanceof ScilabString)) {
285 throw new WrongTypeException(DATA_FIELD_NAMES, field);
290 if (!(data.get(field) instanceof ScilabString) && !isEmptyField(data.get(field))) {
291 throw new WrongTypeException(DATA_FIELD_NAMES, field);
296 if (!(data.get(field) instanceof ScilabString) && !isEmptyField(data.get(field))) {
297 throw new WrongTypeException(DATA_FIELD_NAMES, field);
300 // field added on the 5.3-5.4 dev. cycle
301 // not checked due to compatibility
307 // CSON: CyclomaticComplexity
308 // CSON: NPathComplexity
312 * Fill the block with the origin parameters
315 * the target instance
317 private void decodeOrigin(final BasicBlock into) {
324 final double[][] real = ((ScilabDouble) data.get(ORIGIN_INDEX)).getRealPart();
326 final double[] vector = real[real.length - 1];
327 y = vector[vector.length - 1];
330 * Apply compatibility patterns
336 * Invert the y-axis value and translate it.
338 y = -y - into.getGeometry().getHeight();
343 into.getGeometry().setX(x);
344 into.getGeometry().setY(y);
348 * Fill the block with the dimension parameters
351 * the target instance
353 private void decodeDimension(final BasicBlock into) {
360 final double[][] real = ((ScilabDouble) data.get(DIMS_INDEX)).getRealPart();
362 final double[] vector = real[real.length - 1];
363 h = vector[vector.length - 1];
366 * When a block has no parent diagram, the size should be updated. On a diagram decode, size is right.
374 into.getGeometry().setWidth(w);
375 into.getGeometry().setHeight(h);
379 * Fill the block with the flip and theta parameters
382 * the target instance
384 private void decodeFlipAndRotation(final BasicBlock into) {
385 String[] interfaceFunction = new String[1];
386 controller.getObjectProperty(into.getUID(), into.getKind(), ObjectProperties.INTERFACE_FUNCTION, interfaceFunction);
388 StyleMap styleMap = new StyleMap(interfaceFunction[0]);
393 if (!((ScilabBoolean) data.get(FLIP_INDEX)).getData()[0][0]) {
394 styleMap.put(XcosConstants.STYLE_FLIP, Boolean.TRUE.toString());
398 * Rotation management
400 double theta = ((ScilabDouble) data.get(FLIP_INDEX + 1)).getRealPart()[0][0];
402 // convert to a valid value
403 theta = BlockPositioning.roundAngle(-theta);
404 styleMap.put(mxConstants.STYLE_ROTATION, Double.toString(theta));
407 controller.setObjectProperty(into.getUID(), into.getKind(), ObjectProperties.STYLE, styleMap.toString());
411 * Preserve the id if applicable
414 * the target instance
416 private void decodeIdCell(final BasicBlock into) {
421 final String[][] id = ((ScilabString) data.get(ID_INDEX)).getData();
422 if (id.length == 0 || id[0].length == 0 || id[0][0].isEmpty()) {
427 * Create the local identifier
429 final mxCell identifier = diag.createCellIdentifier(into);
430 identifier.setValue(id[0][0]);
432 into.insert(identifier);
436 * Check if the element can be decoded.
440 * @return true, if the Scicos types match.
441 * @see org.scilab.modules.xcos.io.scicos.Element#canDecode(org.scilab.modules.types.ScilabType)
444 public boolean canDecode(ScilabType element) {
445 data = (ScilabMList) element;
447 final String type = ((ScilabString) data.get(0)).getData()[0][0];
448 return type.equals(DATA_FIELD_NAMES.get(0));
451 // CSON: ClassDataAbstractionCoupling