Xcos: add a function type for debugging
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / block / BasicBlock.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Bruno JOFRET
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-en.txt
10  *
11  */
12
13 package org.scilab.modules.xcos.block;
14
15 import static org.scilab.modules.xcos.utils.FileUtils.delete;
16
17 import java.awt.MouseInfo;
18 import java.awt.event.ActionEvent;
19 import java.awt.event.ActionListener;
20 import java.beans.PropertyChangeEvent;
21 import java.beans.PropertyChangeListener;
22 import java.beans.PropertyChangeSupport;
23 import java.io.File;
24 import java.io.IOException;
25 import java.io.Serializable;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.Comparator;
29 import java.util.Deque;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.LinkedList;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36
37 import ncsa.hdf.hdf5lib.exceptions.HDF5Exception;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41 import org.scilab.modules.action_binding.InterpreterManagement;
42 import org.scilab.modules.action_binding.highlevel.ScilabInterpreterManagement;
43 import org.scilab.modules.action_binding.highlevel.ScilabInterpreterManagement.InterpreterException;
44 import org.scilab.modules.graph.ScilabGraph;
45 import org.scilab.modules.graph.ScilabGraphUniqueObject;
46 import org.scilab.modules.graph.actions.CopyAction;
47 import org.scilab.modules.graph.actions.CutAction;
48 import org.scilab.modules.graph.actions.DeleteAction;
49 import org.scilab.modules.graph.actions.base.DefaultAction;
50 import org.scilab.modules.graph.utils.ScilabGraphConstants;
51 import org.scilab.modules.graph.utils.StyleMap;
52 import org.scilab.modules.gui.bridge.contextmenu.SwingScilabContextMenu;
53 import org.scilab.modules.gui.contextmenu.ContextMenu;
54 import org.scilab.modules.gui.contextmenu.ScilabContextMenu;
55 import org.scilab.modules.gui.events.callback.CallBack;
56 import org.scilab.modules.gui.menu.Menu;
57 import org.scilab.modules.gui.menu.ScilabMenu;
58 import org.scilab.modules.gui.menuitem.MenuItem;
59 import org.scilab.modules.gui.menuitem.ScilabMenuItem;
60 import org.scilab.modules.hdf5.write.H5Write;
61 import org.scilab.modules.types.ScilabDouble;
62 import org.scilab.modules.types.ScilabList;
63 import org.scilab.modules.types.ScilabString;
64 import org.scilab.modules.types.ScilabType;
65 import org.scilab.modules.xcos.Xcos;
66 import org.scilab.modules.xcos.XcosTab;
67 import org.scilab.modules.xcos.actions.EditFormatAction;
68 import org.scilab.modules.xcos.actions.ShowHideShadowAction;
69 import org.scilab.modules.xcos.block.actions.BlockDocumentationAction;
70 import org.scilab.modules.xcos.block.actions.BlockParametersAction;
71 import org.scilab.modules.xcos.block.actions.BorderColorAction;
72 import org.scilab.modules.xcos.block.actions.FilledColorAction;
73 import org.scilab.modules.xcos.block.actions.FlipAction;
74 import org.scilab.modules.xcos.block.actions.MirrorAction;
75 import org.scilab.modules.xcos.block.actions.RegionToSuperblockAction;
76 import org.scilab.modules.xcos.block.actions.RotateAction;
77 import org.scilab.modules.xcos.block.actions.ViewDetailsAction;
78 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockAction;
79 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockActionBottom;
80 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockActionCenter;
81 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockActionLeft;
82 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockActionMiddle;
83 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockActionRight;
84 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockActionTop;
85 import org.scilab.modules.xcos.graph.PaletteDiagram;
86 import org.scilab.modules.xcos.graph.SuperBlockDiagram;
87 import org.scilab.modules.xcos.graph.XcosDiagram;
88 import org.scilab.modules.xcos.io.scicos.BasicBlockInfo;
89 import org.scilab.modules.xcos.io.scicos.H5RWHandler;
90 import org.scilab.modules.xcos.port.BasicPort;
91 import org.scilab.modules.xcos.port.command.CommandPort;
92 import org.scilab.modules.xcos.port.control.ControlPort;
93 import org.scilab.modules.xcos.port.input.InputPort;
94 import org.scilab.modules.xcos.port.output.OutputPort;
95 import org.scilab.modules.xcos.utils.BlockPositioning;
96 import org.scilab.modules.xcos.utils.FileUtils;
97 import org.scilab.modules.xcos.utils.XcosConstants;
98 import org.scilab.modules.xcos.utils.XcosEvent;
99 import org.scilab.modules.xcos.utils.XcosMessages;
100
101 import com.mxgraph.model.mxGeometry;
102 import com.mxgraph.model.mxICell;
103 import com.mxgraph.model.mxIGraphModel;
104 import com.mxgraph.util.mxConstants;
105 import com.mxgraph.util.mxEventObject;
106 import com.mxgraph.util.mxUtils;
107
108 public class BasicBlock extends ScilabGraphUniqueObject implements Serializable {
109         /**
110          * Property name of {@link #interfaceFunctionName}
111          */
112         public static final String INTERFACE_FUNCTION_NAME = "interfaceFunctionName";
113         /**
114          * Property name of {@link #simulationFunctionName}
115          */
116         public static final String SIMULATION_FUNCTION_NAME = "simulationFunctionName";
117         /**
118          * Property name of {@link #simulationFunctionType}
119          */
120         public static final String SIMULATION_FUNCTION_TYPE = "simulationFunctionType";
121         /**
122          * Property name of {@link #realParameters}
123          */
124         public static final String REAL_PARAMETERS = "realParameters";
125         /**
126          * Property name of {@link #integerParameters}
127          */
128         public static final String INTEGER_PARAMETERS = "integerParameters";
129         /**
130          * Property name of {@link #objectsParameters}
131          */
132         public static final String OBJECTS_PARAMETERS = "objectsParameters";
133         /**
134          * Property name of {@link #dependsOnU}
135          */
136         public static final String DEPENDS_ON_U = "dependsOnU";
137         /**
138          * Property name of {@link #dependsOnT}
139          */
140         public static final String DEPENDS_ON_T = "dependsOnT";
141         /**
142          * Property name of {@link #blockType}
143          */
144         public static final String BLOCK_TYPE = "blockType";
145         /**
146          * Property name of {@link #ordering}
147          */
148         public static final String ORDERING = "ordering";
149         /**
150          * Property name of {@link #exprs}
151          */
152         public static final String EXPRS = "exprs";
153         /**
154          * Property name of {@link #nbZerosCrossing}
155          */
156         public static final String NB_ZEROS_CROSSING = "nbZerosCrossing";
157         /**
158          * Property name of {@link #nmode}
159          */
160         public static final String NMODE = "nmode";
161         /**
162          * Property name of {@link #state}
163          */
164         public static final String STATE = "state";
165         /**
166          * Property name of {@link #dState}
167          */
168         public static final String D_STATE = "dState";
169         /**
170          * Property name of {@link #oDState}
171          */
172         public static final String O_D_STATE = "oDState";
173         /**
174          * Property name of {@link #equations}
175          */
176         public static final String EQUATIONS = "equations";
177         
178         private static final double DEFAULT_POSITION_X = 10.0;
179         private static final double DEFAULT_POSITION_Y = 10.0;
180         private static final double DEFAULT_WIDTH = 40.0;
181         private static final double DEFAULT_HEIGHT = 40.0;
182         
183         private static final PropertyChangeListener STYLE_UPDATER = new UpdateStyleFromInterfunction();
184         private static final Log LOG = LogFactory.getLog(BasicBlock.class);
185         
186         /**
187          * Manage events for block parameters.
188          * 
189          * The property name is the field name, is one of:
190          *     - "interfaceFunctionName"
191          *     - "simulationFunctionName"
192          *     - "simulationFunctionType"
193          *     - "exprs"
194          *     - "realParameters"
195          *     - "integerParameters"
196          *     - "objectsParameters"
197          *     - "nbZerosCrossing"
198          *     - "nmode"
199          *     - "state"
200          *     - "dState"
201          *     - "oDState"
202          *     - "equations"
203          *     - "dependsOnU"
204          *     - "dependsOnT"
205          *     - "blockType"
206          *     - "ordering"
207          *  
208          *  you can easily access to then by using property name constants.
209          */
210         private PropertyChangeSupport parametersPCS = new PropertyChangeSupport(this);
211         
212     private String interfaceFunctionName = "xcos_block";
213     private String simulationFunctionName = "xcos_simulate";
214     private SimulationFunctionType simulationFunctionType = SimulationFunctionType.DEFAULT;
215     private transient XcosDiagram parentDiagram;   
216     
217     private int angle;
218     private boolean isFlipped;
219     private boolean isMirrored;
220     
221
222     // TODO : Must make this types evolve, but for now keep a strong link to Scilab
223     // !! WARNING !!
224     // exprs = [] ; rpar = [] ; ipar = [] ; opar = list()
225
226     //private List<String> exprs = new ArrayList<String>();
227     private ScilabType exprs;
228     //private List<Double> realParameters = new ArrayList<Double>();
229     private ScilabType realParameters;
230     //private List<Integer> integerParameters = new ArrayList<Integer>();
231     private ScilabType integerParameters;
232     //private List objectsParameters = new ArrayList();
233     private ScilabType objectsParameters;
234
235     private ScilabType nbZerosCrossing = new ScilabDouble();
236
237     private ScilabType nmode = new ScilabDouble();
238
239     private ScilabType state = new ScilabDouble();
240     private ScilabType dState = new ScilabDouble();
241     private ScilabType oDState = new ScilabDouble();
242
243     private ScilabType equations;
244
245     private boolean dependsOnU;
246     private boolean dependsOnT;
247
248     private String blockType = "c";
249
250     private int ordering;
251     private boolean locked;
252
253         /**
254          * Represent a simulation function type compatible with Scilab/Scicos
255          * function type descriptors.
256          */
257         public static enum SimulationFunctionType {
258                 ESELECT(-2.0), IFTHENELSE(-1.0), DEFAULT(0.0), TYPE_1(1.0), TYPE_2(2.0),
259                     TYPE_3(3.0), C_OR_FORTRAN(4.0), SCILAB(5.0), DEBUG(99), MODELICA(30004.0), UNKNOWN(5.0), OLDBLOCKS(10001.0), IMPLICIT_C_OR_FORTRAN(10004.0);
260
261                 private double value;
262
263                 /**
264                  * Default constructor
265                  * 
266                  * @param scilabValue
267                  *            Scilab/Scicos function type descriptor
268                  */
269                 private SimulationFunctionType(double scilabValue) {
270                         value = scilabValue;
271                 }
272
273                 /**
274                  * Get the Java descriptor from the Scilab descriptor.
275                  * 
276                  * @param scilabValue
277                  *            Scilab/Scicos function type descriptor
278                  * @return The corresponding java descriptor
279                  */
280                 public static SimulationFunctionType convertScilabValue(int scilabValue) {
281                         for (SimulationFunctionType iter : SimulationFunctionType.values()) {
282                                 if (iter.getAsDouble() == scilabValue) {
283                                         return iter;
284                                 }
285                         }
286                         return UNKNOWN;
287                 }
288
289                 /**
290                  * Get the Scilab Descriptor from the Java Descriptor
291                  * 
292                  * @return The corresponding Scilab/Scicos descriptor
293                  */
294                 public double getAsDouble() {
295                         return value;
296                 }
297         };
298
299         /**
300          * Update the source block when the interfunction change. 
301          */
302         private static final class UpdateStyleFromInterfunction implements PropertyChangeListener, Serializable {
303
304                 /**
305                  * Default constructor.
306                  */
307                 public UpdateStyleFromInterfunction() {
308                 }
309                 
310                 /**
311                  * Update the label on interfunction change.
312                  * 
313                  * @param evt the property change event.
314                  * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
315                  */
316                 @Override
317                 public void propertyChange(PropertyChangeEvent evt) {
318                         BasicBlock source = (BasicBlock) evt.getSource();
319                         
320                         StyleMap style = new StyleMap(source.getStyle());
321                         style.remove(evt.getOldValue());
322                         style.put((String) evt.getNewValue(), null);
323                         source.setStyle(style.toString());
324                 }
325                 
326         }
327         
328         /**
329          * Trace the parameters change on the {@link Log}.
330          * 
331          * This listener is only installed if the trace is enable.
332          */
333         private static final class TraceParametersListener implements PropertyChangeListener, Serializable {
334                 private static TraceParametersListener instance;
335                 
336                 /**
337                  * Default constructor.
338                  */
339                 private TraceParametersListener() {
340                         super();
341                 }
342                 
343                 /**
344                  * @return the instance
345                  */
346                 public static TraceParametersListener getInstance() {
347                         if (instance == null) {
348                                 instance = new TraceParametersListener();
349                         }
350                         return instance;
351                 }
352                 
353                 /**
354                  * Trace.
355                  * @param evt the event
356                  * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
357                  */
358                 @Override
359                 public void propertyChange(PropertyChangeEvent evt) {
360                         LOG.trace(evt.getPropertyName() + ": " + evt.getOldValue() + ", " + evt.getNewValue());
361                 }
362         }
363         
364         /**
365          * Default constructor.
366          */
367         public BasicBlock() {
368                 super();
369                 setDefaultValues();
370                 setVisible(true);
371                 setVertex(true);
372                 
373                 if (getStyle().isEmpty() && !getInterfaceFunctionName().isEmpty()) {
374                         setStyle(getInterfaceFunctionName());
375                 }
376                 
377                 parametersPCS.addPropertyChangeListener(INTERFACE_FUNCTION_NAME,
378                                 STYLE_UPDATER);
379                 
380                 /*
381                  * Trace block parameters change if applicable.
382                  */
383                 if (LOG.isTraceEnabled()) {
384                         parametersPCS.addPropertyChangeListener(TraceParametersListener.getInstance());
385                 }
386         }
387
388         /**
389          * @param label block label
390          */
391         protected BasicBlock(String label) {
392                 this();
393                 setDefaultValues();
394         }
395
396         /**
397          * @param label block label
398          * @param style initial style
399          */
400         protected BasicBlock(String label, String style) {
401                 this(label);
402                 setStyle(style);
403         }
404
405         /**
406          * Initialize the block with the default values
407          */
408         protected void setDefaultValues() {
409                 setVisible(true);
410                 setVertex(true);
411                 setConnectable(false);
412                 setGeometry(new mxGeometry(DEFAULT_POSITION_X, DEFAULT_POSITION_Y,
413                                 DEFAULT_WIDTH, DEFAULT_HEIGHT));
414                 setValue("");
415                 setStyle("");
416         }
417         
418     /**
419      * @return parent diagram
420      */
421     public XcosDiagram getParentDiagram() {
422         return parentDiagram;
423     }
424
425     /**
426      * @param parentDiagram parent diagram
427      */
428     public void setParentDiagram(XcosDiagram parentDiagram) {
429         this.parentDiagram = parentDiagram;
430     }
431
432     
433     /**
434      * @return interface function name
435      */
436     public String getInterfaceFunctionName() {
437         return interfaceFunctionName;
438     }
439
440     /**
441      * @param interfaceFunctionName interface function name
442      */
443     public void setInterfaceFunctionName(String interfaceFunctionName) {
444                 if ((this.interfaceFunctionName == null && interfaceFunctionName != null)
445                                 || !this.interfaceFunctionName.equals(interfaceFunctionName)) {
446                         
447                         final String oldValue = this.interfaceFunctionName;
448                         this.interfaceFunctionName = interfaceFunctionName;
449                         parametersPCS.firePropertyChange(INTERFACE_FUNCTION_NAME, oldValue,
450                                         interfaceFunctionName);
451                 }
452     }
453
454     /**
455      * @param simulationFunctionName sumulation function name
456      */
457     public void setSimulationFunctionName(String simulationFunctionName) {
458                 if ((this.simulationFunctionName == null && simulationFunctionName != null)
459                                 || !this.simulationFunctionName.equals(simulationFunctionName)) {
460                         
461                 final String oldValue = this.simulationFunctionName;
462                 this.simulationFunctionName = simulationFunctionName;
463                 parametersPCS.firePropertyChange(SIMULATION_FUNCTION_NAME, oldValue, simulationFunctionName);
464         }
465     }
466
467     /**
468      * @return sumulation function name
469      */
470     public String getSimulationFunctionName() {
471         return simulationFunctionName;
472     }
473
474     /**
475      * @param scilabValue simulation function type
476      */
477     public void setSimulationFunctionType(int scilabValue) {
478                 SimulationFunctionType simFunctionType = SimulationFunctionType.convertScilabValue(scilabValue);
479                 setSimulationFunctionType(simFunctionType);
480     }
481
482     /**
483      * @param simulationFunctionType simulation function type
484      */
485         public void setSimulationFunctionType(SimulationFunctionType simulationFunctionType) {
486                 if ((this.simulationFunctionType == null && simulationFunctionType != null)
487                                 || !this.simulationFunctionType.equals(simulationFunctionType)) {
488                         
489                         final SimulationFunctionType oldValue = this.simulationFunctionType;
490                         this.simulationFunctionType = simulationFunctionType;
491                         parametersPCS.firePropertyChange(SIMULATION_FUNCTION_TYPE, oldValue,
492                                         simulationFunctionType);
493                 }
494         }
495
496     /**
497      * @return simulation function type
498      */
499     public SimulationFunctionType getSimulationFunctionType() {
500         return simulationFunctionType;
501     }
502
503     /**
504      * @return real parameter ( rpar )
505      */
506     public ScilabType getRealParameters() {
507         return realParameters;
508     }
509
510     /**
511      * @param realParameters reaL parameter ( rpar )
512      */
513     public void setRealParameters(ScilabType realParameters) {
514                 if ((this.realParameters == null && realParameters != null)
515                                 || !this.realParameters.equals(realParameters)) {
516                         
517                         final ScilabType oldValue = this.realParameters;
518                         this.realParameters = realParameters;
519                         parametersPCS.firePropertyChange(REAL_PARAMETERS, oldValue, realParameters);
520                 }
521     } 
522
523     /**
524      * @return integer parameter ( ipar )
525      */
526     public ScilabType getIntegerParameters() {
527         return integerParameters;
528     }
529
530     /**
531      * @param integerParameters integer parameter ( ipar )
532      */
533     public void setIntegerParameters(ScilabType integerParameters) {
534                 if ((this.integerParameters == null && integerParameters != null)
535                                 || !this.integerParameters.equals(integerParameters)) {
536                         
537                         final ScilabType oldValue = this.integerParameters;
538                         this.integerParameters = integerParameters;
539                         parametersPCS.firePropertyChange(INTEGER_PARAMETERS, oldValue, integerParameters);
540                 }
541     }
542
543     /**
544      * @return object parameter ( opar )
545      */
546     public ScilabType getObjectsParameters() {
547         return objectsParameters;
548     }
549
550     /**
551      * @param objectsParameters object parameter ( opar )
552      */
553     public void setObjectsParameters(ScilabType objectsParameters) {
554                 if ((this.objectsParameters == null && objectsParameters != null)
555                                 || !this.objectsParameters.equals(objectsParameters)) {
556                         
557                         final ScilabType oldValue = this.objectsParameters;
558                         this.objectsParameters = objectsParameters;
559                         parametersPCS.firePropertyChange(OBJECTS_PARAMETERS, oldValue, objectsParameters);
560                 }
561     }
562
563     /**
564      * @param dependsOnU ?
565      */
566     public void setDependsOnU(boolean dependsOnU) {
567                 if (this.dependsOnU != dependsOnU) {
568                         
569                         final boolean oldValue = this.dependsOnU;
570                         this.dependsOnU = dependsOnU;
571                         parametersPCS.firePropertyChange(DEPENDS_ON_U, oldValue, dependsOnU);
572                 }
573     }
574
575     /**
576      * @return ?
577      */
578     public boolean isDependsOnU() {
579         return dependsOnU;
580     }
581
582     /**
583      * @param dependsOnT ?
584      */
585     public void setDependsOnT(boolean dependsOnT) {
586                 if (this.dependsOnT != dependsOnT) {
587                         
588                         final boolean oldValue = this.dependsOnT;
589                         this.dependsOnT = dependsOnT;
590                         parametersPCS.firePropertyChange(DEPENDS_ON_T, oldValue, dependsOnT);
591                 }
592     }
593
594     /**
595      * @return ?
596      */
597     public boolean isDependsOnT() {
598         return dependsOnT;
599     }
600
601     /**
602      * @param blockType block type
603      */
604     public void setBlockType(String blockType) {
605                 if ((this.blockType == null && blockType != null)
606                                 || !this.blockType.equals(blockType)) {
607                         
608                         final String oldValue = this.blockType;
609                         this.blockType = blockType;
610                         parametersPCS.firePropertyChange(BLOCK_TYPE, oldValue, blockType);
611                 }
612     }
613
614     /**
615      * @return block type
616      */
617     public String getBlockType() {
618         return blockType;
619     }
620
621     /**
622      * @param ordering order value
623      */
624     public void setOrdering(int ordering) {
625                 if (this.ordering != ordering) {
626                         
627                         final int oldValue = this.ordering;
628                         this.ordering = ordering;
629                         parametersPCS.firePropertyChange(ORDERING, oldValue, ordering);
630                 }
631     }
632
633     /**
634      * @return order value
635      */
636     public int getOrdering() {
637         return ordering;
638     }
639
640     /**
641      * @param exprs expression
642      */
643     public void setExprs(ScilabType exprs) {
644                 if ((this.exprs == null && exprs != null)
645                                 || !this.exprs.equals(exprs)) {
646                         
647                         final ScilabType oldValue = this.exprs;
648                         this.exprs = exprs;
649                         parametersPCS.firePropertyChange(EXPRS, oldValue, exprs);
650                 }
651     }
652
653     /**
654      * @return expression
655      */
656     public ScilabType getExprs() {
657         return exprs;
658     }
659
660     /**
661      * @return the expression as a object array
662      */
663     public String[] getExprsFormat() {
664         // evaluate emptiness
665                 if (getExprs() == null || getExprs().isEmpty()
666                                 || getExprs().getHeight() == 0 || getExprs().getWidth() == 0) {
667                         return new String[0];
668                 }
669         
670                 // only ScilabString is handled
671                 if (!(getExprs() instanceof ScilabString)) {
672                         return new String[0];
673                 }
674                 String[][] scilabData = ((ScilabString) getExprs()).getData();
675                 
676         // normal case
677                 final String[] array = new String[getExprs().getHeight() * getExprs().getWidth()];
678                 final int width = scilabData[0].length;
679                 for (int i = 0; i < scilabData.length; ++i) {
680                         System.arraycopy(scilabData[i], 0, array, i * width, width);
681                 }
682                 
683                 return array;
684     }
685     
686     /**
687      * @return zero crossing value
688      */
689     public ScilabType getNbZerosCrossing() {
690         return nbZerosCrossing;
691     }
692
693     /**
694      * @param nbZerosCrossing zero crossing value
695      */
696     public void setNbZerosCrossing(ScilabType nbZerosCrossing) {
697                 if ((this.nbZerosCrossing == null && nbZerosCrossing != null)
698                                 || !this.nbZerosCrossing.equals(nbZerosCrossing)) {
699                         
700                         final ScilabType oldValue = this.nbZerosCrossing;
701                         this.nbZerosCrossing = nbZerosCrossing;
702                         parametersPCS.firePropertyChange(NB_ZEROS_CROSSING, oldValue, nbZerosCrossing);
703                 }
704     }
705
706     /**
707      * @return nmode
708      */
709     public ScilabType getNmode() {
710         return nmode;
711     }
712
713     /**
714      * @param nmode nmode
715      */
716     public void setNmode(ScilabType nmode) {
717                 if ((this.nmode == null && nmode != null)
718                                 || !this.nmode.equals(nmode)) {
719                         
720                         final ScilabType oldValue = this.nmode;
721                         this.nmode = nmode;
722                         parametersPCS.firePropertyChange(NMODE, oldValue, nmode);
723                 }
724     }
725
726     /**
727      * @return current state
728      */
729     public ScilabType getState() {
730         return state;
731     }
732
733     /**
734      * @param state new state
735      */
736     public void setState(ScilabType state) {
737                 if ((this.state == null && state != null)
738                                 || !this.state.equals(state)) {
739                         
740                         final ScilabType oldValue = this.state;
741                         this.state = state;
742                         parametersPCS.firePropertyChange(STATE, oldValue, state);
743                 }
744     }
745
746     /**
747      * @return current dstate
748      */
749     public ScilabType getDState() {
750         return dState;
751     }
752
753     /**
754      * @param dState new dstate
755      */
756     public void setDState(ScilabType dState) {
757                 if ((this.dState == null && dState != null)
758                                 || !this.dState.equals(dState)) {
759                         
760                         final ScilabType oldValue = this.dState;
761                         this.dState = dState;
762                         parametersPCS.firePropertyChange(D_STATE, oldValue, dState);
763                 }
764     }
765
766     /**
767      * @return current ostate
768      */
769     public ScilabType getODState() {
770         return oDState;
771     }
772
773     /**
774      * @param oDState new odstate
775      */
776     public void setODState(ScilabType oDState) {
777                 if ((this.oDState == null && oDState != null)
778                                 || !this.oDState.equals(oDState)) {
779                         
780                         final ScilabType oldValue = this.oDState;
781                         this.oDState = oDState;
782                         parametersPCS.firePropertyChange(O_D_STATE, oldValue, oDState);
783                 }
784     }
785
786     /**
787      * @return equations
788      */
789     public ScilabType getEquations() {
790         return equations;
791     }
792
793     /**
794      * @param equations equations
795      */
796     public void setEquations(ScilabType equations) {
797                 if ((this.equations == null && equations != null)
798                                 || !this.equations.equals(equations)) {
799                         
800                         final ScilabType oldValue = this.equations;
801                         this.equations = equations;
802                         parametersPCS.firePropertyChange(EQUATIONS, oldValue, equations);
803                 }
804     }
805
806     /**
807      * @return locked status
808      */
809     public synchronized boolean isLocked() {
810         return locked;
811     }
812
813     /**
814      * @param locked change locked status
815      */
816     public synchronized void setLocked(boolean locked) {
817         this.locked = locked;
818     }
819
820     /**
821      * @param port to remove
822      */
823     public void removePort(BasicPort port) {
824         if (port.getEdgeCount() != 0) {
825             getParentDiagram().removeCells(new Object[]{port.getEdgeAt(0)});
826         }
827         remove(port);
828     }
829     
830     /**
831      * Add a port on the block.
832      * @param port The port to be added to the block
833      */
834     public void addPort(BasicPort port) {
835         insert(port);
836         BlockPositioning.updateBlockView(this);
837         port.setOrdering(BasicBlockInfo.getAllTypedPorts(this, false, port.getClass()).size());
838     }
839
840         /**
841          * @return command ports initial state
842          */
843         public ScilabDouble getAllCommandPortsInitialStates() {
844                 final List<CommandPort> cmdPorts = BasicBlockInfo.getAllTypedPorts(
845                                 this, false, CommandPort.class);
846                 if (cmdPorts.isEmpty()) {
847                         return new ScilabDouble();
848                 }
849
850                 double[][] data = new double[cmdPorts.size()][1];
851                 for (int i = 0; i < cmdPorts.size(); ++i) {
852                         data[i][0] = cmdPorts.get(i).getInitialState();
853                 }
854
855                 return new ScilabDouble(data);
856         }
857
858     /**
859      * @return name and type of the simulation function
860      */
861     public ScilabType getSimulationFunctionNameAndType() {
862         if (getSimulationFunctionType() == SimulationFunctionType.DEFAULT) {
863             return new ScilabString(getSimulationFunctionName());
864         }
865         ScilabList data = new ScilabList();
866
867         data.add(new ScilabString(getSimulationFunctionName()));
868         data.add(new ScilabDouble(getSimulationFunctionType().getAsDouble()));
869
870         return data;
871     }
872
873     /**
874      * Does the block update and register on the undo manager 
875      * @param modifiedBlock the new settings
876      */
877     public void updateBlockSettings(BasicBlock modifiedBlock) {
878         /*
879                  * Update the block settings
880                  */
881                 updateFields(modifiedBlock);
882
883                 /*
884                  * Update the children ports
885                  */
886                 if (children != null) {
887                         updateChildren(modifiedBlock);
888                 }
889
890                 /*
891                  * If the block is in a superblock then update it.
892                  */
893                 if (getParentDiagram() instanceof SuperBlockDiagram) {
894                         SuperBlock parentBlock = ((SuperBlockDiagram) getParentDiagram())
895                                         .getContainer();
896                         parentBlock.getParentDiagram().fireEvent(
897                                         new mxEventObject(XcosEvent.SUPER_BLOCK_UPDATED,
898                                                         XcosConstants.EVENT_BLOCK_UPDATED, parentBlock));
899                 }
900     }
901
902         /**
903          * Update the instance field.
904          * 
905          * @param modifiedBlock the modified instance
906          */
907         private void updateFields(BasicBlock modifiedBlock) {
908                 setDependsOnT(modifiedBlock.isDependsOnT());
909                 setDependsOnU(modifiedBlock.isDependsOnU());
910                 setExprs(modifiedBlock.getExprs());
911
912                 setRealParameters(modifiedBlock.getRealParameters());
913                 setIntegerParameters(modifiedBlock.getIntegerParameters());
914                 setObjectsParameters(modifiedBlock.getObjectsParameters());
915
916                 setState(modifiedBlock.getState());
917                 setDState(modifiedBlock.getDState());
918                 setODState(modifiedBlock.getODState());
919
920                 setEquations(modifiedBlock.getEquations());
921         }
922
923         /**
924          * Update the children of the block.
925          * 
926          * @param modifiedBlock the new block instance
927          */
928         private void updateChildren(BasicBlock modifiedBlock) {
929                 /*
930                  * Checked as port classes only
931                  */
932                 @SuppressWarnings("unchecked")
933                 Set<Class< ? extends mxICell>> types = new HashSet<Class< ? extends mxICell>>(
934                                 Arrays.asList(InputPort.class, OutputPort.class,
935                                                 ControlPort.class, CommandPort.class));
936
937                 Map<Class< ? extends mxICell>, Deque<mxICell>> annotatedOlds = getTypedChildren(types);
938                 Map<Class< ? extends mxICell>, Deque<mxICell>> annotatedNews = modifiedBlock
939                                 .getTypedChildren(types);
940
941                 getParentDiagram().getModel().beginUpdate();
942                 try {
943                         for (Class< ? extends mxICell> klass : types) {
944                                 final Deque<mxICell> olds = annotatedOlds.get(klass);
945                                 final Deque<mxICell> news = annotatedNews.get(klass);
946
947                                 // updated ports
948                                 while (!olds.isEmpty() && !news.isEmpty()) {
949                                         mxICell previous = olds.poll();
950                                         mxICell modified = news.poll();
951
952                                         final int previousIndex = children.indexOf(previous);
953
954                                         // relink
955                                         if (previous.getEdgeCount() != 0) {
956                                                 final mxICell edge = previous.getEdgeAt(0);
957                                                 final boolean isOutgoing = previous == edge
958                                                                 .getTerminal(true);
959                                                 previous.removeEdge(edge, isOutgoing);
960                                                 modified.insertEdge(edge, isOutgoing);
961                                         }
962
963                                         getParentDiagram().removeCells(new Object[] {previous},
964                                                         false);
965                                         getParentDiagram().addCells(new Object[] {modified},
966                                                         this, previousIndex);
967                                 }
968
969                                 // removed ports
970                                 if (!olds.isEmpty()) {
971                                         getParentDiagram().removeCells(olds.toArray(), true);
972                                 }
973
974                                 // added ports
975                                 if (!news.isEmpty()) {
976                                         getParentDiagram().addCells(news.toArray(), this);
977                                 }
978                         }
979                 } finally {
980                         getParentDiagram().getModel().endUpdate();
981                 }
982         }
983         
984         /**
985          * Format the children as a typed map for the given class set.
986          * 
987          * @param types the classes to search for.
988          * @return a map which linked foreach type the corresponding cell list. 
989          */
990         private Map<Class< ? extends mxICell>, Deque<mxICell>> getTypedChildren(Set<Class< ? extends mxICell>> types) {
991                 Map<Class< ? extends mxICell>, Deque<mxICell>> oldPorts = new HashMap<Class< ? extends mxICell>, Deque<mxICell>>();
992                 
993                 // Allocate all types set
994                 for (Class< ? extends mxICell> type : types) {
995                         oldPorts.put(type, new LinkedList<mxICell>());
996                 }
997                 
998                 // sort children according to the ordering parameter (useful on scilab-5.2.x diagrams)
999                 Collections.sort(children, new Comparator<Object>() {
1000                         @Override
1001                         public int compare(Object o1, Object o2) {
1002                                 if (o1 instanceof BasicPort && o2 instanceof BasicPort) {
1003                                         return ((BasicPort) o1).getOrdering() - ((BasicPort) o2).getOrdering();
1004                                 } else {
1005                                         return 0;
1006                                 }
1007                         }
1008                 });
1009                 
1010                 // children lookup
1011                 for (Object cell : children) {
1012                         
1013                         Class< ? extends Object> klass = cell.getClass();
1014                         while (klass != null) {
1015                                 if (types.contains(klass)) {
1016                                         break;
1017                                 }
1018                                 klass = klass.getSuperclass();
1019                         }
1020                         
1021                         final Deque<mxICell> current = oldPorts.get(klass);
1022                         if (current != null) {
1023                                 current.add((mxICell) cell);
1024                         }
1025                 }
1026                 
1027                 return oldPorts;
1028         }
1029
1030     /**
1031      * @param context parent diagram context
1032      */
1033     public void openBlockSettings(String[] context) {
1034         
1035         if (getParentDiagram() instanceof PaletteDiagram) {
1036             return;
1037         }
1038         
1039         //prevent to open twice
1040         if (isLocked()) {
1041             return;
1042         }
1043         
1044         final File tempOutput;
1045         final File tempInput;
1046         final File tempContext;
1047         final BasicBlock currentBlock = this;
1048         
1049         try {
1050             tempInput = FileUtils.createTempFile();
1051
1052             // Write scs_m
1053             tempOutput = exportBlockStruct();
1054             // Write context
1055             tempContext = exportContext(context);
1056             
1057             final ActionListener action = new ActionListener() {
1058                         @Override
1059                         public void actionPerformed(ActionEvent e) {
1060                                 if (tempInput.exists()) {
1061                                         LOG.trace("Updating data.");
1062                                         
1063                                 // Now read new Block
1064                             BasicBlock modifiedBlock = new H5RWHandler(tempInput).readBlock();
1065                             updateBlockSettings(modifiedBlock);
1066                             
1067                             getParentDiagram().fireEvent(new mxEventObject(XcosEvent.ADD_PORTS, XcosConstants.EVENT_BLOCK_UPDATED, 
1068                                     currentBlock));
1069                             delete(tempInput);
1070                                 } else {
1071                                         LOG.trace("No needs to update data.");
1072                                 }
1073                                 
1074                             setLocked(false);
1075                             delete(tempOutput);
1076                             delete(tempContext);
1077                         }
1078                 };
1079                 
1080             try {
1081                         ScilabInterpreterManagement.asynchronousScilabExec(action, 
1082                                 "xcosBlockInterface", 
1083                                 tempOutput.getAbsolutePath(),
1084                                 tempInput.getAbsolutePath(),
1085                                 getInterfaceFunctionName().toCharArray(),
1086                                 "set",
1087                                 tempContext.getAbsolutePath());
1088                 } catch (InterpreterException e) {
1089                         LOG.error(e);
1090                 }
1091             setLocked(true);
1092
1093         } catch (IOException e) {
1094             LOG.error(e);
1095         }
1096     }
1097
1098     /**
1099      * @return exported file
1100      */
1101     protected File exportBlockStruct() {
1102
1103         // Write scs_m
1104         File tempOutput;
1105         try {
1106             tempOutput = FileUtils.createTempFile();
1107             tempOutput.deleteOnExit();
1108             
1109             new H5RWHandler(tempOutput).writeBlock(this);
1110             return tempOutput;
1111         } catch (IOException e) {
1112             e.printStackTrace();
1113         }
1114         return null;
1115     }
1116     
1117     /**
1118      * @param context parent diagram context
1119      * @return exported file
1120      */
1121     protected File exportContext(String[] context) {
1122
1123         // Write context
1124         try {
1125             File tempContext = FileUtils.createTempFile();
1126             tempContext.deleteOnExit();
1127             int contextFileId = H5Write.createFile(tempContext.getAbsolutePath());
1128             H5Write.writeInDataSet(contextFileId, "context", new ScilabString(context));
1129             H5Write.closeFile(contextFileId);
1130             return tempContext;
1131         } catch (IOException e) {
1132             e.printStackTrace();
1133         } catch (HDF5Exception e) {
1134             e.printStackTrace();
1135         }
1136         return null;
1137     }
1138     
1139     /**
1140      * @return tooltip text
1141      */
1142     public String getToolTipText() {
1143         StringBuilder result = new StringBuilder();
1144         result.append(ScilabGraphConstants.HTML_BEGIN);
1145         result.append("Block Name : " + getInterfaceFunctionName() + ScilabGraphConstants.HTML_NEWLINE);
1146         result.append("Simulation : " + getSimulationFunctionName() + ScilabGraphConstants.HTML_NEWLINE);
1147
1148         if (getParentDiagram() instanceof PaletteDiagram) {
1149             if (getIntegerParameters() != null) {
1150                 result.append("Integer parameters : " + getIntegerParameters() + ScilabGraphConstants.HTML_NEWLINE);
1151             }
1152             
1153             if (getRealParameters() != null && getRealParameters().getHeight() != 0 && getRealParameters().getWidth() != 0) {
1154                 result.append("Real parameters : " + getRealParameters() + ScilabGraphConstants.HTML_NEWLINE);
1155             }
1156             
1157             if (getObjectsParameters() != null) {
1158                 result.append("Object parameters : " + getObjectsParameters() + ScilabGraphConstants.HTML_NEWLINE);
1159             }
1160         } else {
1161             result.append("UID : " + getId() + ScilabGraphConstants.HTML_NEWLINE);
1162                 final int length = getStyle().length();
1163                 result.append("Style : ");
1164                 if (length > XcosConstants.MAX_CHAR_IN_STYLE) {
1165                         result.append(getStyle().substring(0, XcosConstants.MAX_CHAR_IN_STYLE));
1166                         result.append(XcosMessages.DOTS);
1167                 } else {
1168                         result.append(getStyle());
1169                 }
1170                 result.append(ScilabGraphConstants.HTML_NEWLINE);
1171             result.append("Flip : " + getFlip() + ScilabGraphConstants.HTML_NEWLINE);
1172             result.append("Mirror : " + getMirror() + ScilabGraphConstants.HTML_NEWLINE);
1173             result.append("Input ports : "
1174                         + BasicBlockInfo.getAllTypedPorts(this, false, InputPort.class).size() + ScilabGraphConstants.HTML_NEWLINE);
1175             result.append("Output ports : "
1176                         + BasicBlockInfo.getAllTypedPorts(this, false, OutputPort.class).size() + ScilabGraphConstants.HTML_NEWLINE);
1177             result.append("Control ports : "
1178                         + BasicBlockInfo.getAllTypedPorts(this, false, ControlPort.class).size() + ScilabGraphConstants.HTML_NEWLINE);
1179             result.append("Command ports : "
1180                         + BasicBlockInfo.getAllTypedPorts(this, false, CommandPort.class).size() + ScilabGraphConstants.HTML_NEWLINE);
1181         }
1182
1183         result.append("x : " + getGeometry().getX() + ScilabGraphConstants.HTML_NEWLINE);
1184         result.append("y : " + getGeometry().getY() + ScilabGraphConstants.HTML_NEWLINE);
1185         result.append("w : " + getGeometry().getWidth() + ScilabGraphConstants.HTML_NEWLINE);
1186         result.append("h : " + getGeometry().getHeight() + ScilabGraphConstants.HTML_NEWLINE);
1187         result.append(ScilabGraphConstants.HTML_END);
1188         return result.toString();
1189     }
1190
1191     /**
1192      * @param graph parent graph
1193      */
1194     public void openContextMenu(ScilabGraph graph) {
1195         ContextMenu menu = null;
1196         if (getParentDiagram() instanceof PaletteDiagram) {
1197             menu = createPaletteContextMenu(graph);
1198         } else {
1199             menu = createContextMenu(graph);
1200         }
1201         menu.setVisible(true);
1202     }
1203
1204     /**
1205      * @param graph parent graph
1206      * @return context menu
1207      */
1208     public ContextMenu createPaletteContextMenu(ScilabGraph graph) {
1209         ContextMenu menu = ScilabContextMenu.createContextMenu();
1210
1211         final List<XcosDiagram> allDiagrams = Xcos.getInstance().getDiagrams();
1212
1213         if (allDiagrams.size() == 0) {
1214             // No diagram opened: should never happen if Xcos opens an empty diagram when it is launched
1215             MenuItem addTo = ScilabMenuItem.createMenuItem();
1216
1217             addTo.setText(XcosMessages.ADDTO_NEW_DIAGRAM);
1218             addTo.setCallback(new CallBack(XcosMessages.ADDTO_NEW_DIAGRAM) {
1219                 @Override
1220                 public void callBack() {
1221                         
1222                     XcosDiagram theDiagram = new XcosDiagram();
1223                     BasicBlock block = (BasicBlock) BlockFactory.createClone(BasicBlock.this);
1224                     theDiagram.getModel().add(theDiagram.getDefaultParent(), block, 0);
1225                     mxGeometry geom = BasicBlock.this.getGeometry();
1226                     setDefaultPosition(geom);
1227                     theDiagram.getModel().setGeometry(block, geom);
1228                     
1229                     new XcosTab(theDiagram).setVisible(true);
1230                     BlockPositioning.updateBlockView(block);
1231                 }
1232             });
1233
1234             menu.add(addTo);
1235
1236         } else if (allDiagrams.size() == 1) {
1237             // A single diagram opened: add to this diagram
1238             MenuItem addTo = ScilabMenuItem.createMenuItem();
1239
1240             addTo.setText(XcosMessages.ADDTO + " " + allDiagrams.get(0).getParentTab().getName());
1241             final XcosDiagram theDiagram = allDiagrams.get(0);
1242             addTo.setCallback(new CallBack(theDiagram.getTitle()) {
1243                 private static final long serialVersionUID = -99601763227525686L;
1244
1245                 @Override
1246                 public void callBack() {
1247                     BasicBlock block = (BasicBlock) BlockFactory.createClone(BasicBlock.this);
1248                     theDiagram.getModel().add(theDiagram.getDefaultParent(), block, 0);
1249                     mxGeometry geom = BasicBlock.this.getGeometry();
1250                     setDefaultPosition(geom);
1251                     theDiagram.getModel().setGeometry(block, geom);
1252                     BlockPositioning.updateBlockView(block);
1253                     block.setParentDiagram(theDiagram);
1254                 }
1255             });
1256
1257             menu.add(addTo);
1258
1259         } else {
1260             // The user has to choose
1261             Menu addTo = ScilabMenu.createMenu();
1262
1263             addTo.setText(XcosMessages.ADDTO);
1264
1265             for (int i = 0; i < allDiagrams.size(); i++) {
1266                 MenuItem diagram = ScilabMenuItem.createMenuItem();
1267                 final XcosDiagram theDiagram = allDiagrams.get(i);
1268                 diagram.setText(allDiagrams.get(i).getParentTab().getName());
1269                 diagram.setCallback(new CallBack(theDiagram.getTitle()) {
1270                     private static final long serialVersionUID = 3345416658377835057L;
1271
1272                         @Override
1273                     public void callBack() {
1274                         BasicBlock block = (BasicBlock) BlockFactory.createClone(BasicBlock.this);
1275                         theDiagram.getModel().add(theDiagram.getDefaultParent(), block, 0);
1276                         mxGeometry geom = BasicBlock.this.getGeometry();
1277                     setDefaultPosition(geom);
1278                         theDiagram.getModel().setGeometry(block, geom);
1279                         BlockPositioning.updateBlockView(block);
1280                     }
1281                 });
1282                 addTo.add(diagram);
1283             }
1284
1285             menu.add(addTo);
1286         }
1287
1288
1289         menu.getAsSimpleContextMenu().addSeparator();
1290
1291         MenuItem help = ScilabMenuItem.createMenuItem();
1292         help.setText(XcosMessages.BLOCK_DOCUMENTATION);
1293         help.setCallback(new CallBack(XcosMessages.BLOCK_DOCUMENTATION) {
1294             private static final long serialVersionUID = -1480947262397441951L;
1295
1296                 @Override
1297             public void callBack() {
1298                 InterpreterManagement.requestScilabExec("help " + getInterfaceFunctionName());
1299             }
1300         });
1301         menu.add(help);
1302
1303         menu.setVisible(true);
1304
1305         ((SwingScilabContextMenu) menu.getAsSimpleContextMenu()).setLocation(
1306                 MouseInfo.getPointerInfo().getLocation().x, MouseInfo.getPointerInfo().getLocation().y);
1307         
1308         return menu;
1309     }
1310
1311     /**
1312      * @param graph parent graph
1313      * @return context menu
1314      */
1315     public ContextMenu createContextMenu(ScilabGraph graph) {
1316                 ContextMenu menu = ScilabContextMenu.createContextMenu();
1317                 Map<Class< ? extends DefaultAction>, Menu> menuList = new HashMap<Class< ? extends DefaultAction>, Menu>();
1318                 
1319                 MenuItem value = BlockParametersAction.createMenu(graph);
1320                 menuList.put(BlockParametersAction.class, value);
1321                 menu.add(value);
1322                 /*--- */
1323                 menu.getAsSimpleContextMenu().addSeparator();
1324                 /*--- */
1325                 value = CutAction.cutMenu(graph);
1326                 menuList.put(CutAction.class, value);
1327                 menu.add(value);
1328                 value = CopyAction.copyMenu(graph);
1329                 menuList.put(CopyAction.class, value);
1330                 menu.add(value);
1331                 value = DeleteAction.createMenu(graph);
1332                 menuList.put(DeleteAction.class, value);
1333                 menu.add(value);
1334                 /*--- */
1335                 menu.getAsSimpleContextMenu().addSeparator();
1336                 /*--- */
1337                 value = RegionToSuperblockAction.createMenu(graph);
1338                 menuList.put(RegionToSuperblockAction.class, value);
1339                 menu.add(value);
1340                 /*--- */
1341                 menu.getAsSimpleContextMenu().addSeparator();
1342                 /*--- */
1343                 Menu format = ScilabMenu.createMenu();
1344                 format.setText(XcosMessages.FORMAT);
1345                 menu.add(format);
1346                 value = RotateAction.createMenu(graph);
1347                 menuList.put(RotateAction.class, value);
1348                 format.add(value);
1349                 value = MirrorAction.createMenu(graph);
1350                 menuList.put(MirrorAction.class, value);
1351                 format.add(value);
1352                 value = FlipAction.createMenu(graph);
1353                 menuList.put(FlipAction.class, value);
1354                 format.add(value);
1355                 value = ShowHideShadowAction.createMenu(graph);
1356                 menuList.put(ShowHideShadowAction.class, value);
1357                 format.add(value);
1358                 /*--- */
1359                 format.addSeparator();
1360                 /*--- */
1361                 Menu alignMenu = ScilabMenu.createMenu();
1362                 alignMenu.setText(XcosMessages.ALIGN_BLOCKS);
1363                 alignMenu.add(AlignBlockActionLeft.createMenu(graph));
1364                 alignMenu.add(AlignBlockActionCenter.createMenu(graph));
1365                 alignMenu.add(AlignBlockActionRight.createMenu(graph));
1366                 alignMenu.addSeparator();
1367                 alignMenu.add(AlignBlockActionTop.createMenu(graph));
1368                 alignMenu.add(AlignBlockActionMiddle.createMenu(graph));
1369                 alignMenu.add(AlignBlockActionBottom.createMenu(graph));
1370                 menuList.put(AlignBlockAction.class, alignMenu);
1371                 format.add(alignMenu);
1372                 /*--- */
1373                 format.addSeparator();
1374                 /*--- */
1375                 if (graph.getSelectionCells().length > 1) {
1376                         format.add(BorderColorAction.createMenu(graph));
1377                         format.add(FilledColorAction.createMenu(graph));
1378                 } else {
1379                         format.add(EditFormatAction.createMenu(graph));
1380                 }
1381                 /*--- */
1382                 menu.getAsSimpleContextMenu().addSeparator();
1383                 /*--- */
1384                 menu.add(ViewDetailsAction.createMenu(graph));
1385                 /*--- */
1386                 menu.getAsSimpleContextMenu().addSeparator();
1387                 /*--- */
1388                 menu.add(BlockDocumentationAction.createMenu(graph));
1389
1390                 ((SwingScilabContextMenu) menu.getAsSimpleContextMenu()).setLocation(MouseInfo.getPointerInfo().getLocation().x, 
1391                         MouseInfo.getPointerInfo().getLocation().y);
1392                 
1393                 customizeMenu(menuList);
1394                 
1395                 return menu;
1396     }
1397     
1398     /**
1399      * @param flip value
1400      */
1401         public void setFlip(boolean flip) {
1402                 if (getParentDiagram() != null) {
1403                         isFlipped = flip;
1404                         final mxIGraphModel model = getParentDiagram().getModel();
1405                         mxUtils.setCellStyles(model, new Object[] { this },
1406                                         ScilabGraphConstants.STYLE_FLIP, Boolean.toString(flip));
1407                 }
1408         }
1409
1410     /**
1411      * Override this to customize contextual menu
1412      * @param menuList list of menu
1413      */
1414     protected void customizeMenu(Map<Class< ? extends DefaultAction>, Menu> menuList) {
1415         // To be overridden by sub-classes
1416     }
1417     
1418
1419     /**
1420      * @return mirror value
1421      */
1422     public boolean getMirror() {
1423         return isMirrored;
1424     }
1425     
1426     /**
1427      * @param mirror new mirror value
1428      */
1429         public void setMirror(boolean mirror) {
1430                 if (getParentDiagram() != null) {
1431                         isMirrored = mirror;
1432                         final mxIGraphModel model = getParentDiagram().getModel();
1433                         mxUtils.setCellStyles(model, new Object[] { this },
1434                                         ScilabGraphConstants.STYLE_MIRROR, Boolean.toString(mirror));
1435                 }
1436         }
1437
1438     /**
1439      * @return flip status
1440      */
1441     public boolean getFlip() {
1442         return isFlipped;
1443     }
1444
1445     /**
1446      * invert flip status
1447      */
1448     public void toggleFlip() {
1449         BlockPositioning.toggleFlip(this);
1450     }
1451
1452     /**
1453      * invert mirror value
1454      */
1455     public void toggleMirror() {
1456         BlockPositioning.toggleMirror(this);
1457     }
1458
1459     /**
1460      * 
1461      */
1462     public void toggleAntiClockwiseRotation() {
1463         BlockPositioning.toggleAntiClockwiseRotation(this);
1464
1465     }
1466
1467     /**
1468      * @return current angle
1469      */
1470     public int getAngle() {
1471         return angle;
1472     }
1473
1474     /**
1475      * @param angle new block angle
1476      */
1477     public void setAngle(int angle) {
1478         this.angle = angle;
1479         
1480         if (getParentDiagram() != null) {
1481             mxUtils.setCellStyles(getParentDiagram().getModel(), new Object[] {this}, mxConstants.STYLE_ROTATION, Integer.toString(angle));
1482         }
1483     }
1484
1485     /**
1486      * Useful when we need to update local properties with mxCell style properties 
1487      */
1488         public void updateFieldsFromStyle() {
1489                 StyleMap map = new StyleMap(getStyle());
1490
1491                 if (map.get(mxConstants.STYLE_ROTATION) != null) {
1492                         angle = Integer.parseInt(map.get(mxConstants.STYLE_ROTATION));
1493                 } else {
1494                         angle = 0;
1495                 }
1496                 
1497                 isFlipped = Boolean.parseBoolean(map.get(ScilabGraphConstants.STYLE_FLIP));
1498                 isMirrored = Boolean.parseBoolean(map.get(ScilabGraphConstants.STYLE_MIRROR));
1499         }
1500
1501         /**
1502          * Set the default block position on the geom
1503          * @param geom the current geom
1504          */
1505         private void setDefaultPosition(mxGeometry geom) {
1506                 geom.setX(DEFAULT_POSITION_X);
1507                 geom.setY(DEFAULT_POSITION_Y);
1508         }
1509         
1510         /**
1511          * Get the parameters change support.
1512          * 
1513          * The property name for each event is the field name, so one of:
1514          *     - "interfaceFunctionName"
1515          *     - "simulationFunctionName"
1516          *     - "simulationFunctionType"
1517          *     - "exprs"
1518          *     - "realParameters"
1519          *     - "integerParameters"
1520          *     - "objectsParameters"
1521          *     - "nbZerosCrossing"
1522          *     - "nmode"
1523          *     - "state"
1524          *     - "dState"
1525          *     - "oDState"
1526          *     - "equations"
1527          *     - "dependsOnU"
1528          *     - "dependsOnT"
1529          *     - "blockType"
1530          *     - "ordering"
1531          * 
1532          * @return the associated {@link PropertyChangeSupport} instance
1533          */
1534         protected PropertyChangeSupport getParametersPCS() {
1535                 return parametersPCS;
1536         }
1537         
1538     /*
1539      * Overriden methods from jgraphx
1540      */
1541     
1542     /**
1543      * @return always false
1544      * @see com.mxgraph.model.mxCell#isConnectable()
1545      */
1546     @Override
1547     public boolean isConnectable() {
1548         return false;
1549     }
1550         
1551         /**
1552          * Re-associate fields with the new instance.
1553          * 
1554          * @return a new clone instance
1555          * @throws CloneNotSupportedException never
1556          * @see com.mxgraph.model.mxCell#clone()
1557          */
1558         @Override
1559         public Object clone() throws CloneNotSupportedException {
1560                 BasicBlock clone = (BasicBlock) super.clone();
1561                 
1562                 /* Reinstall the PropertyChangeSupport and all of it listeners */
1563                 clone.parametersPCS = new PropertyChangeSupport(clone);
1564                 PropertyChangeSupport pcs = getParametersPCS();
1565                 for (PropertyChangeListener iter : pcs.getPropertyChangeListeners()) {
1566                         clone.parametersPCS.addPropertyChangeListener(iter);
1567                 }
1568                 
1569                 return clone;
1570         }
1571         
1572         /**
1573          * Overriden to correct jgraphx bug fixed in 1.4.0.4
1574          * 
1575          * @param child the child to insert
1576          * @return the previous child
1577          * @see com.mxgraph.model.mxCell#insert(com.mxgraph.model.mxICell)
1578          * @see http://www.jgraphsupport.co.uk/bugzilla/show_bug.cgi?id=39
1579          * @deprecated Will be left after the switch to jgraphx >= 1.4.0.4
1580          */
1581         @Deprecated
1582         @Override
1583         public mxICell insert(mxICell child) {
1584                 int index = getChildCount();
1585                 
1586                 if (child.getParent() == this) {
1587                         index--;
1588                 }
1589                 
1590                 return insert(child, index);
1591         }
1592 }