2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009 - DIGITEO - Bruno JOFRET
4 * Copyright (C) 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-en.txt
14 package org.scilab.modules.xcos;
16 import java.awt.Component;
18 import java.io.IOException;
19 import java.lang.reflect.InvocationTargetException;
20 import java.util.ArrayDeque;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.List;
29 import java.util.logging.LogManager;
30 import java.util.logging.Logger;
32 import javax.swing.Action;
33 import javax.swing.ImageIcon;
34 import javax.swing.SwingUtilities;
36 import org.scilab.modules.action_binding.InterpreterManagement;
37 import org.scilab.modules.commons.xml.XConfiguration;
38 import org.scilab.modules.core.Scilab;
39 import org.scilab.modules.graph.utils.ScilabExported;
40 import org.scilab.modules.gui.bridge.menu.SwingScilabMenu;
41 import org.scilab.modules.gui.bridge.menubar.SwingScilabMenuBar;
42 import org.scilab.modules.gui.bridge.tab.SwingScilabTab;
43 import org.scilab.modules.gui.messagebox.ScilabModalDialog;
44 import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption;
45 import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType;
46 import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType;
47 import org.scilab.modules.gui.tabfactory.AbstractScilabTabFactory;
48 import org.scilab.modules.gui.tabfactory.ScilabTabFactory;
49 import org.scilab.modules.gui.utils.BarUpdater;
50 import org.scilab.modules.gui.utils.ClosingOperationsManager;
51 import org.scilab.modules.gui.utils.ScilabSwingUtilities;
52 import org.scilab.modules.gui.utils.WindowsConfigurationManager;
53 import org.scilab.modules.localization.Messages;
54 import org.scilab.modules.xcos.actions.ExternalAction;
55 import org.scilab.modules.xcos.block.BasicBlock;
56 import org.scilab.modules.xcos.block.SuperBlock;
57 import org.scilab.modules.xcos.configuration.ConfigurationManager;
58 import org.scilab.modules.xcos.configuration.model.DocumentType;
59 import org.scilab.modules.xcos.graph.DiagramComparator;
60 import org.scilab.modules.xcos.graph.SuperBlockDiagram;
61 import org.scilab.modules.xcos.graph.XcosDiagram;
62 import org.scilab.modules.xcos.io.XcosFileType;
63 import org.scilab.modules.xcos.io.scicos.ScicosFormatException;
64 import org.scilab.modules.xcos.io.scicos.ScilabDirectHandler;
65 import org.scilab.modules.xcos.palette.PaletteManager;
66 import org.scilab.modules.xcos.palette.view.PaletteManagerView;
67 import org.scilab.modules.xcos.preferences.XcosConfiguration;
68 import org.scilab.modules.xcos.utils.BlockPositioning;
69 import org.scilab.modules.xcos.utils.FileUtils;
70 import org.scilab.modules.xcos.utils.XcosMessages;
72 import com.mxgraph.model.mxCell;
73 import com.mxgraph.model.mxGraphModel;
74 import com.mxgraph.model.mxICell;
75 import com.mxgraph.util.mxEvent;
76 import com.mxgraph.util.mxEventObject;
77 import com.mxgraph.view.mxStylesheet;
80 * Xcos entry point class
82 // CSOFF: ClassFanOutComplexity
83 // CSOFF: ClassDataAbstractionCoupling
84 public final class Xcos {
86 * The current Xcos version
88 public static final String VERSION = "1.0";
90 * The current Xcos tradename
92 public static final String TRADENAME = "Xcos";
93 public static final ImageIcon ICON = new ImageIcon(ScilabSwingUtilities.findIcon("utilities-system-monitor", "256x256"));
95 private static final String LOAD_XCOS_LIBS_LOAD_SCICOS = "loadXcosLibs(); loadScicos();";
98 * Dependencies version
100 private static final List<String> MXGRAPH_VERSIONS = null;
101 private static final List<String> HDF5_VERSIONS = Arrays.asList("[1, 8, 4]", "[1, 8, 5]", "[1, 8, 6]", "[1, 8, 7]", "[1, 8, 8]");
102 private static final List<String> BATIK_VERSIONS = Arrays.asList("1.7");
104 private static final String UNABLE_TO_LOAD_JGRAPHX = Messages.gettext("Unable to load the jgraphx library.\nExpecting version %s ; Getting version %s .");
105 private static final String UNABLE_TO_LOAD_JHDF5 = Messages
106 .gettext("Unable to load the hdf5-java (jhdf5) library. \nExpecting version %s ; Getting version %s .");
107 private static final String UNABLE_TO_LOAD_HDF5 = Messages.gettext("Unable to load the native HDF5 library.");
108 private static final String UNABLE_TO_LOAD_BATIK = Messages.gettext("Unable to load the Batik library. \nExpecting version %s ; Getting version %s .");
110 private static final String CALLED_OUTSIDE_THE_EDT_THREAD = "Called outside the EDT thread.";
111 private static final Logger LOG = Logger.getLogger(Xcos.class.getSimpleName());
113 /** common shared instance */
114 private static volatile Xcos sharedInstance;
117 Scilab.registerInitialHook(new Runnable() {
120 /* load scicos libraries (macros) */
121 InterpreterManagement.requestScilabExec(LOAD_XCOS_LIBS_LOAD_SCICOS);
125 XConfiguration.addXConfigurationListener(new XcosConfiguration());
131 private final Map<File, Collection<XcosDiagram>> diagrams;
132 private boolean onDiagramIteration = false;
133 private String lastError = null;
138 private final PaletteManager palette;
139 private final ConfigurationManager configuration;
140 private final mxStylesheet styleSheet;
141 private final List<ExternalAction> externalActions;
143 private final XcosTabFactory factory;
146 * Construct an Xcos instance.
148 * There must be only one Xcos instance per Scilab application
150 private Xcos(final XcosTabFactory factory) {
152 * Read the configuration to support dynamic (before Xcos launch)
156 LogManager.getLogManager().readConfiguration();
157 } catch (final SecurityException e) {
158 LOG.severe(e.toString());
159 } catch (final IOException e) {
160 LOG.severe(e.toString());
163 /* Check the dependencies at startup time */
164 // checkDependencies();
169 diagrams = new HashMap<File, Collection<XcosDiagram>>();
170 // null is used for not saved diagrams
171 addDiagram(null, null);
174 * get the handlers instance
176 palette = PaletteManager.getInstance();
177 configuration = ConfigurationManager.getInstance();
178 styleSheet = new mxStylesheet();
179 externalActions = new ArrayList<ExternalAction>();
182 FileUtils.decodeStyle(styleSheet);
183 } catch (final IOException e) {
184 LOG.severe(e.toString());
188 * Register as an AbstractScilabTabFactory
190 if (factory == null) {
191 this.factory = new XcosTabFactory(false);
193 this.factory = factory;
195 ScilabTabFactory.getInstance().addTabFactory(this.factory);
199 * Check the dependencies and the version dependencies.
201 * This method use runtime class loading to handle ClassNotFoundException.
203 * This method catch any exception and rethrow it with a well defined
204 * message. Thus it doesn't pass the IllegalCatch metrics.
206 // CSOFF: IllegalCatch
207 // CSOFF: MagicNumber
208 private void checkDependencies() {
209 final ClassLoader loader = ClassLoader.getSystemClassLoader();
212 String mxGraphVersion = "";
214 final Class<?> klass = loader.loadClass("com.mxgraph.view.mxGraph");
215 mxGraphVersion = (String) klass.getDeclaredField("VERSION").get(null);
217 if (MXGRAPH_VERSIONS != null && !MXGRAPH_VERSIONS.contains(mxGraphVersion)) {
218 throw new Exception();
220 } catch (final Throwable e) {
221 throw new RuntimeException(String.format(UNABLE_TO_LOAD_JGRAPHX, MXGRAPH_VERSIONS.get(0), mxGraphVersion), e);
225 final int[] libVersion = new int[3];
227 final Class<?> klass = loader.loadClass("ncsa.hdf.hdf5lib.H5");
230 int ret = (Integer) klass.getMethod("H5get_libversion", libVersion.getClass()).invoke(null, libVersion);
232 throw new Exception();
235 if (!HDF5_VERSIONS.contains(Arrays.toString(libVersion))) {
236 throw new Exception();
240 ret = (Integer) klass.getMethod("H5check_version", int.class, int.class, int.class).invoke(null, libVersion[0], libVersion[1], libVersion[2]);
242 throw new RuntimeException(UNABLE_TO_LOAD_HDF5);
245 } catch (final Throwable e) {
246 if (!(e instanceof RuntimeException)) {
247 throw new RuntimeException(String.format(UNABLE_TO_LOAD_JHDF5, HDF5_VERSIONS.get(0), Arrays.toString(libVersion)), e);
252 String batikVersion = null;
254 final Class<?> klass = loader.loadClass("org.apache.batik.Version");
255 batikVersion = klass.getPackage().getImplementationVersion().split("\\+")[0];
257 if (!BATIK_VERSIONS.contains(batikVersion)) {
258 throw new Exception();
261 } catch (final Throwable e) {
262 throw new RuntimeException(String.format(UNABLE_TO_LOAD_BATIK, BATIK_VERSIONS.get(0), batikVersion), e);
267 // CSON: IllegalCatch
270 * @return the per Scilab application, Xcos instance
272 public static synchronized Xcos getInstance() {
273 return getInstance(null);
278 * the tab factory instance or null on creation
279 * @return the per Scilab application, Xcos instance
281 private static synchronized Xcos getInstance(final XcosTabFactory factory) {
282 if (sharedInstance == null) {
283 sharedInstance = new Xcos(factory);
285 LOG.finest("Session started");
288 return sharedInstance;
294 public void quit(boolean force) {
295 if (sharedInstance == null) {
302 * Clear the shared instance.
304 private static synchronized void clearInstance() {
305 sharedInstance = null;
306 LOG.finest("Session ended");
310 * All Opened diagrams
312 * @return the opened diagrams list
314 public List<XcosDiagram> openedDiagrams() {
315 final List<XcosDiagram> opened = new ArrayList<XcosDiagram>();
316 for (File f : diagrams.keySet()) {
317 opened.addAll(openedDiagrams(f));
328 * @return the opened diagrams list
330 public List<XcosDiagram> openedDiagrams(File f) {
331 final List<XcosDiagram> opened = new ArrayList<XcosDiagram>();
332 for (XcosDiagram d : diagrams.get(f)) {
342 * Check if the in memory file representation is modified
346 * @return is modified
348 public boolean isModified(File f) {
349 for (XcosDiagram d : diagrams.get(f)) {
350 if (d.isModified()) {
359 * @return the global shared styleSheet
361 public mxStylesheet getStyleSheet() {
366 * Open a file from it's filename.
368 * This method must be called on the EDT thread. For other use, please use
369 * the {@link #xcos(String, String)} method.
372 * the file to open. If null an empty diagram is created.
374 * the variable to decode. If null no decode is performed.
376 public void open(final String file, final String variable) {
377 if (!SwingUtilities.isEventDispatchThread()) {
378 LOG.severe(CALLED_OUTSIDE_THE_EDT_THREAD);
382 * If it is the first window opened, then open the palette first.
384 if (file == null && variable == null && openedDiagrams().isEmpty()) {
385 PaletteManager.setVisible(true);
388 XcosDiagram diag = null;
396 if (f != null && f.exists()) {
397 configuration.addToRecentFiles(f);
401 * looking for an already opened diagram
403 final Collection<XcosDiagram> diags = diagrams.get(f);
404 if (diags != null && !diags.isEmpty()) {
405 diag = diags.iterator().next();
407 // if unsaved and empty, reuse it. Allocate otherwise.
408 if (f == null && diag != null && diag.getModel().getChildCount(diag.getDefaultParent()) > 0) {
411 // if reuse then request focus
413 XcosTab tab = XcosTab.get(diag);
421 // loading disabled, unlock
422 synchronized (this) {
427 // loading enable, unlock will be performed later, on another thread
430 * Allocate and setup a new diagram
432 diag = new XcosDiagram();
433 diag.installListeners();
436 * Ask for file creation
438 if (f != null && !f.exists()) {
439 if (!diag.askForFileCreation(f)) {
440 // loading disabled, unlock
441 synchronized (this) {
446 // return now, to avoid tab creation
452 * Create a visible window before loading
454 if (XcosTab.get(diag) == null) {
455 XcosTab.restore(diag);
461 diag.transformAndLoadFile(file, variable);
464 addDiagram(diag.getSavedFile(), diag);
469 diag.updateTabTitle();
474 * Log a loading error
477 * the error description
479 public void setLastError(String error) {
480 this.lastError = error;
484 * Get an unmodifiable view of the diagrams for a specific file
488 * @return the diagram collection
490 public Collection<XcosDiagram> getDiagrams(final File f) {
491 final Collection<XcosDiagram> diags = diagrams.get(f);
495 return Collections.unmodifiableCollection(diags);
499 * Add a diagram to the diagram list for a file. Be sure to set the right
500 * opened status on the diagram before calling this method.
507 public void addDiagram(final File f, final XcosDiagram diag) {
508 if (onDiagramIteration) {
509 throw new RuntimeException();
513 * Create the collection if it does not exist
515 Collection<XcosDiagram> diags = diagrams.get(f);
517 diags = createDiagramCollection();
518 diagrams.put(f, diags);
523 * Remove the diagram (and any child)
525 final Collection<XcosDiagram> toBeMoved = removeChildren(diag);
528 * Add the diagram to the collection
530 diags.addAll(toBeMoved);
534 private Collection<XcosDiagram> removeChildren(XcosDiagram diag) {
535 final Collection<XcosDiagram> removed = new HashSet<XcosDiagram>();
538 for (Collection<XcosDiagram> it : diagrams.values()) {
539 if (!it.contains(diag)) {
544 * Add all children to the removed collection.
546 for (XcosDiagram graph : it) {
547 if (graph instanceof SuperBlockDiagram) {
548 final XcosDiagram parent = ((SuperBlockDiagram) graph).getContainer().getParentDiagram();
550 // As "it" is sorted according to the hierarchy, "removed"
552 if (removed.contains(parent)) {
560 * really remove them all
562 it.removeAll(removed);
570 * Create a diagram collections (sorted List)
572 * @return the diagram collection
574 public Collection<XcosDiagram> createDiagramCollection() {
575 return new ArrayList<XcosDiagram>() {
577 public boolean add(XcosDiagram element) {
578 final boolean status = super.add(element);
579 DiagramComparator.sort(this);
584 public boolean addAll(Collection <? extends XcosDiagram > c) {
585 final boolean status = super.addAll(c);
586 DiagramComparator.sort(this);
593 * Try to close the graph (popup save dialog)
597 * @return if we can (or not) close the graph
599 public boolean canClose(final XcosDiagram graph) {
600 boolean canClose = false;
601 final File f = graph.getSavedFile();
603 final boolean wasLastOpened = openedDiagrams(f).size() <= 1;
604 final boolean isModified = isModified(f);
605 if (!(wasLastOpened && isModified)) {
610 final AnswerOption ans = ScilabModalDialog.show(XcosTab.get(graph), XcosMessages.DIAGRAM_MODIFIED, XcosMessages.XCOS, IconType.QUESTION_ICON,
611 ButtonType.YES_NO_CANCEL);
615 canClose = diagrams.get(f).iterator().next().saveDiagram();
618 canClose = true; // can close
621 canClose = false; // operation canceled
627 * Update configuration before the destroy call to validate the uuid
630 configuration.addToRecentTabs(graph);
631 configuration.saveConfig();
639 * This method must be called on the EDT thread.
642 * the diagram to close
644 public void destroy(XcosDiagram graph) {
645 final File f = graph.getSavedFile();
646 final boolean wasLastOpenedForFile = openedDiagrams(f).size() <= 1;
648 if (!onDiagramIteration && wasLastOpenedForFile) {
652 if (openedDiagrams().size() <= 1) {
653 /* halt scicos (stop the simulation) */
654 InterpreterManagement.requestScilabExec("haltscicos()");
660 * the graph to handle
662 * the diagram to check
663 * @return diagram name for the "Are your sure ?" dialog
665 public String askForClosing(final XcosDiagram graph, final List<SwingScilabTab> list) {
668 if (wasLastOpened(list)) {
678 * Does Xcos will close or not ?
681 * the list to be closed
682 * @return true if all files will be close on tabs close.
684 public boolean wasLastOpened(final List<SwingScilabTab> list) {
685 final HashSet<String> opened = new HashSet<String>();
686 for (XcosDiagram diag : openedDiagrams()) {
687 opened.add(diag.getGraphTab());
690 final HashSet<String> tabs = new HashSet<String>();
691 for (SwingScilabTab tab : list) {
693 tabs.add(tab.getPersistentId());
697 opened.removeAll(tabs);
699 return opened.isEmpty();
703 * @return the external action list
705 public List<ExternalAction> getExternalActions() {
706 return externalActions;
710 * Close the current xcos session.
712 * This method must be called on the EDT thread. For other use, please use
713 * the {@link #closeXcosFromScilab()} method.
715 public static synchronized void closeSession(final boolean ask) {
716 if (!SwingUtilities.isEventDispatchThread()) {
717 LOG.severe(CALLED_OUTSIDE_THE_EDT_THREAD);
720 /* Doesn't instantiate xcos on close operation */
721 if (sharedInstance == null) {
726 * Try to close all opened files
728 final Xcos instance = sharedInstance;
731 final List<SwingScilabTab> tabs = new ArrayList<SwingScilabTab>();
732 for (final Collection<XcosDiagram> diags : instance.diagrams.values()) {
733 for (final XcosDiagram diag : diags) {
734 final SwingScilabTab tab = XcosTab.get(diag);
742 final boolean status = ClosingOperationsManager.startClosingOperation(tabs, ask, ask);
746 /* reset the shared instance state */
747 instance.diagrams.keySet().clear();
748 instance.addDiagram(null, null);
750 /* terminate any remaining simulation */
751 InterpreterManagement.putCommandInScilabQueue("if isdef('haltscicos'), then haltscicos(), end;");
753 /* Saving modified data */
754 instance.palette.saveConfig();
755 instance.configuration.saveConfig();
760 * Scilab exported methods.
762 * All the following methods must use SwingUtilities method to assert that
763 * the operations will be called on the EDT thread.
765 * @see modules/xcos/src/jni/Xcos.giws.xml
767 * @see sci_gateway/xcos_gateway.xml
769 * @see modules/xcos/sci_gateway/cpp/sci_*.cpp
775 * This method invoke Xcos operation on the EDT thread.
778 * The filename (can be null)
780 * The Scilab variable to load (can be null)
782 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
783 public static void xcos(final String file, final String variable) {
784 final Xcos instance = getInstance();
785 instance.lastError = null;
787 /* load scicos libraries (macros) */
788 InterpreterManagement.requestScilabExec(LOAD_XCOS_LIBS_LOAD_SCICOS);
790 synchronized (instance) {
794 SwingUtilities.invokeLater(new Runnable() {
798 instance.open(file, variable);
803 * Wait loading and fail on error only if the variable is readeable
806 while (variable != null && instance.lastError == null) {
809 } catch (InterruptedException e) {
813 if (instance.lastError != null && !instance.lastError.isEmpty()) {
814 throw new RuntimeException(instance.lastError);
819 * Close the current xcos session from any thread.
821 * This method invoke Xcos operation on the EDT thread. Please prefer using
822 * {@link #closeSession()} when the caller is on the EDT thread.
824 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
825 public static void closeXcosFromScilab() {
827 SwingUtilities.invokeAndWait(new Runnable() {
834 } catch (final InterruptedException e) {
835 LOG.severe(e.toString());
836 } catch (final InvocationTargetException e) {
837 Throwable throwable = e;
838 String firstMessage = null;
839 while (throwable != null) {
840 firstMessage = throwable.getLocalizedMessage();
841 throwable = throwable.getCause();
844 throw new RuntimeException(firstMessage, e);
849 * Look in each diagram to find the block corresponding to the given uid and
850 * display a warning message.
852 * This method invoke Xcos operation on the EDT thread.
857 * The message to display.
859 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
860 public static void warnCellByUID(final String[] uid, final String message) {
862 SwingUtilities.invokeAndWait(new Runnable() {
865 getInstance().warnCell(uid, message);
868 } catch (final InterruptedException e) {
869 LOG.severe(e.toString());
870 } catch (final InvocationTargetException e) {
871 Throwable throwable = e;
872 String firstMessage = null;
873 while (throwable != null) {
874 firstMessage = throwable.getLocalizedMessage();
875 throwable = throwable.getCause();
878 throw new RuntimeException(firstMessage, e);
882 private void warnCell(final String[] uid, final String message) {
883 final mxCell cell = (mxCell) lookupForCell(uid);
885 // We are unable to find the block with the right id
890 // finally perform the action on the last block
891 final XcosDiagram parent = findParent(cell);
892 parent.warnCellByUID(cell.getId(), message);
894 SwingUtilities.invokeLater(new Runnable() {
898 * Focus on an existing diagram
900 XcosTab.get(parent).setCurrent();
905 private Object lookupForCell(final String[] uid) {
906 final ArrayDeque<String> deque = new ArrayDeque<String>(Arrays.asList(uid));
908 // specific case with an empty array
909 if (deque.isEmpty()) {
915 Collection<XcosDiagram> diags = null;
916 String id = deque.pop();
918 onDiagramIteration = true;
920 for (Collection<XcosDiagram> ds : diagrams.values()) {
925 final XcosDiagram root = ds.iterator().next();
927 cell = ((mxGraphModel) root.getModel()).getCell(id);
934 onDiagramIteration = false;
937 // loop to get only the last diagram
938 while (cell instanceof SuperBlock && !deque.isEmpty()) {
939 final SuperBlock block = (SuperBlock) cell;
941 block.getParentDiagram().warnCellByUID(block.getId(), XcosMessages.ERROR_UNABLE_TO_COMPILE_THIS_SUPER_BLOCK);
945 if (!diags.contains(block.getChild()) || !block.getChild().isOpened()) {
946 block.openBlockSettings(null);
949 final mxGraphModel model = ((mxGraphModel) block.getChild().getModel());
950 cell = model.getCell(id);
956 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
957 public static void updateBlock(final String h5File) {
959 SwingUtilities.invokeAndWait(new Runnable() {
962 getInstance().updateBlockInstance();
965 } catch (final InterruptedException e) {
966 LOG.severe(e.toString());
967 } catch (final InvocationTargetException e) {
968 Throwable throwable = e;
969 String firstMessage = null;
970 while (throwable != null) {
971 firstMessage = throwable.getLocalizedMessage();
972 throwable = throwable.getCause();
975 throw new RuntimeException(firstMessage, e);
979 private void updateBlockInstance() {
981 BasicBlock modifiedBlock;
983 final ScilabDirectHandler handler = ScilabDirectHandler.acquire();
984 if (handler == null) {
989 modifiedBlock = handler.readBlock();
990 } catch (ScicosFormatException e) {
991 throw new RuntimeException(e);
995 if (modifiedBlock == null) {
1000 final XcosDiagram diag = findParent(modifiedBlock);
1002 throw new RuntimeException(Messages.gettext("parent diagram not found."));
1005 // finally update the instance
1006 final mxGraphModel model = (mxGraphModel) diag.getModel();
1007 final BasicBlock block = (BasicBlock) model.getCell(modifiedBlock.getId());
1008 assert block != null;
1010 block.updateBlockSettings(modifiedBlock);
1011 block.setInterfaceFunctionName(modifiedBlock.getInterfaceFunctionName());
1012 block.setSimulationFunctionName(modifiedBlock.getSimulationFunctionName());
1013 block.setSimulationFunctionType(modifiedBlock.getSimulationFunctionType());
1014 if (block instanceof SuperBlock) {
1015 ((SuperBlock) block).setChild(null);
1018 block.setStyle(block.getStyle() + ";blockWithLabel");
1019 block.setValue(block.getSimulationFunctionName());
1020 BlockPositioning.updateBlockView(block);
1024 * This function convert a Xcos diagram to Scilab variable.
1026 * This method invoke Xcos operation on the EDT thread.
1029 * The xcos diagram file
1030 * @return Not used (compatibility)
1032 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
1033 public static int xcosDiagramToScilab(final String xcosFile) {
1034 final File file = new File(xcosFile);
1036 if (!file.exists()) {
1041 SwingUtilities.invokeAndWait(new Runnable() {
1044 LOG.finest("xcosDiagramToScilab: entering");
1045 final XcosDiagram diagram = new XcosDiagram();
1047 final XcosFileType filetype = XcosFileType.findFileType(file);
1048 if (filetype != null) {
1050 LOG.finest("xcosDiagramToScilab: initialized");
1051 filetype.load(xcosFile, diagram);
1052 LOG.finest("xcosDiagramToScilab: loaded");
1054 final ScilabDirectHandler handler = ScilabDirectHandler.acquire();
1055 if (handler == null) {
1060 handler.writeDiagram(diagram);
1064 } catch (Exception e) {
1065 throw new RuntimeException(e);
1068 LOG.finest("xcosDiagramToScilab: exiting");
1071 } catch (final InterruptedException e) {
1072 throw new RuntimeException(e);
1073 } catch (final InvocationTargetException e) {
1074 Throwable throwable = e;
1075 String firstMessage = null;
1076 while (throwable != null) {
1077 firstMessage = throwable.getLocalizedMessage();
1078 throwable = throwable.getCause();
1081 throw new RuntimeException(firstMessage, e);
1088 * Add a menu into xcos
1093 * the callback (as a Scilab executable String)
1095 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
1096 public static void addToolsMenu(final String label, final String command) {
1097 final ExternalAction action = new ExternalAction(null, command);
1098 action.putValue(Action.NAME, label);
1099 final Xcos instance = Xcos.getInstance();
1102 * Store for future tabs
1104 instance.externalActions.add(action);
1107 * Update opened tabs
1109 for (final XcosDiagram d : instance.openedDiagrams()) {
1110 final String uuid = d.getGraphTab();
1111 final SwingScilabTab tab = ScilabTabFactory.getInstance().getFromCache(uuid);
1114 final SwingScilabMenuBar bar = ((SwingScilabMenuBar) tab.getMenuBar().getAsSimpleMenuBar());
1116 final Component[] comps = bar.getComponents();
1117 for (Component component : comps) {
1118 if (component instanceof SwingScilabMenu) {
1119 final SwingScilabMenu menu = (SwingScilabMenu) component;
1121 if (menu.getText() == XcosMessages.TOOLS) {
1122 menu.add(new ExternalAction(action, d));
1127 // Also update the parent window toolbar
1128 BarUpdater.updateBars(tab.getParentWindowId(), tab.getMenuBar(), tab.getToolBar(), tab.getInfoBar(), tab.getName(), tab.getWindowIcon());
1134 * Open a diagram by uid.
1136 * This method invoke Xcos operation on the EDT thread.
1139 * UID path to a block.
1141 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
1143 public static void xcosDiagramOpen(final String[] uid) {
1144 throw new UnsupportedOperationException();
1148 * Close a diagram by uid.
1150 * This method invoke Xcos operation on the EDT thread.
1153 * The diagram id path
1155 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
1157 public static void xcosDiagramClose(final String[] uid) {
1158 throw new UnsupportedOperationException();
1162 * Look for the parent diagram of the cell in the diagram hierarchy.
1165 * the cell to search for
1166 * @return the associated diagram
1168 public static XcosDiagram findParent(Object cell) {
1169 final Xcos instance = getInstance();
1171 instance.onDiagramIteration = true;
1173 for (Collection<XcosDiagram> diags : instance.diagrams.values()) {
1174 for (XcosDiagram diag : diags) {
1175 final mxGraphModel model = (mxGraphModel) diag.getModel();
1177 // use the O(1) lookup
1178 if (cell instanceof mxICell && model.getCell(((mxICell) cell).getId()) != null) {
1179 if (cell instanceof BasicBlock) {
1180 ((BasicBlock) cell).setParentDiagram(diag);
1187 instance.onDiagramIteration = false;
1194 * @see org.scilab.modules.gui.tabfactory.AbstractScilabTabFactory
1196 public static class XcosTabFactory extends AbstractScilabTabFactory {
1201 private DocumentType cachedDocumentType;
1204 * Default constructor
1206 public XcosTabFactory() {
1210 private XcosTabFactory(boolean instanciateXcos) {
1211 if (instanciateXcos) {
1217 * Create/restore a tab for a given uuid
1221 * @return the tab instance
1224 public synchronized SwingScilabTab getTab(final String uuid) {
1229 SwingScilabTab tab = ScilabTabFactory.getInstance().getFromCache(uuid);
1231 // Palette manager restore
1233 if (PaletteManagerView.DEFAULT_TAB_UUID.equals(uuid)) {
1234 PaletteManagerView.restore(null, false);
1235 tab = PaletteManagerView.get();
1239 // diagram (tab or viewport) restore
1242 if (cachedDocumentType == null) {
1246 final boolean isTab = uuid.equals(cachedDocumentType.getUuid());
1247 final boolean isViewport = uuid.equals(cachedDocumentType.getViewport());
1249 final XcosDiagram graph = getDiagram(isTab, isViewport);
1250 if (graph != null && isTab) {
1251 XcosTab.restore(graph, false);
1252 graph.fireEvent(new mxEventObject(mxEvent.ROOT));
1253 tab = XcosTab.get(graph);
1254 } else if (graph != null && isViewport) {
1255 ViewPortTab.restore(graph, false);
1256 tab = ViewPortTab.get(graph);
1258 ClosingOperationsManager.addDependency(XcosTab.get(graph), tab);
1259 WindowsConfigurationManager.makeDependency(graph.getGraphTab(), tab.getPersistentId());
1265 WindowsConfigurationManager.restorationFinished(tab);
1266 ScilabTabFactory.getInstance().addToCache(tab);
1271 private XcosDiagram getDiagram(boolean isTab, boolean isViewport) {
1272 XcosDiagram graph = null;
1274 // load a new diagram
1275 graph = getInstance().configuration.loadDiagram(cachedDocumentType);
1276 } else if (isViewport) {
1277 // get the cached diagram
1278 final File f = getInstance().configuration.getFile(cachedDocumentType);
1279 final Collection<XcosDiagram> diags = getInstance().diagrams.get(f);
1281 for (XcosDiagram d : diags) {
1282 final String id = d.getGraphTab();
1283 if (id != null && id.equals(cachedDocumentType.getUuid())) {
1294 public synchronized boolean isAValidUUID(String uuid) {
1295 // check the Palette manager view (static uuid)
1296 if (PaletteManagerView.DEFAULT_TAB_UUID.equals(uuid)) {
1301 * Cache and check against cache to ease next getTab(uuid) call
1304 return cachedDocumentType != null;
1308 * Cache the {@link DocumentType} for the specific uuid
1313 private void cache(String uuid) {
1315 * Handle a non null cache
1317 if (cachedDocumentType != null) {
1318 final boolean isTab = uuid.equals(cachedDocumentType.getUuid());
1319 final boolean isViewport = uuid.equals(cachedDocumentType.getViewport());
1321 if (isTab || isViewport) {
1324 cachedDocumentType = null;
1329 * Invalid cache, look for the right one
1331 final ConfigurationManager config = getInstance().configuration;
1332 final List<DocumentType> docs = config.getSettings().getTab();
1333 for (DocumentType d : docs) {
1334 final boolean isTab = uuid.equals(d.getUuid());
1335 final boolean isViewport = uuid.equals(d.getViewport());
1337 if (isTab || isViewport) {
1338 cachedDocumentType = d;
1345 public String getPackage() {
1350 public String getClassName() {
1351 return XcosTabFactory.class.getName();
1355 public String getApplication() {
1360 // CSON: ClassDataAbstractionCoupling
1361 // CSON: ClassFanOutComplexity