add load as palette option in palette browser
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / block / SuperBlock.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Bruno JOFRET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 package org.scilab.modules.xcos.block;
14
15 import java.util.ArrayList;
16 import java.util.List;
17
18 import org.scilab.modules.graph.ScilabGraph;
19 import org.scilab.modules.gui.contextmenu.ContextMenu;
20 import org.scilab.modules.gui.utils.UIElementMapper;
21 import org.scilab.modules.gui.window.ScilabWindow;
22 import org.scilab.modules.hdf5.scilabTypes.ScilabDouble;
23 import org.scilab.modules.hdf5.scilabTypes.ScilabList;
24 import org.scilab.modules.hdf5.scilabTypes.ScilabMList;
25 import org.scilab.modules.hdf5.scilabTypes.ScilabString;
26 import org.scilab.modules.xcos.PaletteDiagram;
27 import org.scilab.modules.xcos.Xcos;
28 import org.scilab.modules.xcos.XcosTab;
29 import org.scilab.modules.xcos.actions.CodeGenerationAction;
30 import org.scilab.modules.xcos.io.BasicBlockInfo;
31 import org.scilab.modules.xcos.io.BlockReader;
32 import org.scilab.modules.xcos.io.BlockWriter;
33 import org.scilab.modules.xcos.port.command.CommandPort;
34 import org.scilab.modules.xcos.port.control.ControlPort;
35 import org.scilab.modules.xcos.port.input.ExplicitInputPort;
36 import org.scilab.modules.xcos.port.input.ImplicitInputPort;
37 import org.scilab.modules.xcos.port.output.ExplicitOutputPort;
38 import org.scilab.modules.xcos.port.output.ImplicitOutputPort;
39 import org.scilab.modules.xcos.utils.XcosEvent;
40 import org.scilab.modules.xcos.utils.XcosMessages;
41
42 import com.mxgraph.model.mxCell;
43 import com.mxgraph.util.mxEventObject;
44
45 public class SuperBlock extends BasicBlock {
46
47     private SuperBlockDiagram child = null;
48  
49     public SuperBlock(){
50         super();
51         setVertex(false);
52         setVisible(false);
53     }
54
55     public SuperBlock(String label) {
56         super(label);
57         setInterfaceFunctionName("SUPER_f");
58         setSimulationFunctionName("super");
59         setRealParameters(new ScilabDouble());
60         setIntegerParameters(new ScilabDouble());
61         setObjectsParameters(new ScilabList());
62         setExprs(new ScilabDouble());
63         setBlockType("h");
64         setNbZerosCrossing(new ScilabDouble(0));
65         setNmode(new ScilabDouble(0));
66     }
67     
68     /**
69      * openBlockSettings
70      * this method is called when a double click occured on a super block
71      * /!\ WARNING /!\ this method must have the same signature as BasicBlock.openBlockSettings
72      * @see BasicBlock.openBlockSettings
73      * 
74      */
75     public void openBlockSettings(String[] context) {
76         if(getParentDiagram() instanceof PaletteDiagram) {
77             return;
78         }
79
80         if (getChild() == null && getSimulationFunctionType().compareTo(SimulationFunctionType.DEFAULT) != 0) {
81             // This means we have a SuperBlock and we generated C code for it.
82             this.setLocked(false);
83             return;
84         }
85
86         if(createChildDiagram() == true) {
87             getChild().setModified(false);
88             XcosTab.createTabFromDiagram(getChild());
89             XcosTab.showTabFromDiagram(getChild());
90         } else {
91             getChild().setVisible(true);
92         }
93         
94         
95         getChild().updateCellsContext();
96     }
97
98     public void closeBlockSettings() {
99
100         // Do not ask the user, the diagram is saved and closed
101         if (getChild().isModified()) {
102             setRealParameters(BlockWriter.convertDiagramToMList(getChild()));
103             getParentDiagram().setModified(true);
104             getChild().setModified(false);
105         }
106
107         if(getChild().canClose() == false) {
108             getChild().setVisible(false);
109             return;
110         }
111
112         if(getChild().getParentTab() != null) {
113             ScilabWindow xcosWindow = (ScilabWindow) UIElementMapper.getCorrespondingUIElement(getChild().getParentTab().getParentWindowId());
114             xcosWindow.removeTab(getChild().getParentTab());
115             getChild().getViewPort().close();
116             getChild().setOpened(false);
117             XcosTab.closeDiagram(getChild());
118             if(getParentDiagram().isOpened() && getParentDiagram().isVisible() == false) {
119                 getParentDiagram().closeDiagram();
120             }
121         }
122
123         child.removeListener(null);
124         setLocked(false);
125         child = null;
126     }
127
128     public void openContextMenu(ScilabGraph graph) {
129         ContextMenu menu = null;
130
131         if(getParentDiagram() instanceof PaletteDiagram) {
132             menu = createPaletteContextMenu(graph);
133         } else { 
134             menu = createContextMenu(graph);
135             menu.getAsSimpleContextMenu().addSeparator();
136             menu.add(CodeGenerationAction.createMenu(graph));
137         }
138         menu.setVisible(true);
139     }
140     
141     public boolean createChildDiagram(){
142         return createChildDiagram(false);
143     }
144
145     public boolean createChildDiagram(boolean generatedUID){
146         if (child == null) {
147             child = new SuperBlockDiagram(this);
148             child.installListeners();
149             child.loadDiagram(BlockReader.convertMListToDiagram((ScilabMList) getRealParameters(), false));
150             child.installSuperBlockListeners();
151             child.setChildrenParentDiagram();
152             updateAllBlocksColor();
153             //only for loading and generate sub block UID
154             if(generatedUID) {
155                 child.generateUID();
156             }
157         } else {
158                 return false;
159         }
160         
161         return true;
162     }
163     
164     public SuperBlockDiagram getChild() {
165         return child;
166     }
167
168     public void setChild(SuperBlockDiagram child) {
169         this.child = child;
170     }
171
172     public ScilabMList getAsScilabObj() {
173         if (child != null) {
174             setRealParameters(BlockWriter.convertDiagramToMList(child));
175         }
176         return BasicBlockInfo.getAsScilabObj(this);
177     }
178
179     protected List<mxCell> getAllExplicitInBlock(){
180         List<mxCell> list = new ArrayList<mxCell>();
181         if(child == null){
182             return list;
183         }
184
185         int blockCount = child.getModel().getChildCount(child.getDefaultParent());
186
187         for(int i = 0 ; i < blockCount ; i++){
188             mxCell cell = (mxCell)child.getModel().getChildAt(child.getDefaultParent(), i);
189             if(cell instanceof ExplicitInBlock){
190                 list.add(cell);
191             }
192         }
193         return list; 
194     }
195
196     protected List<mxCell> getAllImplicitInBlock(){
197         List<mxCell> list = new ArrayList<mxCell>();
198         if(child == null){
199             return list;
200         }
201
202         int blockCount = child.getModel().getChildCount(child.getDefaultParent());
203
204         for(int i = 0 ; i < blockCount ; i++){
205             mxCell cell = (mxCell)child.getModel().getChildAt(child.getDefaultParent(), i);
206             if(cell instanceof ImplicitInBlock){
207                 list.add(cell);
208             }
209         }
210         return list; 
211     }
212
213     protected List<mxCell> getAllEventInBlock(){
214         List<mxCell> list = new ArrayList<mxCell>();
215         if(child == null){
216             return list;
217         }
218
219         int blockCount = child.getModel().getChildCount(child.getDefaultParent());
220
221         for(int i = 0 ; i < blockCount ; i++){
222             mxCell cell = (mxCell)child.getModel().getChildAt(child.getDefaultParent(), i);
223             if(cell instanceof EventInBlock){
224                 list.add(cell);
225             }
226         }
227         return list; 
228     }
229
230     protected List<mxCell> getAllExplicitOutBlock(){
231         List<mxCell> list = new ArrayList<mxCell>();
232         if(child == null){
233             return list;
234         }
235
236         int blockCount = child.getModel().getChildCount(child.getDefaultParent());
237
238         for(int i = 0 ; i < blockCount ; i++){
239             mxCell cell = (mxCell)child.getModel().getChildAt(child.getDefaultParent(), i);
240             if(cell instanceof ExplicitOutBlock){
241                 list.add(cell);
242             }
243         }
244         return list; 
245     }
246
247     protected List<mxCell> getAllImplicitOutBlock(){
248         List<mxCell> list = new ArrayList<mxCell>();
249         if(child == null){
250             return list;
251         }
252
253         int blockCount = child.getModel().getChildCount(child.getDefaultParent());
254
255         for(int i = 0 ; i < blockCount ; i++){
256             mxCell cell = (mxCell)child.getModel().getChildAt(child.getDefaultParent(), i);
257             if(cell instanceof ImplicitOutBlock){
258                 list.add(cell);
259             }
260         }
261         return list; 
262     }
263
264     protected List<mxCell> getAllEventOutBlock(){
265         List<mxCell> list = new ArrayList<mxCell>();
266
267         int blockCount = child.getModel().getChildCount(child.getDefaultParent());
268
269         for(int i = 0 ; i < blockCount ; i++){
270             mxCell cell = (mxCell)child.getModel().getChildAt(child.getDefaultParent(), i);
271             if(cell instanceof EventOutBlock){
272                 list.add(cell);
273             }
274         }
275         return list; 
276     }
277
278     protected int getBlocksConsecutiveUniqueValueCount(List<mxCell> blocks){
279         if(blocks == null){
280                 return 0;
281         }
282
283         int count = blocks.size();
284         int[] array = new int[blocks.size()];
285
286         //initialize
287         for(int i = 0 ; i < array.length; i++){
288                 array[i] = 0;
289                 }
290         
291         //populate
292         for(int i = 0 ; i < array.length; i++){
293                 int index = (Integer)((BasicBlock)blocks.get(i)).getValue();
294                 if(index <= array.length){
295                         array[index - 1] = 1;   
296                 }
297         }
298         
299         //parse
300         for(int i = 0 ; i < array.length; i++){
301                 if(array[i] == 0){
302                         count = i;
303                         break;
304                 }
305         }
306         
307         return count;
308     }
309
310     protected void updateAllBlocksColor(){
311         updateBlocksColor(getAllExplicitInBlock());
312         updateBlocksColor(getAllImplicitInBlock());
313         updateBlocksColor(getAllEventInBlock());
314
315         updateBlocksColor(getAllExplicitOutBlock());
316         updateBlocksColor(getAllImplicitOutBlock());
317         updateBlocksColor(getAllEventOutBlock());
318     }
319     
320     private void updateBlocksColor(List<mxCell> blocks){
321
322         try{
323                 child.getModel().beginUpdate();
324                 if(blocks == null || blocks.size() == 0){
325                         return;
326                 }
327
328                 int countUnique = getBlocksConsecutiveUniqueValueCount(blocks);
329                 boolean isDone[] = new boolean[countUnique];
330
331                 //Initialize
332                 for(int i = 0 ; i < countUnique ; i++){
333                         isDone[i] = false;
334                 }
335
336
337                 for(int i = 0 ; i < blocks.size() ; i++){
338                         int index = (Integer)((BasicBlock)blocks.get(i)).getValue();
339                         if(index > countUnique || isDone[index - 1] == true){
340                                 child.getAsComponent().setCellWarning(blocks.get(i), "Wrong port number");
341                         }else{
342                                 isDone[index - 1] = true;
343                                 child.getAsComponent().setCellWarning(blocks.get(i), null);
344                         }
345                 }
346         }finally{
347                 child.getModel().endUpdate();
348         }
349     }
350
351     public void updateExportedPort(){
352         if(child == null){
353                 System.err.println("child == null");
354                 return;
355         }
356
357         updateExportedExplicitInputPort();
358         updateExportedImplicitInputPort();
359         updateExportedEventInputPort();
360         updateExportedExplicitOutputPort();
361         updateExportedImplicitOutputPort();
362         updateExportedEventOutputPort();
363         getParentDiagram().fireEvent(XcosEvent.SUPER_BLOCK_UPDATED, new mxEventObject(new Object[] {this}));
364     }
365
366
367     private void updateExportedExplicitInputPort(){
368         int blockCount = getBlocksConsecutiveUniqueValueCount(getAllExplicitInBlock());
369         List<ExplicitInputPort> ports = BasicBlockInfo.getAllExplicitInputPorts(this, false);
370
371         int portCount = ports.size();
372
373         while(blockCount > portCount){ //add if required
374                 ExplicitInputPort port = new ExplicitInputPort();
375                 port.setDataLines(-1);
376                 port.setDataColumns(-2);
377                 addPort(port);
378                 portCount++;
379         }
380
381         while(portCount > blockCount){ //remove if required
382                 removePort(ports.get(portCount - 1));
383                 portCount--;
384         }
385     }
386
387     private void updateExportedImplicitInputPort(){
388         int blockCount = getBlocksConsecutiveUniqueValueCount(getAllImplicitInBlock());
389         List<ImplicitInputPort> ports = BasicBlockInfo.getAllImplicitInputPorts(this, false);
390
391         int portCount = ports.size();
392
393         while(blockCount > portCount){ //add if required
394                 addPort(new ImplicitInputPort());
395                 portCount++;
396         }
397
398         while(portCount > blockCount){ //remove if required
399                 removePort(ports.get(portCount - 1));
400                 portCount--;
401         }
402     }
403
404     private void updateExportedEventInputPort(){
405         int blockCount = getBlocksConsecutiveUniqueValueCount(getAllEventInBlock());
406         List<ControlPort> ports = BasicBlockInfo.getAllControlPorts(this, false);
407
408         int portCount = ports.size();
409
410         while(blockCount > portCount){ //add if required
411                 addPort(new ControlPort());
412                 portCount++;
413         }
414
415         while(portCount > blockCount){ //remove if required
416                 removePort(ports.get(portCount - 1));
417                 portCount--;
418         }
419     }
420
421     private void updateExportedExplicitOutputPort(){
422         int blockCount = getBlocksConsecutiveUniqueValueCount(getAllExplicitOutBlock());
423         List<ExplicitOutputPort> ports = BasicBlockInfo.getAllExplicitOutputPorts(this, false);
424
425         int portCount = ports.size();
426
427         while(blockCount > portCount){ //add if required
428                 ExplicitOutputPort port = new ExplicitOutputPort();
429                 port.setDataLines(-1);
430                 port.setDataColumns(-2);
431                 addPort(port);
432                 portCount++;
433         }
434
435         while(portCount > blockCount){ //remove if required
436                 removePort(ports.get(portCount - 1));
437                 portCount--;
438         }
439     }
440
441     private void updateExportedImplicitOutputPort(){
442         int blockCount = getBlocksConsecutiveUniqueValueCount(getAllImplicitOutBlock());
443         List<ImplicitOutputPort> ports = BasicBlockInfo.getAllImplicitOutputPorts(this, false);
444
445         int portCount = ports.size();
446
447         while(blockCount > portCount){ //add if required
448                 addPort(new ImplicitOutputPort());
449                 portCount++;
450         }
451
452         while(portCount > blockCount){ //remove if required
453                 removePort(ports.get(portCount - 1));
454                 portCount--;
455         }
456     }
457
458     private void updateExportedEventOutputPort(){
459         int blockCount = getBlocksConsecutiveUniqueValueCount(getAllEventOutBlock());
460         List<CommandPort> ports = BasicBlockInfo.getAllCommandPorts(this, false);
461
462         int portCount = ports.size();
463
464         while(blockCount > portCount){ //add if required
465                 addPort(new CommandPort());
466                 portCount++;
467         }
468
469         while(portCount > blockCount){ //remove if required
470                 removePort(ports.get(portCount - 1));
471                 portCount--;
472         }
473     }
474 }