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