Xcos: fix TextBlock invisible text
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / io / codec / BasicBlockCodec.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Allan SIMON
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  *
11  */
12
13 package org.scilab.modules.xcos.io.codec;
14
15 import java.util.Map;
16 import java.util.logging.Logger;
17
18 import org.scilab.modules.graph.utils.StyleMap;
19 import org.scilab.modules.types.ScilabType;
20 import org.scilab.modules.xcos.block.BasicBlock;
21 import org.scilab.modules.xcos.block.BasicBlock.SimulationFunctionType;
22 import org.scilab.modules.xcos.block.BlockFactory;
23 import org.scilab.modules.xcos.block.BlockFactory.BlockInterFunction;
24 import org.scilab.modules.xcos.block.SuperBlock;
25 import org.scilab.modules.xcos.block.TextBlock;
26 import org.scilab.modules.xcos.port.BasicPort;
27 import org.w3c.dom.Element;
28 import org.w3c.dom.Node;
29
30 import com.mxgraph.io.mxCellCodec;
31 import com.mxgraph.io.mxCodec;
32 import com.mxgraph.io.mxCodecRegistry;
33 import com.mxgraph.model.mxCell;
34 import com.mxgraph.model.mxICell;
35 import com.mxgraph.util.mxUtils;
36
37 /**
38  * Codec for any Block.
39  */
40 public class BasicBlockCodec extends XcosObjectCodec {
41
42     private static final String BASIC_BLOCK = BasicBlock.class.getSimpleName();
43     private static final String SIMULATION_FUNCTION_TYPE = "simulationFunctionType";
44     private static final String[] IGNORED_FIELDS = new String[] { SIMULATION_FUNCTION_TYPE, "locked", "parametersPCS" };
45     private static final Logger LOG = Logger.getLogger(BasicBlockCodec.class.getName());
46
47     /**
48      * The constructor used on for configuration
49      *
50      * @param template
51      *            Prototypical instance of the object to be encoded/decoded.
52      * @param exclude
53      *            Optional array of fieldnames to be ignored.
54      * @param idrefs
55      *            Optional array of fieldnames to be converted to/from
56      *            references.
57      * @param mapping
58      *            Optional mapping from field- to attributenames.
59      */
60     public BasicBlockCodec(Object template, String[] exclude, String[] idrefs, Map<String, String> mapping) {
61         super(template, exclude, idrefs, mapping);
62     }
63
64     /**
65      * Register all known codecs on the {@link mxCodecRegistry}.
66      */
67     public static void register() {
68         mxCodecRegistry.addPackage("org.scilab.modules.xcos.block");
69         mxCodecRegistry.addPackage("org.scilab.modules.xcos.block.io");
70         mxCodecRegistry.addPackage("org.scilab.modules.xcos.block.positionning");
71
72         for (BlockInterFunction function : BlockFactory.BlockInterFunction.values()) {
73             XcosObjectCodec codec = new BasicBlockCodec(function.getSharedInstance(), IGNORED_FIELDS, REFS, null);
74             mxCodecRegistry.register(codec);
75         }
76
77         XcosObjectCodec basicBlockCodec = new BasicBlockCodec(new BasicBlock(), IGNORED_FIELDS, REFS, null);
78         mxCodecRegistry.register(basicBlockCodec);
79
80         mxCellCodec cellCodec = new mxCellCodec(new mxCell(), null, REFS, null);
81         mxCodecRegistry.register(cellCodec);
82
83         /*
84          * per block specific codec setup
85          */
86         BasicBlockCodec codec = (BasicBlockCodec) mxCodecRegistry.getCodec("AfficheBlock");
87         codec.exclude.add("printTimer");
88         codec.exclude.add("updateAction");
89
90         /*
91          * Compat. to remove old specific implementations
92          *
93          * These implementation was available from Scilab-5.2.0 to Scilab-5.3.3.
94          */
95         mxCodecRegistry.addAlias("ConstBlock", BASIC_BLOCK);
96         mxCodecRegistry.addAlias("GainBlock", BASIC_BLOCK);
97         mxCodecRegistry.addAlias("PrintBlock", BASIC_BLOCK);
98     }
99
100     /**
101      * Things to do before encoding
102      *
103      * @param enc
104      *            Codec that controls the encoding process.
105      * @param obj
106      *            Object to be encoded.
107      * @param node
108      *            XML node to encode the object into.
109      * @return Returns the object to be encoded by the default encoding.
110      * @see com.mxgraph.io.mxObjectCodec#beforeEncode(com.mxgraph.io.mxCodec,
111      *      java.lang.Object, org.w3c.dom.Node)
112      */
113     @Override
114     public Object beforeEncode(mxCodec enc, Object obj, Node node) {
115         ((Element) node).setAttribute(SIMULATION_FUNCTION_TYPE, String.valueOf(((BasicBlock) obj).getSimulationFunctionType()));
116
117         /*
118          * Log some information
119          */
120         final BasicBlock b = (BasicBlock) obj;
121
122         for (int i = 0; i < b.getChildCount(); i++) {
123             final mxICell o = b.getChildAt(i);
124
125             // switch instanceof(o)
126             if (o instanceof BasicPort) {
127                 if (o.getParent() != b) {
128                     trace(enc, node, "Inconsistent parent");
129                 }
130                 continue;
131             }
132             if (o instanceof mxCell) {
133                 // this is a comment
134                 continue;
135             }
136
137             trace(enc, node, "Inconsistent child %s at %d", o, i);
138         }
139
140         if (b.getEdgeCount() > 0) {
141             trace(enc, node, "Has %d links", b.getEdgeCount());
142         }
143
144         return super.beforeEncode(enc, obj, node);
145     }
146
147     /**
148      * {@inheritDoc}
149      *
150      * Shortcut method to avoid old-XML-compat (before jgraphx-1.4) from
151      * {@link mxCellCodec}.
152      *
153      * Without this shortcut, alias does not works (Class name String
154      * comparaison).
155      *
156      * @see http://forum.jgraph.com/questions/1467/aliases-are-not-handled-on-
157      *      mxcellcodecbeforedecode
158      */
159     @Override
160     public Node beforeDecode(mxCodec dec, Node node, Object obj) {
161         return node;
162     }
163
164     /**
165      * Apply compatibility pattern to the decoded object
166      *
167      * @param dec
168      *            Codec that controls the decoding process.
169      * @param node
170      *            XML node to decode the object from.
171      * @param obj
172      *            Object decoded.
173      * @return The Object transformed
174      * @see org.scilab.modules.xcos.io.codec.XcosObjectCodec#afterDecode(com.mxgraph.io.mxCodec,
175      *      org.w3c.dom.Node, java.lang.Object)
176      */
177     @Override
178     public Object afterDecode(mxCodec dec, Node node, Object obj) {
179         if (!(obj instanceof BasicBlock)) {
180             LOG.severe("Unable to decode " + obj);
181             return obj;
182         }
183         final BasicBlock block = (BasicBlock) obj;
184
185         block.setSimulationFunctionType(SimulationFunctionType.DEFAULT);
186
187         String functionType = (((Element) node).getAttribute(SIMULATION_FUNCTION_TYPE));
188         if (functionType != null && functionType.compareTo("") != 0) {
189             SimulationFunctionType type = BasicBlock.SimulationFunctionType.valueOf(functionType);
190             if (type != null) {
191                 block.setSimulationFunctionType(type);
192             }
193         }
194
195         // Re associate the diagram container
196         if (block instanceof SuperBlock) {
197             final SuperBlock superBlock = (SuperBlock) block;
198             if (superBlock.getChild() != null) {
199                 superBlock.getChild().setContainer(superBlock);
200             }
201             superBlock.invalidateRpar();
202         }
203
204         // update TextBlock due to a wrong serialization of the CSS properties
205         if (block instanceof TextBlock) {
206             block.setValue(mxUtils.getBodyMarkup(String.valueOf(block.getValue()), true));
207         }
208
209         // update style to replace direction by rotation and add the
210         // default style if absent
211         StyleMap map = new StyleMap(((Element) node).getAttribute(STYLE));
212         formatStyle(map, (BasicBlock) obj);
213         block.setStyle(map.toString());
214         block.updateFieldsFromStyle();
215
216         /*
217          * Compat. to remove old specific implementations
218          *
219          * These implementation was available from Scilab-5.2.0 to Scilab-5.3.3.
220          *
221          * Set default values stolen from the old implementation in case of
222          * default value.
223          */
224         if (node.getNodeName().equals("ConstBlock")) {
225             if (block.getInterfaceFunctionName().equals(BasicBlock.DEFAULT_INTERFACE_FUNCTION)) {
226                 block.setInterfaceFunctionName("CONST_m");
227             }
228             if (block.getSimulationFunctionName().equals(BasicBlock.DEFAULT_SIMULATION_FUNCTION)) {
229                 block.setSimulationFunctionName("cstblk4");
230             }
231             if (block.getValue() == null) {
232                 block.setValue("1");
233             }
234         }
235         if (node.getNodeName().equals("GainBlock")) {
236             if (block.getInterfaceFunctionName().equals(BasicBlock.DEFAULT_INTERFACE_FUNCTION)) {
237                 block.setInterfaceFunctionName("GAINBLK_f");
238             }
239         }
240         // PrintBlock has no default values
241
242         return super.afterDecode(dec, node, obj);
243     }
244
245     /**
246      * Format the style value
247      *
248      * @param map
249      *            the read style value
250      * @param obj
251      *            the block instance
252      */
253     private void formatStyle(StyleMap map, BasicBlock obj) {
254
255         // Append the bloc style if not present.
256         String name = obj.getInterfaceFunctionName();
257         if (!map.containsKey(name)) {
258             map.put(name, null);
259         }
260
261         formatStyle(map);
262     }
263
264     /**
265      * To force serialisation/deserialisation of Scilab values, return null
266      * instead of any ScilabType instance.
267      *
268      * {@inheritDoc}
269      */
270     @Override
271     protected Object getFieldTemplate(Object obj, String fieldname, Node child) {
272         final Object template = getFieldValue(obj, fieldname);
273
274         if (template instanceof ScilabType) {
275             return null;
276         } else {
277             return super.getFieldTemplate(obj, fieldname, child);
278         }
279     }
280 }