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