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