2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009-2009 - DIGITEO - Antoine ELIAS
4 * Copyright (C) 2009-2010 - DIGITEO - Clement DAVID
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
14 package org.scilab.modules.xcos.graph;
17 import java.io.Serializable;
18 import java.util.Hashtable;
19 import java.util.List;
20 import java.util.logging.Logger;
22 import org.scilab.modules.types.ScilabDouble;
23 import org.scilab.modules.xcos.Xcos;
24 import org.scilab.modules.xcos.block.BasicBlock;
25 import org.scilab.modules.xcos.block.SuperBlock;
26 import org.scilab.modules.xcos.block.io.ContextUpdate;
27 import org.scilab.modules.xcos.block.io.ContextUpdate.IOBlocks;
28 import org.scilab.modules.xcos.block.io.EventInBlock;
29 import org.scilab.modules.xcos.block.io.EventOutBlock;
30 import org.scilab.modules.xcos.block.io.ExplicitInBlock;
31 import org.scilab.modules.xcos.block.io.ExplicitOutBlock;
32 import org.scilab.modules.xcos.block.io.ImplicitInBlock;
33 import org.scilab.modules.xcos.block.io.ImplicitOutBlock;
34 import org.scilab.modules.xcos.utils.XcosEvent;
35 import org.scilab.modules.xcos.utils.XcosMessages;
37 import com.mxgraph.model.mxICell;
38 import com.mxgraph.util.mxEvent;
39 import com.mxgraph.util.mxEventObject;
41 public final class SuperBlockDiagram extends XcosDiagram implements Serializable, Cloneable {
43 private static final String PARENT_DIAGRAM_WAS_NULL = "Parent diagram was null";
44 private static final long serialVersionUID = -402918614723713301L;
46 private SuperBlock container;
51 public SuperBlockDiagram() {
59 public SuperBlockDiagram(SuperBlock superBlock) {
61 setContainer(superBlock);
65 * @return parent super block
67 public SuperBlock getContainer() {
75 public void setContainer(SuperBlock container) {
76 this.container = container;
80 public File getSavedFile() {
81 if (getContainer() != null) {
82 XcosDiagram parent = getContainer().getParentDiagram();
84 return parent.getSavedFile();
88 return super.getSavedFile();
92 * Concatenate the context with the parent one
95 * @see org.scilab.modules.xcos.graph.XcosDiagram#getContext()
98 public String[] getContext() {
99 final SuperBlock block = getContainer();
100 XcosDiagram graph = block.getParentDiagram();
102 block.setParentDiagram(Xcos.findParent(block));
103 graph = block.getParentDiagram();
104 Logger.getLogger(SuperBlockDiagram.class.getName()).finest(PARENT_DIAGRAM_WAS_NULL);
107 final String[] parent;
109 parent = new String[] {};
111 parent = graph.getContext();
114 final String[] current = super.getContext();
116 String[] full = new String[current.length + parent.length];
117 System.arraycopy(parent, 0, full, 0, parent.length);
118 System.arraycopy(current, 0, full, parent.length, current.length);
123 * Validate I/O ports.
125 * /!\ No model modification should be made in this method, this is only a validation method.
128 * Cell that represents the cell to validate.
130 * Hashtable that represents the global validation state.
132 @SuppressWarnings("unchecked")
134 public String validateCell(final Object cell, final Hashtable<Object, Object> context) {
138 * Only validate I/O blocks
143 if (cell instanceof ExplicitInBlock || cell instanceof ImplicitInBlock) {
145 } else if (cell instanceof ExplicitOutBlock || cell instanceof ImplicitOutBlock) {
147 } else if (cell instanceof EventInBlock) {
149 } else if (cell instanceof EventOutBlock) {
155 final BasicBlock block;
157 block = (BasicBlock) cell;
167 fillContext(context);
173 // get the real index
174 final List <? extends BasicBlock > blocks = (List <? extends BasicBlock > ) context.get(key);
175 final int realIndex = blocks.indexOf(block) + 1;
177 // get the user index
178 final ScilabDouble data = (ScilabDouble) block.getIntegerParameters();
179 if (data.getWidth() < 1 || data.getHeight() < 1) {
182 final int userIndex = (int) data.getRealPart()[0][0];
184 // if the indexes are not equals, alert the user.
185 if (realIndex != userIndex) {
186 final StringBuilder str = new StringBuilder();
187 str.append("<html><body><em>");
188 str.append(XcosMessages.WRONG_PORT_NUMBER);
189 str.append("</em><br/>");
190 str.append(String.format(XcosMessages.EXPECTING_NUMBER, realIndex));
191 str.append("</body></html> ");
193 err = str.toString();
200 * Listener for SuperBlock diagram events.
202 @SuppressWarnings(value = { "serial" })
203 private static final class GenericSuperBlockListener implements mxIEventListener, Serializable {
204 private static GenericSuperBlockListener instance;
207 * Reduce constructor visibility
209 private GenericSuperBlockListener() {
214 * Mono-threaded singleton implementation getter
216 * @return The unique instance
218 public static GenericSuperBlockListener getInstance() {
219 if (instance == null) {
220 instance = new GenericSuperBlockListener();
226 * Update the IOPorts colors and values.
232 * @see com.mxgraph.util.mxEventSource.mxIEventListener#invoke(java.lang.Object,
233 * com.mxgraph.util.mxEventObject)
236 public void invoke(Object arg0, mxEventObject arg1) {
237 final SuperBlockDiagram graph = ((SuperBlockDiagram) arg0);
238 final SuperBlock block = graph.getContainer();
240 block.updateExportedPort();
243 // validate display errors
244 graph.getAsComponent().clearCellOverlays();
245 graph.getAsComponent().validateGraph();
250 * Listener for SuperBlock diagram events.
251 @SuppressWarnings(value = { "serial" })
253 private static final class ContentChangedListener implements mxIEventListener, Serializable {
254 private static ContentChangedListener instance;
257 * Reduce constructor visibility
259 private ContentChangedListener() {
264 * Mono-threaded singleton implementation getter
266 * @return The unique instance
268 public static ContentChangedListener getInstance() {
269 if (instance == null) {
270 instance = new ContentChangedListener();
276 * Update the IOPorts colors and values.
282 * @see com.mxgraph.util.mxEventSource.mxIEventListener#invoke(java.lang.Object,
283 * com.mxgraph.util.mxEventObject)
286 public void invoke(Object arg0, mxEventObject arg1) {
287 final SuperBlockDiagram graph = ((SuperBlockDiagram) arg0);
288 final SuperBlock block = graph.getContainer();
290 block.invalidateRpar();
296 @SuppressWarnings(value = { "serial" })
297 * Update the diagram labels
299 private static final class LabelBlockListener implements mxIEventListener, Serializable {
300 private static LabelBlockListener instance;
303 * Default Constructor
305 private LabelBlockListener() {
310 * @return the instance
312 public static LabelBlockListener getInstance() {
313 if (instance == null) {
314 instance = new LabelBlockListener();
321 public void invoke(Object sender, mxEventObject evt) {
322 final String value = (String) evt.getProperty("value");
323 final Object parent = evt.getProperty("parent");
324 if (parent instanceof ContextUpdate) {
325 final ContextUpdate block = (ContextUpdate) parent;
326 final ScilabDouble data = (ScilabDouble) block.getIntegerParameters();
329 if (data.getHeight() > 0 && data.getWidth() > 0) {
330 index = (int) data.getRealPart()[0][0];
335 final SuperBlock container = ((SuperBlockDiagram) sender).getContainer();
336 if (container == null) {
340 container.sortChildren();
341 final List<mxICell> ports = IOBlocks.getPorts(container, block.getClass());
343 XcosDiagram graph = container.getParentDiagram();
345 container.setParentDiagram(Xcos.findParent(container));
346 graph = container.getParentDiagram();
347 Logger.getLogger(SuperBlockDiagram.class.getName()).finest(PARENT_DIAGRAM_WAS_NULL);
350 if (index > 0 && index <= ports.size()) {
351 container.getParentDiagram().cellLabelChanged(ports.get(index - 1), value, false);
358 * Install the specific listeners for {@link SuperBlockDiagram}.
360 public void installSuperBlockListeners() {
361 removeListener(GenericSuperBlockListener.getInstance());
362 removeListener(LabelBlockListener.getInstance());
363 removeListener(ContentChangedListener.getInstance());
365 addListener(mxEvent.CELLS_ADDED, GenericSuperBlockListener.getInstance());
366 addListener(mxEvent.CELLS_REMOVED, GenericSuperBlockListener.getInstance());
367 addListener(XcosEvent.IO_PORT_VALUE_UPDATED, GenericSuperBlockListener.getInstance());
368 addListener(mxEvent.LABEL_CHANGED, LabelBlockListener.getInstance());
370 addListener(mxEvent.CELLS_ADDED, ContentChangedListener.getInstance());
371 addListener(mxEvent.CELLS_MOVED, ContentChangedListener.getInstance());
372 addListener(mxEvent.CELLS_REMOVED, ContentChangedListener.getInstance());
373 addListener(mxEvent.CELLS_RESIZED, ContentChangedListener.getInstance());
377 * This function set the SuperBlock diagram and all its parents in a
378 * modified state or not.
384 public void setModified(boolean modified) {
385 super.setModified(modified);
387 if (getContainer() != null && getContainer().getParentDiagram() != null) {
388 getContainer().getParentDiagram().setModified(modified);
393 * This function set the SuperBlock diagram in a modified state or not.
395 * It doesn't perform recursively on the parent diagrams. If you want such a
396 * behavior use setModified instead.
402 public void setModifiedNonRecursively(boolean modified) {
403 super.setModified(modified);
409 public Object clone() throws CloneNotSupportedException {
410 final SuperBlockDiagram clone = new SuperBlockDiagram();
411 clone.installListeners();
412 clone.installSuperBlockListeners();
414 clone.setScicosParameters((ScicosParameters) getScicosParameters().clone());
415 clone.addCells(cloneCells(getChildCells(getDefaultParent())), clone.getDefaultParent());