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