Checkstyle, comment
[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.menu.Menu;
21 import org.scilab.modules.gui.menu.ScilabMenu;
22 import org.scilab.modules.gui.utils.UIElementMapper;
23 import org.scilab.modules.gui.window.ScilabWindow;
24 import org.scilab.modules.hdf5.scilabTypes.ScilabDouble;
25 import org.scilab.modules.hdf5.scilabTypes.ScilabList;
26 import org.scilab.modules.hdf5.scilabTypes.ScilabMList;
27 import org.scilab.modules.xcos.XcosTab;
28 import org.scilab.modules.xcos.actions.CodeGenerationAction;
29 import org.scilab.modules.xcos.block.actions.SuperblockMaskCreateAction;
30 import org.scilab.modules.xcos.block.actions.SuperblockMaskCustomizeAction;
31 import org.scilab.modules.xcos.block.actions.SuperblockMaskRemoveAction;
32 import org.scilab.modules.xcos.block.io.EventInBlock;
33 import org.scilab.modules.xcos.block.io.EventOutBlock;
34 import org.scilab.modules.xcos.block.io.ExplicitInBlock;
35 import org.scilab.modules.xcos.block.io.ExplicitOutBlock;
36 import org.scilab.modules.xcos.block.io.ImplicitInBlock;
37 import org.scilab.modules.xcos.block.io.ImplicitOutBlock;
38 import org.scilab.modules.xcos.graph.PaletteDiagram;
39 import org.scilab.modules.xcos.graph.SuperBlockDiagram;
40 import org.scilab.modules.xcos.io.BasicBlockInfo;
41 import org.scilab.modules.xcos.io.BlockReader;
42 import org.scilab.modules.xcos.io.BlockWriter;
43 import org.scilab.modules.xcos.port.command.CommandPort;
44 import org.scilab.modules.xcos.port.control.ControlPort;
45 import org.scilab.modules.xcos.port.input.ExplicitInputPort;
46 import org.scilab.modules.xcos.port.input.ImplicitInputPort;
47 import org.scilab.modules.xcos.port.output.ExplicitOutputPort;
48 import org.scilab.modules.xcos.port.output.ImplicitOutputPort;
49 import org.scilab.modules.xcos.utils.XcosConstants;
50 import org.scilab.modules.xcos.utils.XcosEvent;
51 import org.scilab.modules.xcos.utils.XcosMessages;
52
53 import com.mxgraph.model.mxCell;
54 import com.mxgraph.util.mxEventObject;
55
56 public final class SuperBlock extends BasicBlock {
57
58         private static final long serialVersionUID = 3005281208417373333L;
59         private SuperBlockDiagram child = null;
60
61         public SuperBlock() {
62                 super();
63         }
64
65         protected SuperBlock(String label) {
66                 this();
67                 setDefaultValues();
68                 setValue(label);
69         }
70
71         protected SuperBlock(boolean masked) {
72                 this();
73                 if (masked) {
74                         mask();
75                 }
76         }
77         
78         protected SuperBlock(String label, boolean masked) {
79                 this(label);
80                 if (masked) {
81                         mask();
82                 }
83         }
84         
85         /**
86          * Initialize the block with the default values
87          */
88         @Override
89         protected void setDefaultValues() {
90                 super.setDefaultValues();
91                 setInterfaceFunctionName("SUPER_f");
92                 setSimulationFunctionName("super");
93                 setRealParameters(new ScilabDouble());
94                 setIntegerParameters(new ScilabDouble());
95                 setObjectsParameters(new ScilabList());
96                 setExprs(new ScilabDouble());
97                 setBlockType("h");
98                 setNbZerosCrossing(new ScilabDouble(0));
99                 setNmode(new ScilabDouble(0));
100         }
101
102         /**
103          * openBlockSettings this method is called when a double click occured on a
104          * super block 
105          * 
106          * @see BasicBlock.openBlockSettings
107          */
108         @Override
109         public void openBlockSettings(String[] context) {
110                 if (getParentDiagram() instanceof PaletteDiagram) {
111                         return;
112                 }
113
114                 if (getChild() == null
115                                 && getSimulationFunctionType().compareTo(
116                                                 SimulationFunctionType.DEFAULT) != 0) {
117                         // This means we have a SuperBlock and we generated C code for it.
118                         this.setLocked(false);
119                         return;
120                 }
121
122                 if (isMasked()) {
123                         super.openBlockSettings(context);
124                 } else {
125                         if (createChildDiagram() == true) {
126                                 getChild().setModifiedNonRecursively(false);
127                                 XcosTab.createTabFromDiagram(getChild());
128                                 XcosTab.showTabFromDiagram(getChild());
129                         } else {
130                                 getChild().setVisible(true);
131                         }
132
133                         getChild().updateCellsContext();
134                 }
135         }
136
137         public void closeBlockSettings() {
138
139                 // Do not ask the user, the diagram is saved and closed
140                 if (getChild().isModified()) {
141                         setRealParameters(BlockWriter.convertDiagramToMList(getChild()));
142                         getChild().setModified(true);
143                         getChild().setModifiedNonRecursively(false);
144                 }
145
146                 if (getChild().canClose() == false) {
147                         getChild().setVisible(false);
148                         return;
149                 }
150
151                 if (getChild().getParentTab() != null) {
152                         ScilabWindow xcosWindow = (ScilabWindow) UIElementMapper
153                                         .getCorrespondingUIElement(getChild().getParentTab()
154                                                         .getParentWindowId());
155                         xcosWindow.removeTab(getChild().getParentTab());
156                         getChild().getViewPort().close();
157                         getChild().setOpened(false);
158                         XcosTab.closeDiagram(getChild());
159                         if (getParentDiagram().isOpened()
160                                         && getParentDiagram().isVisible() == false) {
161                                 getParentDiagram().closeDiagram();
162                         }
163                 }
164
165                 child.removeListener(null);
166                 setLocked(false);
167                 child = null;
168         }
169
170         public void openContextMenu(ScilabGraph graph) {
171                 ContextMenu menu = null;
172
173                 if (getParentDiagram() instanceof PaletteDiagram) {
174                         menu = createPaletteContextMenu(graph);
175                 } else {
176                         menu = createContextMenu(graph);
177                         menu.getAsSimpleContextMenu().addSeparator();
178                         menu.add(CodeGenerationAction.createMenu(graph));
179
180                         /*
181                          * FIXME: It is not possible to use Mask. So remove any possibility.
182                          * Mask removing only option is not applicable : if remove the mask
183                          * you have no way to edit the values anymore.
184                          */
185                         Menu maskMenu = ScilabMenu.createMenu();
186                         maskMenu.setText(XcosMessages.SUPERBLOCK_MASK);
187
188                         if (isMasked()) {
189                                 maskMenu.add(SuperblockMaskRemoveAction.createMenu(graph));
190                                 menu.add(maskMenu);
191                         } else {
192                                 maskMenu.add(SuperblockMaskCreateAction.createMenu(graph));
193                         }
194                         maskMenu.add(SuperblockMaskCustomizeAction.createMenu(graph));
195                         menu.add(maskMenu);
196                          
197                 }
198                 menu.setVisible(true);
199         }
200
201         public boolean createChildDiagram() {
202                 return createChildDiagram(false);
203         }
204
205         public boolean createChildDiagram(boolean generatedUID) {
206                 if (child == null) {
207                         child = new SuperBlockDiagram(this);
208                         child.installListeners();
209                         child.loadDiagram(BlockReader.convertMListToDiagram(
210                                         (ScilabMList) getRealParameters(), false));
211                         child.installSuperBlockListeners();
212                         child.setChildrenParentDiagram();
213                         updateAllBlocksColor();
214                         // only for loading and generate sub block UID
215                         if (generatedUID) {
216                                 child.generateUID();
217                         }
218                 } else {
219                         return false;
220                 }
221
222                 return true;
223         }
224
225         public SuperBlockDiagram getChild() {
226                 return child;
227         }
228
229         public void setChild(SuperBlockDiagram child) {
230                 this.child = child;
231         }
232
233         public ScilabMList getAsScilabObj() {
234                 if (child != null) {
235                         setRealParameters(BlockWriter.convertDiagramToMList(child));
236                 }
237                 return BasicBlockInfo.getAsScilabObj(this);
238         }
239
240         protected List<mxCell> getAllExplicitInBlock() {
241                 List<mxCell> list = new ArrayList<mxCell>();
242                 if (child == null) {
243                         return list;
244                 }
245
246                 int blockCount = child.getModel().getChildCount(
247                                 child.getDefaultParent());
248
249                 for (int i = 0; i < blockCount; i++) {
250                         mxCell cell = (mxCell) child.getModel().getChildAt(
251                                         child.getDefaultParent(), i);
252                         if (cell instanceof ExplicitInBlock) {
253                                 list.add(cell);
254                         }
255                 }
256                 return list;
257         }
258
259         protected List<mxCell> getAllImplicitInBlock() {
260                 List<mxCell> list = new ArrayList<mxCell>();
261                 if (child == null) {
262                         return list;
263                 }
264
265                 int blockCount = child.getModel().getChildCount(
266                                 child.getDefaultParent());
267
268                 for (int i = 0; i < blockCount; i++) {
269                         mxCell cell = (mxCell) child.getModel().getChildAt(
270                                         child.getDefaultParent(), i);
271                         if (cell instanceof ImplicitInBlock) {
272                                 list.add(cell);
273                         }
274                 }
275                 return list;
276         }
277
278         protected List<mxCell> getAllEventInBlock() {
279                 List<mxCell> list = new ArrayList<mxCell>();
280                 if (child == null) {
281                         return list;
282                 }
283
284                 int blockCount = child.getModel().getChildCount(
285                                 child.getDefaultParent());
286
287                 for (int i = 0; i < blockCount; i++) {
288                         mxCell cell = (mxCell) child.getModel().getChildAt(
289                                         child.getDefaultParent(), i);
290                         if (cell instanceof EventInBlock) {
291                                 list.add(cell);
292                         }
293                 }
294                 return list;
295         }
296
297         protected List<mxCell> getAllExplicitOutBlock() {
298                 List<mxCell> list = new ArrayList<mxCell>();
299                 if (child == null) {
300                         return list;
301                 }
302
303                 int blockCount = child.getModel().getChildCount(
304                                 child.getDefaultParent());
305
306                 for (int i = 0; i < blockCount; i++) {
307                         mxCell cell = (mxCell) child.getModel().getChildAt(
308                                         child.getDefaultParent(), i);
309                         if (cell instanceof ExplicitOutBlock) {
310                                 list.add(cell);
311                         }
312                 }
313                 return list;
314         }
315
316         protected List<mxCell> getAllImplicitOutBlock() {
317                 List<mxCell> list = new ArrayList<mxCell>();
318                 if (child == null) {
319                         return list;
320                 }
321
322                 int blockCount = child.getModel().getChildCount(
323                                 child.getDefaultParent());
324
325                 for (int i = 0; i < blockCount; i++) {
326                         mxCell cell = (mxCell) child.getModel().getChildAt(
327                                         child.getDefaultParent(), i);
328                         if (cell instanceof ImplicitOutBlock) {
329                                 list.add(cell);
330                         }
331                 }
332                 return list;
333         }
334
335         protected List<mxCell> getAllEventOutBlock() {
336                 List<mxCell> list = new ArrayList<mxCell>();
337
338                 int blockCount = child.getModel().getChildCount(
339                                 child.getDefaultParent());
340
341                 for (int i = 0; i < blockCount; i++) {
342                         mxCell cell = (mxCell) child.getModel().getChildAt(
343                                         child.getDefaultParent(), i);
344                         if (cell instanceof EventOutBlock) {
345                                 list.add(cell);
346                         }
347                 }
348                 return list;
349         }
350
351         protected int getBlocksConsecutiveUniqueValueCount(List<mxCell> blocks) {
352                 if (blocks == null) {
353                         return 0;
354                 }
355
356                 int count = blocks.size();
357                 int[] array = new int[blocks.size()];
358
359                 // initialize
360                 for (int i = 0; i < array.length; i++) {
361                         array[i] = 0;
362                 }
363
364                 // populate
365                 for (int i = 0; i < array.length; i++) {
366                         int index = (Integer) ((BasicBlock) blocks.get(i)).getValue();
367                         if (index <= array.length) {
368                                 array[index - 1] = 1;
369                         }
370                 }
371
372                 // parse
373                 for (int i = 0; i < array.length; i++) {
374                         if (array[i] == 0) {
375                                 count = i;
376                                 break;
377                         }
378                 }
379
380                 return count;
381         }
382
383         public void updateAllBlocksColor() {
384                 updateBlocksColor(getAllExplicitInBlock());
385                 updateBlocksColor(getAllImplicitInBlock());
386                 updateBlocksColor(getAllEventInBlock());
387
388                 updateBlocksColor(getAllExplicitOutBlock());
389                 updateBlocksColor(getAllImplicitOutBlock());
390                 updateBlocksColor(getAllEventOutBlock());
391         }
392
393         private void updateBlocksColor(List<mxCell> blocks) {
394
395                 try {
396                         child.getModel().beginUpdate();
397                         if (blocks == null || blocks.size() == 0) {
398                                 return;
399                         }
400
401                         int countUnique = getBlocksConsecutiveUniqueValueCount(blocks);
402                         boolean isDone[] = new boolean[countUnique];
403
404                         // Initialize
405                         for (int i = 0; i < countUnique; i++) {
406                                 isDone[i] = false;
407                         }
408
409                         for (int i = 0; i < blocks.size(); i++) {
410                                 int index = (Integer) ((BasicBlock) blocks.get(i)).getValue();
411                                 if (index > countUnique || isDone[index - 1] == true) {
412                                         child.getAsComponent().setCellWarning(blocks.get(i),
413                                                         "Wrong port number");
414                                 } else {
415                                         isDone[index - 1] = true;
416                                         child.getAsComponent().setCellWarning(blocks.get(i), null);
417                                 }
418                         }
419                 } finally {
420                         child.getModel().endUpdate();
421                 }
422         }
423
424         public void updateExportedPort() {
425                 if (child == null) {
426                         return;
427                 }
428
429                 updateExportedExplicitInputPort();
430                 updateExportedImplicitInputPort();
431                 updateExportedEventInputPort();
432                 updateExportedExplicitOutputPort();
433                 updateExportedImplicitOutputPort();
434                 updateExportedEventOutputPort();
435                 getParentDiagram().fireEvent(new mxEventObject(XcosEvent.SUPER_BLOCK_UPDATED, XcosConstants.EVENT_BLOCK_UPDATED, this));
436         }
437
438         private void updateExportedExplicitInputPort() {
439                 int blockCount = getBlocksConsecutiveUniqueValueCount(getAllExplicitInBlock());
440                 List<ExplicitInputPort> ports = BasicBlockInfo
441                                 .getAllExplicitInputPorts(this, false);
442
443                 int portCount = ports.size();
444
445                 while (blockCount > portCount) { // add if required
446                         ExplicitInputPort port = new ExplicitInputPort();
447                         port.setDefaultValues();
448                         addPort(port);
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 updateExportedImplicitInputPort() {
459                 int blockCount = getBlocksConsecutiveUniqueValueCount(getAllImplicitInBlock());
460                 List<ImplicitInputPort> ports = BasicBlockInfo
461                                 .getAllImplicitInputPorts(this, false);
462
463                 int portCount = ports.size();
464
465                 while (blockCount > portCount) { // add if required
466                         addPort(new ImplicitInputPort());
467                         portCount++;
468                 }
469
470                 while (portCount > blockCount) { // remove if required
471                         removePort(ports.get(portCount - 1));
472                         portCount--;
473                 }
474         }
475
476         private void updateExportedEventInputPort() {
477                 int blockCount = getBlocksConsecutiveUniqueValueCount(getAllEventInBlock());
478                 List<ControlPort> ports = BasicBlockInfo
479                                 .getAllControlPorts(this, false);
480
481                 int portCount = ports.size();
482
483                 while (blockCount > portCount) { // add if required
484                         addPort(new ControlPort());
485                         portCount++;
486                 }
487
488                 while (portCount > blockCount) { // remove if required
489                         removePort(ports.get(portCount - 1));
490                         portCount--;
491                 }
492         }
493
494         private void updateExportedExplicitOutputPort() {
495                 int blockCount = getBlocksConsecutiveUniqueValueCount(getAllExplicitOutBlock());
496                 List<ExplicitOutputPort> ports = BasicBlockInfo
497                                 .getAllExplicitOutputPorts(this, false);
498
499                 int portCount = ports.size();
500
501                 while (blockCount > portCount) { // add if required
502                         ExplicitOutputPort port = new ExplicitOutputPort();
503                         port.setDefaultValues();
504                         addPort(port);
505                         portCount++;
506                 }
507
508                 while (portCount > blockCount) { // remove if required
509                         removePort(ports.get(portCount - 1));
510                         portCount--;
511                 }
512         }
513
514         private void updateExportedImplicitOutputPort() {
515                 int blockCount = getBlocksConsecutiveUniqueValueCount(getAllImplicitOutBlock());
516                 List<ImplicitOutputPort> ports = BasicBlockInfo
517                                 .getAllImplicitOutputPorts(this, false);
518
519                 int portCount = ports.size();
520
521                 while (blockCount > portCount) { // add if required
522                         addPort(new ImplicitOutputPort());
523                         portCount++;
524                 }
525
526                 while (portCount > blockCount) { // remove if required
527                         removePort(ports.get(portCount - 1));
528                         portCount--;
529                 }
530         }
531
532         private void updateExportedEventOutputPort() {
533                 int blockCount = getBlocksConsecutiveUniqueValueCount(getAllEventOutBlock());
534                 List<CommandPort> ports = BasicBlockInfo
535                                 .getAllCommandPorts(this, false);
536
537                 int portCount = ports.size();
538
539                 while (blockCount > portCount) { // add if required
540                         addPort(new CommandPort());
541                         portCount++;
542                 }
543
544                 while (portCount > blockCount) { // remove if required
545                         removePort(ports.get(portCount - 1));
546                         portCount--;
547                 }
548         }
549
550         /**
551          * Mask the SuperBlock
552          */
553         public void mask() {
554                 setInterfaceFunctionName("DSUPER");
555                 setSimulationFunctionName("csuper");
556         }
557
558         /**
559          * Unmask the SuperBlock
560          */
561         public void unmask() {
562                 setInterfaceFunctionName("SUPER_f");
563                 setSimulationFunctionName("super");
564         }
565
566         /**
567          * @return True is the SuperBlock is masked, false otherwise
568          */
569         public boolean isMasked() {
570                 return getInterfaceFunctionName().compareTo("SUPER_f") != 0;
571         }
572 }