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