0987faa97406d656c7e360cfdcf3f3a667b116a6
[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
16 import java.awt.MouseInfo;
17 import java.io.File;
18 import java.io.IOException;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 import ncsa.hdf.hdf5lib.exceptions.HDF5Exception;
24
25 import org.scilab.modules.action_binding.InterpreterManagement;
26 import org.scilab.modules.graph.ScilabGraph;
27 import org.scilab.modules.graph.actions.CopyAction;
28 import org.scilab.modules.graph.actions.CutAction;
29 import org.scilab.modules.graph.actions.DefaultAction;
30 import org.scilab.modules.graph.actions.DeleteAction;
31 import org.scilab.modules.gui.bridge.contextmenu.SwingScilabContextMenu;
32 import org.scilab.modules.gui.contextmenu.ContextMenu;
33 import org.scilab.modules.gui.contextmenu.ScilabContextMenu;
34 import org.scilab.modules.gui.events.callback.CallBack;
35 import org.scilab.modules.gui.menu.Menu;
36 import org.scilab.modules.gui.menu.ScilabMenu;
37 import org.scilab.modules.gui.menuitem.MenuItem;
38 import org.scilab.modules.gui.menuitem.ScilabMenuItem;
39 import org.scilab.modules.hdf5.scilabTypes.ScilabDouble;
40 import org.scilab.modules.hdf5.scilabTypes.ScilabList;
41 import org.scilab.modules.hdf5.scilabTypes.ScilabString;
42 import org.scilab.modules.hdf5.scilabTypes.ScilabType;
43 import org.scilab.modules.hdf5.write.H5Write;
44 import org.scilab.modules.xcos.Xcos;
45 import org.scilab.modules.xcos.XcosUIDObject;
46 import org.scilab.modules.xcos.actions.ShowHideShadowAction;
47 import org.scilab.modules.xcos.block.actions.AlignBlockAction;
48 import org.scilab.modules.xcos.block.actions.BlockDocumentationAction;
49 import org.scilab.modules.xcos.block.actions.BlockParametersAction;
50 import org.scilab.modules.xcos.block.actions.ColorAction;
51 import org.scilab.modules.xcos.block.actions.FlipAction;
52 import org.scilab.modules.xcos.block.actions.MirrorAction;
53 import org.scilab.modules.xcos.block.actions.RegionToSuperblockAction;
54 import org.scilab.modules.xcos.block.actions.RotateAction;
55 import org.scilab.modules.xcos.block.actions.ViewDetailsAction;
56 import org.scilab.modules.xcos.graph.PaletteDiagram;
57 import org.scilab.modules.xcos.graph.SuperBlockDiagram;
58 import org.scilab.modules.xcos.graph.XcosDiagram;
59 import org.scilab.modules.xcos.io.BasicBlockInfo;
60 import org.scilab.modules.xcos.io.BlockReader;
61 import org.scilab.modules.xcos.port.BasicPort;
62 import org.scilab.modules.xcos.port.command.CommandPort;
63 import org.scilab.modules.xcos.port.control.ControlPort;
64 import org.scilab.modules.xcos.port.input.InputPort;
65 import org.scilab.modules.xcos.port.output.OutputPort;
66 import org.scilab.modules.xcos.utils.BlockPositioning;
67 import org.scilab.modules.xcos.utils.Signal;
68 import org.scilab.modules.xcos.utils.XcosConstants;
69 import org.scilab.modules.xcos.utils.XcosEvent;
70 import org.scilab.modules.xcos.utils.XcosMessages;
71
72 import com.mxgraph.model.mxGeometry;
73 import com.mxgraph.util.mxConstants;
74 import com.mxgraph.util.mxEventObject;
75 import com.mxgraph.util.mxUtils;
76 import com.mxgraph.view.mxCellState;
77
78 public class BasicBlock extends XcosUIDObject {
79
80     private static final long serialVersionUID = 2189690915516168262L;
81     private String interfaceFunctionName = "xcos_block";
82     private String simulationFunctionName = "xcos_simulate";
83     private SimulationFunctionType simulationFunctionType = SimulationFunctionType.DEFAULT;
84     private transient XcosDiagram parentDiagram = null;
85     
86     private transient int angle = 0;
87     private transient boolean isFlipped = false;
88     private transient boolean isMirrored = false;
89     
90
91     // TODO : Must make this types evolve, but for now keep a strong link to Scilab
92     // !! WARNING !!
93     // exprs = [] ; rpar = [] ; ipar = [] ; opar = list()
94
95     //private List<String> exprs = new ArrayList<String>();
96     private ScilabType exprs = null;
97     //private List<Double> realParameters = new ArrayList<Double>();
98     private ScilabType realParameters = null;
99     //private List<Integer> integerParameters = new ArrayList<Integer>();
100     private ScilabType integerParameters = null;
101     //private List objectsParameters = new ArrayList();
102     private ScilabType objectsParameters = null;
103
104     private ScilabType nbZerosCrossing = new ScilabDouble();
105
106     private ScilabType nmode = new ScilabDouble();
107
108     private ScilabType state = new ScilabDouble();
109     private ScilabType dState = new ScilabDouble();
110     private ScilabType oDState = new ScilabDouble();
111
112     private ScilabType equations = null;
113
114     private boolean dependsOnU = false;
115     private boolean dependsOnT = false;
116
117     private String blockType = "c";
118
119     private int ordering = 0;
120     private boolean locked = false;
121
122     public enum SimulationFunctionType {
123     ESELECT,
124     IFTHENELSE, 
125         DEFAULT,
126         TYPE_1,
127         TYPE_2,
128         TYPE_3,
129         C_OR_FORTRAN,
130         SCILAB,
131         UNKNOWN;
132
133         public static SimulationFunctionType convertScilabValue(int scilabValue) {
134             switch (scilabValue) {
135             case -2:
136             return ESELECT;
137             case -1:
138             return IFTHENELSE;
139             case 0:
140                 return DEFAULT;
141             case 1:
142                 return TYPE_1;
143             case 2:
144                 return TYPE_2;
145             case 3:
146                 return TYPE_3;
147             case 4:
148                 return C_OR_FORTRAN;
149             case 5:
150                 return SCILAB;
151             default:
152                 return UNKNOWN;
153             }
154         }
155
156         public double getAsDouble() {
157             switch (this) {
158             case ESELECT:
159             return -2.0;
160             case IFTHENELSE:
161             return -1.0;
162             case DEFAULT:
163                 return 0.0;
164             case TYPE_1:
165                 return 1.0;
166             case TYPE_2 :
167                 return 2.0;
168             case TYPE_3 :
169                 return 3.0;
170             case C_OR_FORTRAN:
171                 return 4.0;
172             case SCILAB:
173                 return 5.0;
174             default:
175                 return Double.NaN;
176             }
177         }
178     };
179
180     public static BasicBlock createBlock(String label) {
181         if (label.compareTo("TEXT_f") == 0) {
182             return new TextBlock(label);
183         }
184         if (label.compareTo("SUPER_f") == 0) {
185             return new SuperBlock(label);
186         }
187         if (label.compareTo("DSUPER") == 0) {
188             return new SuperBlock(label, true);
189         }
190         if (label.compareTo("CONST_m") == 0 || label.compareTo("CONST") == 0
191                 || label.compareTo("CONST_f") == 0) {
192             return new ConstBlock(label);
193         }
194         if (label.compareTo("AFFICH_m") == 0
195                 || label.compareTo("AFFICH_f") == 0) {
196             return new AfficheBlock(label);
197         }
198         if (label.compareTo("GAINBLK_f") == 0
199                 || label.compareTo("GAINBLK") == 0
200                 || label.compareTo("GAIN_f") == 0) {
201             return new GainBlock(label);
202         }
203         if (label.compareTo("IN_f") == 0) {
204             return new ExplicitInBlock(label);
205         }
206         if (label.compareTo("OUT_f") == 0) {
207             return new ExplicitOutBlock(label);
208         }
209         if (label.compareTo("INIMPL_f") == 0) {
210             return new ImplicitInBlock(label);
211         }
212         if (label.compareTo("OUTIMPL_f") == 0) {
213             return new ImplicitOutBlock(label);
214         }
215         if (label.compareTo("CLKINV_f") == 0) {
216             return new EventInBlock(label);
217         }
218         if (label.compareTo("CLKOUTV_f") == 0
219                 || label.compareTo("CLKOUT_f") == 0) {
220             return new EventOutBlock(label);
221         }
222         if (label.compareTo("SPLIT_f") == 0
223                 || label.compareTo("IMPSPLIT_f") == 0
224                 || label.compareTo("CLKSPLIT_f") == 0) {
225             return new SplitBlock(label);
226         } else {
227             return new BasicBlock(label);
228         }
229     }
230
231     public BasicBlock() {
232         super();
233         setVertex(false);
234         setVisible(false);
235     }
236
237     protected BasicBlock(String label) {
238         super();
239         setValue(label);
240         setStyle("");
241         setVertex(true);
242         setConnectable(false);
243         setGeometry(new mxGeometry(0,0,40,40));
244     }
245
246     protected BasicBlock(String label, String style) {
247         super();
248         setValue(label);
249         setStyle(style);
250         setVertex(true);
251         setConnectable(false);
252         setGeometry(new mxGeometry(0,0,40,40));
253     }
254
255     public XcosDiagram getParentDiagram() {
256         return parentDiagram;
257     }
258
259     public void setParentDiagram(XcosDiagram parentDiagram) {
260         this.parentDiagram = parentDiagram;
261     }
262
263     
264     public String getInterfaceFunctionName() {
265         return interfaceFunctionName;
266     }
267
268     public void setInterfaceFunctionName(String interfaceFunctionName) {
269         this.interfaceFunctionName = interfaceFunctionName;
270     }
271
272     public void setSimulationFunctionName(String simulationFunctionName) {
273         this.simulationFunctionName = simulationFunctionName;
274     }
275
276     public String getSimulationFunctionName() {
277         return simulationFunctionName;
278     }
279
280     public void setSimulationFunctionType(int scilabValue) {
281         this.simulationFunctionType = SimulationFunctionType.convertScilabValue(scilabValue);
282     }
283
284     public void setSimulationFunctionType(SimulationFunctionType simulationFunctionType) {
285         this.simulationFunctionType = simulationFunctionType;
286     }
287
288     public SimulationFunctionType getSimulationFunctionType() {
289         return simulationFunctionType;
290     }
291
292     public ScilabType getRealParameters() {
293         return realParameters;
294     }
295
296     public void setRealParameters(ScilabType realParameters) {
297         this.realParameters = realParameters;
298     } 
299
300     public ScilabType getIntegerParameters() {
301         return integerParameters;
302     }
303
304     public void setIntegerParameters(ScilabType integerParameters) {
305         this.integerParameters = integerParameters;
306     }
307
308     public ScilabType getObjectsParameters() {
309         return objectsParameters;
310     }
311
312     public void setObjectsParameters(ScilabType objectsParameters) {
313         this.objectsParameters = objectsParameters;
314     }
315
316     public void setDependsOnU(boolean dependsOnU) {
317         this.dependsOnU = dependsOnU;
318     }
319
320     public boolean isDependsOnU() {
321         return this.dependsOnU;
322        }
323     
324     public boolean dependsOnU() {
325         return dependsOnU;
326     }
327
328     public void setDependsOnT(boolean dependsOnT) {
329         this.dependsOnT = dependsOnT;
330     }
331
332     public boolean isDependsOnT() {
333         return this.dependsOnT;
334        }
335     public boolean dependsOnT() {
336         return dependsOnT;
337     }
338
339     public void setBlockType(String blockType) {
340         this.blockType = blockType;
341     }
342
343     public String getBlockType() {
344         return blockType;
345     }
346
347     public void setOrdering(int ordering) {
348         this.ordering = ordering;
349     }
350
351     public int getOrdering() {
352         return ordering;
353     }
354
355     public void setExprs(ScilabType exprs) {
356         this.exprs = exprs;
357     }
358
359     public ScilabType getExprs() {
360         return exprs;
361     }
362
363     public ScilabType getNbZerosCrossing() {
364         return nbZerosCrossing;
365     }
366
367     public void setNbZerosCrossing(ScilabType nbZerosCrossing) {
368         this.nbZerosCrossing = nbZerosCrossing;
369     }
370
371     public ScilabType getNmode() {
372         return nmode;
373     }
374
375     public void setNmode(ScilabType nmode) {
376         this.nmode = nmode;
377     }
378
379     public ScilabType getState() {
380         return state;
381     }
382
383     public void setState(ScilabType state) {
384         this.state = state;
385     }
386
387     public ScilabType getDState() {
388         return dState;
389     }
390
391     public void setDState(ScilabType state) {
392         dState = state;
393     }
394
395     public ScilabType getODState() {
396         return oDState;
397     }
398
399     public void setODState(ScilabType state) {
400         oDState = state;
401     }
402
403     public ScilabType getEquations() {
404         return equations;
405     }
406
407     public void setEquations(ScilabType equations) {
408         this.equations = equations;
409     }
410
411     public synchronized boolean isLocked() {
412         return locked;
413     }
414
415     public synchronized void setLocked(boolean locked) {
416         this.locked = locked;
417     }
418
419     public void removePort(BasicPort port){
420         if(port.getEdgeCount() != 0) {
421             getParentDiagram().removeCells(new Object[]{port.getEdgeAt(0)});
422         }
423         remove(port);
424     }
425     
426     public void addPort(InputPort port) {
427         insert(port);
428         BlockPositioning.updatePortsPosition(this);
429         port.setOrdering(BasicBlockInfo.getAllInputPorts(this, false).size());
430     }
431
432     public void addPort(OutputPort port) {
433         insert(port);
434         BlockPositioning.updatePortsPosition(this);
435         port.setOrdering(BasicBlockInfo.getAllOutputPorts(this, false).size());
436     }
437
438     public void addPort(CommandPort port) {
439         insert(port);
440         BlockPositioning.updatePortsPosition(this);
441         port.setOrdering(BasicBlockInfo.getAllCommandPorts(this, false).size());
442     }
443
444     public void addPort(ControlPort port) {
445         insert(port);
446         BlockPositioning.updatePortsPosition(this);
447         port.setOrdering(BasicBlockInfo.getAllControlPorts(this, false).size());
448     }
449
450     public ScilabDouble getAllCommandPortsInitialStates() {
451         if (BasicBlockInfo.getAllCommandPorts(this, false).isEmpty()) {
452             return new ScilabDouble();
453         }
454
455         double[][] data = new double[BasicBlockInfo.getAllCommandPorts(this, false).size()][1];
456         for (int i = 0 ; i < BasicBlockInfo.getAllCommandPorts(this, false).size() ; ++i) {
457             data[i][0] = BasicBlockInfo.getAllCommandPorts(this, false).get(i).getInitialState();
458         }
459
460         return new ScilabDouble(data);
461     }
462
463     public ScilabType getSimulationFunctionNameAndType() {
464         if (getSimulationFunctionType() == SimulationFunctionType.DEFAULT) {
465             return new ScilabString(getSimulationFunctionName());
466         }
467         ScilabList data = new ScilabList();
468
469         data.add(new ScilabString(getSimulationFunctionName()));
470         data.add(new ScilabDouble(getSimulationFunctionType().getAsDouble()));
471
472         return data;
473     }
474
475     /**
476      * Does the block update and register on the undo manager 
477      * @param modifiedBlock the new settings
478      */
479     public void updateBlockSettings(BasicBlock modifiedBlock) {
480         
481         /* TODO: emit changes on update */
482 //      mxUndoableEdit edit = new mxUndoableEdit(getParentDiagram().getModel()) {
483 //          public void dispatch()
484 //              {
485 //                      ((mxGraphModel) source).fireEvent(mxEvent.CHANGE,
486 //                                      new mxEventObject(new Object[] { changes }));
487 //              }
488 //      };
489 //      edit.add(new BlockChange(modifiedBlock, this));
490         
491         doUpdateBlockSettings(modifiedBlock);
492     }
493
494     /**
495      * Does the block update without using the undo manager 
496      * @param modifiedBlock the new settings
497      */
498     public void doUpdateBlockSettings(BasicBlock modifiedBlock) {
499         setDependsOnT(modifiedBlock.dependsOnT());
500         setDependsOnU(modifiedBlock.dependsOnU());
501         setExprs(modifiedBlock.getExprs());
502
503         setRealParameters(modifiedBlock.getRealParameters());
504         setIntegerParameters(modifiedBlock.getIntegerParameters());
505         setObjectsParameters(modifiedBlock.getObjectsParameters());
506
507         setState(modifiedBlock.getState());
508         setDState(modifiedBlock.getDState());
509         setODState(modifiedBlock.getODState());
510
511         setEquations(modifiedBlock.getEquations());
512
513
514         List<? extends BasicPort> modifiedPorts = null;
515         List<? extends BasicPort> ports = null;
516         
517         // Check if new input port have been added
518         if ((modifiedPorts = BasicBlockInfo.getAllInputPorts(modifiedBlock, false)).size() > (ports = BasicBlockInfo.getAllInputPorts(this, false)).size()) {
519             while((ports = BasicBlockInfo.getAllInputPorts(this, false)).size() < modifiedPorts.size()) {
520                 addPort((InputPort)modifiedPorts.get(ports.size()));
521             }
522         }
523         // Check if input ports have been removed
524         else if ((modifiedPorts = BasicBlockInfo.getAllInputPorts(modifiedBlock, false)).size() < (ports = BasicBlockInfo.getAllInputPorts(this, false)).size()) {
525             while((ports = BasicBlockInfo.getAllInputPorts(this, false)).size() > modifiedPorts.size()) {
526                 removePort((BasicPort)ports.get(ports.size() - 1));
527             }
528         }
529
530         // Check if new output port have been added
531         if ((modifiedPorts = BasicBlockInfo.getAllOutputPorts(modifiedBlock, false)).size() > (ports = BasicBlockInfo.getAllOutputPorts(this, false)).size()) {
532             while((ports = BasicBlockInfo.getAllOutputPorts(this, false)).size() < modifiedPorts.size()) {
533                 addPort((OutputPort)modifiedPorts.get(ports.size()));
534             }
535         }
536         // Check if output ports have been removed
537         else if ((modifiedPorts = BasicBlockInfo.getAllOutputPorts(modifiedBlock, false)).size() < (ports = BasicBlockInfo.getAllOutputPorts(this, false)).size()) {
538             while((ports = BasicBlockInfo.getAllOutputPorts(this, false)).size() > modifiedPorts.size()) {
539                 removePort((BasicPort)ports.get(ports.size() - 1));
540             }
541         }
542
543
544         // Check if new command port have been added
545         if ((modifiedPorts = BasicBlockInfo.getAllCommandPorts(modifiedBlock, false)).size() > (ports = BasicBlockInfo.getAllCommandPorts(this, false)).size()) {
546             while((ports = BasicBlockInfo.getAllCommandPorts(this, false)).size() < modifiedPorts.size()) {
547                 addPort((CommandPort)modifiedPorts.get(ports.size()));
548             }
549         }
550         // Check if command ports have been removed
551         else if ((modifiedPorts = BasicBlockInfo.getAllCommandPorts(modifiedBlock, false)).size() < (ports = BasicBlockInfo.getAllCommandPorts(this, false)).size()) {
552             while((ports = BasicBlockInfo.getAllCommandPorts(this, false)).size() > modifiedPorts.size()) {
553                 removePort((BasicPort)ports.get(ports.size() - 1));
554             }
555         }
556
557         // Check if new control port have been added
558         if ((modifiedPorts = BasicBlockInfo.getAllControlPorts(modifiedBlock, false)).size() > (ports = BasicBlockInfo.getAllControlPorts(this, false)).size()) {
559             while((ports = BasicBlockInfo.getAllControlPorts(this, false)).size() < modifiedPorts.size()) {
560                 addPort((ControlPort)modifiedPorts.get(ports.size()));
561             }
562         }
563         // Check if control ports have been removed
564         else if ((modifiedPorts = BasicBlockInfo.getAllControlPorts(modifiedBlock, false)).size() < (ports = BasicBlockInfo.getAllControlPorts(this, false)).size()) {
565             while((ports = BasicBlockInfo.getAllControlPorts(this, false)).size() > modifiedPorts.size()) {
566                 removePort((BasicPort)ports.get(ports.size() - 1));
567             }
568         }
569
570         /*
571          * If the block is in a superblock then update it.
572          */
573         if (getParentDiagram() instanceof SuperBlockDiagram) {
574             SuperBlock parentBlock = ((SuperBlockDiagram) getParentDiagram()).getContainer();
575             parentBlock.getParentDiagram().fireEvent(XcosEvent.SUPER_BLOCK_UPDATED,new mxEventObject(new Object[] { parentBlock }));
576         }
577         
578     }
579
580     public void openBlockSettings(String context[]) {
581         
582         if(getParentDiagram() instanceof PaletteDiagram) {
583             return;
584         }
585         
586         //prevent to open twice
587         if(isLocked()) {
588             return;
589         }
590         
591         final File tempOutput;
592         final File tempInput;
593         final File tempContext;
594         try {
595             tempInput = File.createTempFile("xcos",".h5");
596             tempInput.deleteOnExit();
597
598             // Write scs_m
599             tempOutput = exportBlockStruct();
600             // Write context
601             tempContext = exportContext(context);
602
603             String cmd;
604             
605             cmd = "xcosBlockInterface(\""+tempOutput.getAbsolutePath()+"\"";
606             cmd += ", \""+tempInput.getAbsolutePath()+"\"";
607             cmd += ", "+getInterfaceFunctionName();
608             cmd += ", \"set\"";
609             cmd += ", \""+tempContext.getAbsolutePath()+"\");";
610             
611             InterpreterManagement.putCommandInScilabQueue(cmd);
612             final BasicBlock currentBlock = this;
613             Thread launchMe = new Thread() {
614                 public void run() {
615                     Signal.wait(tempInput.getAbsolutePath());
616                     // Now read new Block
617                     BasicBlock modifiedBlock = BlockReader.readBlockFromFile(tempInput.getAbsolutePath());
618                     updateBlockSettings(modifiedBlock);
619                     getParentDiagram().fireEvent(XcosEvent.ADD_PORTS, new mxEventObject(new Object[] {currentBlock}));
620                     setLocked(false);
621                 }
622             };
623             launchMe.start();
624             setLocked(true);
625
626         } catch (IOException e) {
627             e.printStackTrace();
628         }
629     }
630
631     protected File exportBlockStruct() {
632
633         // Write scs_m
634         File tempOutput;
635         try {
636             tempOutput = File.createTempFile("xcos",".h5");
637             tempOutput.deleteOnExit();
638             int file_id = H5Write.createFile(tempOutput.getAbsolutePath());
639             H5Write.writeInDataSet(file_id, "scs_m", BasicBlockInfo.getAsScilabObj(this));
640             H5Write.closeFile(file_id);
641             return tempOutput;
642         } catch (IOException e) {
643             e.printStackTrace();
644         } catch (HDF5Exception e) {
645             e.printStackTrace();
646         }
647         return null;
648     }
649     
650     protected File exportContext(String[] context) {
651
652         // Write context
653         try {
654             File tempContext = File.createTempFile("xcos",".h5");
655             tempContext.deleteOnExit();
656             int context_file_id = H5Write.createFile(tempContext.getAbsolutePath());
657             H5Write.writeInDataSet(context_file_id, "context", new ScilabString(context));
658             H5Write.closeFile(context_file_id);
659             return tempContext;
660         } catch (IOException e) {
661             e.printStackTrace();
662         } catch (HDF5Exception e) {
663             e.printStackTrace();
664         }
665         return null;
666     }
667     
668     public String getToolTipText() {
669         StringBuffer result = new StringBuffer();
670         result.append("<html>");
671         result.append("Block Name : "+ getInterfaceFunctionName() + "<br>");
672         result.append("Simulation : "+ getSimulationFunctionName() + "<br>");
673
674         if(getParentDiagram() instanceof PaletteDiagram) {
675             if(getIntegerParameters() != null) {
676                 result.append("Integer parameters : "+ getIntegerParameters() + "<br>");
677             }
678             
679             if(getRealParameters() != null && getRealParameters().getHeight() != 0 && getRealParameters().getWidth() != 0) {
680                 result.append("Real parameters : "+ getRealParameters() + "<br>");
681             }
682             
683             if(getObjectsParameters() != null) {
684                 result.append("Object parameters : "+ getObjectsParameters() + "<br>");
685             }
686         } else {
687             result.append("UID : "+ getId() + "<br>");
688             result.append("Block Style : " + getStyle() + "<br>");
689             result.append("Flip : " + getFlip() + "<br>");
690             result.append("Mirror : " + getMirror() + "<br>");
691             result.append("Input ports : " + BasicBlockInfo.getAllInputPorts(this, false).size() + "<br>");
692             result.append("Output ports : " + BasicBlockInfo.getAllOutputPorts(this, false).size() + "<br>");
693             result.append("Control ports : " + BasicBlockInfo.getAllControlPorts(this, false).size() + "<br>");
694             result.append("Command ports : " + BasicBlockInfo.getAllCommandPorts(this, false).size() + "<br>");
695         }
696
697         result.append("x : " + getGeometry().getX() + "<br>");
698         result.append("y : " + getGeometry().getY() + "<br>");
699         result.append("w : " + getGeometry().getWidth() + "<br>");
700         result.append("h : " + getGeometry().getHeight() + "<br>");
701         result.append("</html>");
702         return result.toString();
703     }
704
705     public void openContextMenu(ScilabGraph graph) {
706         ContextMenu menu = null;
707         if(getParentDiagram() instanceof PaletteDiagram) {
708             menu = createPaletteContextMenu(graph);
709         } else {
710             menu = createContextMenu(graph);
711         }
712         menu.setVisible(true);
713     }
714
715     public ContextMenu createPaletteContextMenu(ScilabGraph graph) {
716         ContextMenu menu = ScilabContextMenu.createContextMenu();
717
718         final List<XcosDiagram> allDiagrams = Xcos.getDiagrams();
719
720         if (allDiagrams.size() == 0) {
721             // No diagram opened: should never happen if Xcos opens an empty diagram when it is launched
722             MenuItem addTo = ScilabMenuItem.createMenuItem();
723
724             addTo.setText(XcosMessages.ADDTO_NEW_DIAGRAM);
725             addTo.setCallback(new CallBack(XcosMessages.ADDTO_NEW_DIAGRAM) {
726                 private static final long serialVersionUID = 8370536280449900878L;
727
728                 public void callBack() {
729                     XcosDiagram theDiagram = Xcos.createEmptyDiagram();
730                     BasicBlock block = (BasicBlock)BasicBlock.this.createClone();
731                     theDiagram.getModel().add(theDiagram.getDefaultParent(), block, 0);
732                     mxGeometry geom = BasicBlock.this.getGeometry();
733                     geom.setX(10);
734                     geom.setY(10);
735                     theDiagram.getModel().setGeometry(block, geom);
736                     BlockPositioning.updateBlockView(block);
737                 }
738             });
739
740             menu.add(addTo);
741
742         } else if (allDiagrams.size() == 1) {
743             // A single diagram opened: add to this diagram
744             MenuItem addTo = ScilabMenuItem.createMenuItem();
745
746             addTo.setText(XcosMessages.ADDTO + " " + allDiagrams.get(0).getParentTab().getName());
747             final XcosDiagram theDiagram = allDiagrams.get(0);
748             addTo.setCallback(new CallBack(theDiagram.getTitle()) {
749                 private static final long serialVersionUID = -99601763227525686L;
750
751                 public void callBack() {
752                     BasicBlock block = (BasicBlock)BasicBlock.this.createClone();
753                     theDiagram.getModel().add(theDiagram.getDefaultParent(), block, 0);
754                     mxGeometry geom = BasicBlock.this.getGeometry();
755                     geom.setX(10);
756                     geom.setY(10);
757                     theDiagram.getModel().setGeometry(block, geom);
758                     BlockPositioning.updateBlockView(block);
759                     block.setParentDiagram(theDiagram);
760                 }
761             });
762
763             menu.add(addTo);
764
765         } else {
766             // The user has to choose
767             Menu addTo = ScilabMenu.createMenu();
768
769             addTo.setText(XcosMessages.ADDTO);
770
771             for (int i = 0; i < allDiagrams.size(); i++) {
772                 MenuItem diagram = ScilabMenuItem.createMenuItem();
773                 final XcosDiagram theDiagram = allDiagrams.get(i);
774                 diagram.setText(allDiagrams.get(i).getParentTab().getName());
775                 diagram.setCallback(new CallBack(theDiagram.getTitle()) {
776                     private static final long serialVersionUID = 3345416658377835057L;
777
778                     public void callBack() {
779                         BasicBlock block = (BasicBlock)BasicBlock.this.createClone();
780                         theDiagram.getModel().add(theDiagram.getDefaultParent(), block, 0);
781                         mxGeometry geom = BasicBlock.this.getGeometry();
782                         geom.setX(10);
783                         geom.setY(10);
784                         theDiagram.getModel().setGeometry(block, geom);
785                         BlockPositioning.updateBlockView(block);
786                     }
787                 });
788                 addTo.add(diagram);
789             }
790
791             menu.add(addTo);
792         }
793
794
795         menu.getAsSimpleContextMenu().addSeparator();
796
797         MenuItem help = ScilabMenuItem.createMenuItem();
798         help.setText(XcosMessages.BLOCK_DOCUMENTATION);
799         help.setCallback(new CallBack(XcosMessages.BLOCK_DOCUMENTATION) {
800             private static final long serialVersionUID = -1480947262397441951L;
801
802             public void callBack() {
803                 InterpreterManagement.requestScilabExec("help " + getInterfaceFunctionName());
804             }
805         });
806         menu.add(help);
807
808         menu.setVisible(true);
809
810         ((SwingScilabContextMenu) menu.getAsSimpleContextMenu()).setLocation(
811                 MouseInfo.getPointerInfo().getLocation().x, MouseInfo.getPointerInfo().getLocation().y);
812         
813         return menu;
814     }
815
816     public ContextMenu createContextMenu(ScilabGraph graph) {
817                 ContextMenu menu = ScilabContextMenu.createContextMenu();
818                 Map<Class<? extends DefaultAction>, Menu> menuList = new HashMap<Class<? extends DefaultAction>, Menu>();
819                 
820                 MenuItem value = BlockParametersAction.createMenu(graph);
821                 menuList.put(BlockParametersAction.class, value);
822                 menu.add(value);
823                 /*--- */
824                 menu.getAsSimpleContextMenu().addSeparator();
825                 /*--- */
826                 value = CutAction.cutMenu(graph);
827                 menuList.put(CutAction.class, value);
828                 menu.add(value);
829                 value = CopyAction.copyMenu(graph);
830                 menuList.put(CopyAction.class, value);
831                 menu.add(value);
832                 value = DeleteAction.createMenu(graph);
833                 menuList.put(DeleteAction.class, value);
834                 menu.add(value);
835                 /*--- */
836                 menu.getAsSimpleContextMenu().addSeparator();
837                 /*--- */
838                 value = RegionToSuperblockAction.createMenu(graph);
839                 menuList.put(RegionToSuperblockAction.class, value);
840                 menu.add(value);
841 //              Menu mask = ScilabMenu.createMenu();
842 //              mask.setText(XcosMessages.SUPERBLOCK_MASK);
843 //              menu.add(mask);
844 //              mask.add(SuperblockMaskCreateAction.createMenu(graph));
845 //              mask.add(SuperblockMaskRemoveAction.createMenu(graph));
846                 /*--- */
847                 menu.getAsSimpleContextMenu().addSeparator();
848                 /*--- */
849                 Menu format = ScilabMenu.createMenu();
850                 format.setText(XcosMessages.FORMAT);
851                 menu.add(format);
852                 value = RotateAction.createMenu(graph);
853                 menuList.put(RotateAction.class, value);
854                 format.add(value);
855                 value = MirrorAction.createMenu(graph);
856                 menuList.put(MirrorAction.class, value);
857                 format.add(value);
858                 value = FlipAction.createMenu(graph);
859                 menuList.put(FlipAction.class, value);
860                 format.add(value);
861                 value = ShowHideShadowAction.createMenu(graph);
862                 menuList.put(ShowHideShadowAction.class, value);
863                 format.add(value);
864                 /*--- */
865                 format.addSeparator();
866                 /*--- */
867                 Menu alignMenu = ScilabMenu.createMenu();
868                 alignMenu.setText(XcosMessages.ALIGN_BLOCKS);
869                 alignMenu.add(AlignBlockAction.createMenu(graph, XcosMessages.ALIGN_LEFT, mxConstants.ALIGN_LEFT));
870                 alignMenu.add(AlignBlockAction.createMenu(graph, XcosMessages.ALIGN_CENTER, mxConstants.ALIGN_CENTER));
871                 alignMenu.add(AlignBlockAction.createMenu(graph, XcosMessages.ALIGN_RIGHT, mxConstants.ALIGN_RIGHT));
872                 alignMenu.addSeparator();
873                 alignMenu.add(AlignBlockAction.createMenu(graph, XcosMessages.ALIGN_TOP, mxConstants.ALIGN_TOP));
874                 alignMenu.add(AlignBlockAction.createMenu(graph, XcosMessages.ALIGN_MIDDLE, mxConstants.ALIGN_MIDDLE));
875                 alignMenu.add(AlignBlockAction.createMenu(graph, XcosMessages.ALIGN_BOTTOM, mxConstants.ALIGN_BOTTOM));
876                 menuList.put(AlignBlockAction.class, alignMenu);
877                 format.add(alignMenu);
878                 /*--- */
879                 format.addSeparator();
880                 /*--- */
881                 format.add(ColorAction.createMenu(graph, XcosMessages.BORDER_COLOR, mxConstants.STYLE_STROKECOLOR));
882                 format.add(ColorAction.createMenu(graph, XcosMessages.FILL_COLOR, mxConstants.STYLE_FILLCOLOR));
883                 /*--- */
884                 menu.getAsSimpleContextMenu().addSeparator();
885                 /*--- */
886                 menu.add(ViewDetailsAction.createMenu(graph));
887                 /*--- */
888                 menu.getAsSimpleContextMenu().addSeparator();
889                 /*--- */
890                 menu.add(BlockDocumentationAction.createMenu(graph));
891
892                 ((SwingScilabContextMenu) menu.getAsSimpleContextMenu()).setLocation(MouseInfo.getPointerInfo().getLocation().x, MouseInfo.getPointerInfo().getLocation().y);
893                 
894                 customizeMenu(menuList);
895                 
896                 return menu;
897     }
898     
899     public void setFlip(boolean flip) {
900         if(getParentDiagram() != null) {
901             isFlipped = flip;
902             if(flip == true) {
903                 mxUtils.setCellStyles(getParentDiagram().getModel(), new Object[] {this}, XcosConstants.STYLE_FLIP, "true");
904             } else {
905                 mxUtils.setCellStyles(getParentDiagram().getModel(), new Object[] {this}, XcosConstants.STYLE_FLIP, "false");
906             }
907         }
908     }
909
910     /**
911      * Override this to customize contextual menu
912      * @param menuList
913      */
914     protected void customizeMenu(Map<Class<? extends DefaultAction>, Menu> menuList) {
915         // To be overridden by sub-classes
916     }
917     
918
919     public boolean getMirror(){
920         return isMirrored;
921     }
922     
923     public void setMirror(boolean mirror) {
924         if(getParentDiagram() != null) {
925             isMirrored = mirror;
926             if(mirror == true) {
927                 mxUtils.setCellStyles(getParentDiagram().getModel(), new Object[] {this}, XcosConstants.STYLE_MIRROR, "true");
928             } else {
929                 mxUtils.setCellStyles(getParentDiagram().getModel(), new Object[] {this}, XcosConstants.STYLE_MIRROR, "false");
930             }
931         }
932     }
933
934     public boolean getFlip(){
935         return isFlipped;
936     }
937
938     public void toggleFlip() {
939         BlockPositioning.toggleFlip(this);
940     }
941
942     public void toggleMirror() {
943         BlockPositioning.toggleMirror(this);
944     }
945
946     public void toggleAntiClockwiseRotation() {
947         BlockPositioning.toggleAntiClockwiseRotation(this);
948
949     }
950     /**
951      * Create a clone for block added by context menu in palette
952      * @return the clone
953      */
954     public Object createClone() {
955         try {
956             BasicBlock clone = (BasicBlock) clone();
957
958             /* Clone children */
959             for (int i = 0; i < getChildCount(); i++) {
960                 if (getChildAt(i) instanceof InputPort) {
961                     clone.addPort((InputPort) getChildAt(i).clone());
962                 } else if (getChildAt(i) instanceof OutputPort) {
963                     clone.addPort((OutputPort) getChildAt(i).clone());
964                 } else if (getChildAt(i) instanceof CommandPort) {
965                     clone.addPort((CommandPort) getChildAt(i).clone());
966                 } else if (getChildAt(i) instanceof ControlPort) {
967                     clone.addPort((ControlPort) getChildAt(i).clone());
968                 }
969             }
970
971             return clone;
972         } catch (CloneNotSupportedException e) {
973             e.printStackTrace();
974             return null;
975         }
976     }
977
978     public int getAngle() {
979         return angle;
980     }
981
982     public void setAngle(int angle) {
983         this.angle = angle;
984         
985         if(getParentDiagram() != null) {
986             mxUtils.setCellStyles(getParentDiagram().getModel(), new Object[] {this}, XcosConstants.STYLE_ROTATION, new Integer(angle).toString());
987         }
988     }
989
990     /**
991      * Usefull when we need to update local properties with mxCell style properties 
992      */
993     public void updateFieldsFromStyle() {
994         if (getParentDiagram() != null) {
995             mxCellState state = getParentDiagram().getView().getState(this);
996             if(state != null) {
997                 // Angle field
998                 String  currentAngle = mxUtils.getString(state.getStyle(), XcosConstants.STYLE_ROTATION, "0");
999                 this.angle = Integer.parseInt(currentAngle);
1000             
1001                 // Flip field
1002                 String  currentFlip = mxUtils.getString(state.getStyle(), XcosConstants.STYLE_FLIP, "false");
1003                 if (currentFlip.compareTo("true") == 0) {
1004                     isFlipped = true;
1005                 } else {
1006                     isFlipped = false;
1007                 }
1008                 
1009                 // Mirror field
1010                 String  currentMirror = mxUtils.getString(state.getStyle(), XcosConstants.STYLE_MIRROR, "false");
1011                 if (currentMirror.compareTo("true") == 0) {
1012                     isMirrored = true;
1013                 } else {
1014                     isMirrored = false;
1015                 }
1016             }
1017             
1018         }
1019         
1020     }
1021 }