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
5 * Copyright (C) 2011-2017 - Scilab Enterprises - Clement DAVID
7 * Copyright (C) 2012 - 2016 - Scilab Enterprises
9 * This file is hereby licensed under the terms of the GNU GPL v2.0,
10 * pursuant to article 5.3.4 of the CeCILL v.2.1.
11 * This file was originally licensed under the terms of the CeCILL v2.1,
12 * and continues to be available under such terms.
13 * For more information, see the COPYING file which you should have received
14 * along with this program.
18 package org.scilab.modules.xcos;
20 import java.awt.Component;
22 import java.io.IOException;
23 import java.lang.reflect.InvocationTargetException;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
32 import java.util.logging.LogManager;
33 import java.util.logging.Logger;
35 import javax.swing.Action;
36 import javax.swing.ImageIcon;
37 import javax.swing.SwingUtilities;
39 import org.scilab.modules.action_binding.InterpreterManagement;
40 import org.scilab.modules.commons.gui.FindIconHelper;
41 import org.scilab.modules.commons.xml.XConfiguration;
42 import org.scilab.modules.core.Scilab;
43 import org.scilab.modules.graph.actions.base.GraphActionManager;
44 import org.scilab.modules.graph.utils.ScilabExported;
45 import org.scilab.modules.gui.bridge.menu.SwingScilabMenu;
46 import org.scilab.modules.gui.bridge.menubar.SwingScilabMenuBar;
47 import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel;
48 import org.scilab.modules.gui.messagebox.ScilabModalDialog;
49 import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption;
50 import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType;
51 import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType;
52 import org.scilab.modules.gui.tabfactory.AbstractScilabTabFactory;
53 import org.scilab.modules.gui.tabfactory.ScilabTabFactory;
54 import org.scilab.modules.gui.utils.BarUpdater;
55 import org.scilab.modules.gui.utils.ClosingOperationsManager;
56 import org.scilab.modules.gui.utils.WindowsConfigurationManager;
57 import org.scilab.modules.localization.Messages;
58 import org.scilab.modules.xcos.actions.ExternalAction;
59 import org.scilab.modules.xcos.actions.StopAction;
60 import org.scilab.modules.xcos.configuration.ConfigurationManager;
61 import org.scilab.modules.xcos.configuration.model.DocumentType;
62 import org.scilab.modules.xcos.graph.DiagramComparator;
63 import org.scilab.modules.xcos.graph.XcosDiagram;
64 import org.scilab.modules.xcos.io.XcosFileType;
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.FileUtils;
69 import org.scilab.modules.xcos.utils.XcosMessages;
71 import com.mxgraph.model.mxCell;
72 import com.mxgraph.model.mxGraphModel;
73 import com.mxgraph.model.mxICell;
74 import com.mxgraph.util.mxEvent;
75 import com.mxgraph.util.mxEventObject;
76 import com.mxgraph.view.mxStylesheet;
77 import javax.swing.Timer;
78 import org.scilab.modules.commons.ScilabCommons;
79 import org.scilab.modules.xcos.graph.model.ScicosObjectOwner;
80 import org.scilab.modules.xcos.graph.model.XcosGraphModel;
83 * Xcos entry point class
85 // CSOFF: ClassFanOutComplexity
86 // CSOFF: ClassDataAbstractionCoupling
87 public final class Xcos {
89 * The current Xcos version
91 public static final String VERSION = "2.0";
93 * The current Xcos tradename
95 public static final String TRADENAME = Xcos.class.getSimpleName();
96 public static final ImageIcon ICON = new ImageIcon(FindIconHelper.findIcon("utilities-system-monitor", "256x256"));
98 private static final String LOAD_XCOS_LIBS_LOAD_SCICOS = "prot=funcprot(); funcprot(0); loadXcosLibs(); loadScicos(); funcprot(prot); clear prot";
100 private static final String CALLED_OUTSIDE_THE_EDT_THREAD = "Called outside the EDT thread.";
101 private static final Logger LOG = Logger.getLogger(Xcos.class.getName());
103 /** common shared instance */
104 private static volatile Xcos sharedInstance;
107 Scilab.registerInitialHook(() -> {
108 // wait the Scilab startup termination
109 final Timer t = new Timer(500, null);
110 t.addActionListener((e) -> {
111 if (ScilabCommons.getStartProcessing() == 1)
115 /* load scicos libraries (macros) */
116 InterpreterManagement.requestScilabExec(LOAD_XCOS_LIBS_LOAD_SCICOS);
121 XConfiguration.addXConfigurationListener(new XcosConfiguration());
127 private final Map<ScicosObjectOwner, List<XcosDiagram>> diagrams;
128 private XcosView view;
129 private BrowserView browser;
130 private boolean onDiagramIteration = false;
131 private String lastError = null;
136 private final PaletteManager palette;
137 private final ConfigurationManager configuration;
138 private final mxStylesheet styleSheet;
139 private final List<ExternalAction> externalActions;
141 private final XcosTabFactory factory;
144 * Construct an Xcos instance.
146 * There must be only one Xcos instance per Scilab application
148 private Xcos(final XcosTabFactory factory) {
150 * Read the configuration to support dynamic (before Xcos launch) settings.
153 LogManager.getLogManager().readConfiguration();
154 } catch (final SecurityException | IOException e) {
155 LOG.severe(e.toString());
161 diagrams = new HashMap<>();
163 view = new XcosView();
164 // allocate and install the browser view on demand to avoid any cost
168 * get the handlers instance
170 palette = PaletteManager.getInstance();
171 configuration = ConfigurationManager.getInstance();
172 styleSheet = new mxStylesheet();
173 externalActions = new ArrayList<>();
176 FileUtils.decodeStyle(styleSheet);
177 } catch (final IOException e) {
178 LOG.severe(e.toString());
182 * Register as an AbstractScilabTabFactory
184 if (factory == null) {
185 this.factory = new XcosTabFactory(false);
187 this.factory = factory;
189 ScilabTabFactory.getInstance().addTabFactory(this.factory);
194 protected void finalize() throws Throwable {
195 if (browser != null) {
196 JavaController.unregister_view(browser);
199 JavaController.unregister_view(view);
205 * @return the per Scilab application, Xcos instance
207 public static synchronized Xcos getInstance() {
208 return getInstance(null);
213 * the tab factory instance or null on creation
214 * @return the per Scilab application, Xcos instance
216 private static synchronized Xcos getInstance(final XcosTabFactory factory) {
217 if (sharedInstance == null) {
219 if (!SwingUtilities.isEventDispatchThread()) {
220 SwingUtilities.invokeAndWait(() -> {
221 sharedInstance = new Xcos(factory);
224 sharedInstance = new Xcos(factory);
226 } catch (InvocationTargetException e) {
228 } catch (InterruptedException e) {
232 LOG.finest("Session started");
235 return sharedInstance;
241 public void quit(boolean force) {
242 if (sharedInstance == null) {
246 // TODO : perform something ?
250 * Clear the shared instance.
252 private static synchronized void clearInstance() {
253 sharedInstance = null;
254 LOG.finest("Session ended");
258 * All Opened diagrams
260 * @return the opened diagrams list
262 public List<XcosDiagram> openedDiagrams() {
263 ArrayList<XcosDiagram> opened = new ArrayList<>();
264 diagrams.values().stream().forEach(l -> opened.addAll(l));
273 * @return the opened diagrams list
275 public List<XcosDiagram> openedDiagrams(ScicosObjectOwner root) {
276 return diagrams.getOrDefault(root, Collections.emptyList());
279 public ScicosObjectOwner openedDiagram(File f) {
280 ScicosObjectOwner opened = null;
285 for (ScicosObjectOwner root : diagrams.keySet()) {
286 List<XcosDiagram> diags = diagrams.getOrDefault(root, Collections.emptyList());
288 if (!diags.isEmpty() && f.equals(diags.get(0).getSavedFile())) {
298 * Check if the in memory file representation is modified
302 * @return is modified
304 public boolean isModified(ScicosObjectOwner root) {
305 for (XcosDiagram d : diagrams.get(root)) {
306 if (d.isModified()) {
315 * Set the full diagram as modified
316 * @param root the root diagram
317 * @param modified the modified status
319 public void setModified(ScicosObjectOwner root, boolean modified) {
320 for (XcosDiagram d : diagrams.get(root)) {
321 d.setModified(modified);
326 * Popup a dialog to ask for a file creation
330 * @return true if creation is has been performed
332 public boolean askForFileCreation(final XcosDiagram diag, final File f) {
335 answer = ScilabModalDialog.show(diag.getAsComponent(), new String[] { String.format(XcosMessages.FILE_DOESNT_EXIST, f.getCanonicalFile()) },
336 XcosMessages.XCOS, IconType.QUESTION_ICON, ButtonType.YES_NO);
337 } catch (final IOException e) {
338 LOG.severe(e.toString());
339 answer = AnswerOption.YES_OPTION;
342 if (answer == AnswerOption.YES_OPTION) {
343 return diag.saveDiagramAs(f);
350 * @return the global shared styleSheet
352 public mxStylesheet getStyleSheet() {
357 * Open a file from it's filename.
359 * This method must be called on the EDT thread. For other use, please use the {@link #xcos(String, String)} method.
362 * the file to open. If null an empty diagram is created.
364 * the MVC ID to track. If 0 no association is performed.
366 public void open(final String file, final long diagramId) {
367 if (!SwingUtilities.isEventDispatchThread()) {
368 LOG.severe(CALLED_OUTSIDE_THE_EDT_THREAD);
372 * If it is the first window opened, then open the palette first.
374 boolean openThePalette = openedDiagrams().isEmpty();
376 JavaController controller = new JavaController();
377 XcosDiagram diag = null;
385 if (f != null && f.exists()) {
386 configuration.addToRecentFiles(f);
390 * looking for an already opened diagram
392 ScicosObjectOwner root = openedDiagram(f);
394 diag = diagrams.get(root).iterator().next();
396 // if unsaved and empty, reuse it. Allocate otherwise.
397 if (f == null && diag != null && diag.getModel().getChildCount(diag.getDefaultParent()) > 0) {
401 // looking for an empty, unsaved diagram to use if opening a new file
402 // if not found an already open instance of the file
404 // traverse through the key set of all the opened diagrams
405 for (Map.Entry<ScicosObjectOwner, List<XcosDiagram>> entry : diagrams.entrySet()) {
406 List<XcosDiagram> diagramsWithKey = entry.getValue();
407 XcosDiagram diagramWithKey = diagramsWithKey.get(0); // get the diagram that maps to that key
408 int childCount = diagramWithKey.countChildren(); //count the number of children in the diagram
409 // if empty, unsaved and unused
410 if (childCount == 0 && diagramWithKey.getSavedFile() == null && !diagramWithKey.isModified()) {
411 // use that open diagram
412 diag = diagramWithKey;
413 diag.transformAndLoadFile(controller, file);
417 // if reuse then request focus
419 XcosTab tab = XcosTab.get(diag);
426 final long currentId;
427 if (diagramId != 0) {
428 currentId = diagramId;
430 currentId = controller.createObject(Kind.DIAGRAM);
434 // loading disabled, unlock
435 synchronized (this) {
440 // loading enable, unlock will be performed later, on another thread
443 * Allocate and setup a new diagram
445 diag = new XcosDiagram(controller, currentId, controller.getKind(currentId), "");
446 diag.installListeners();
448 root = findRoot(controller, diag);
449 addDiagram(root, diag);
452 * Ask for file creation
454 if (f != null && !f.exists()) {
455 if (!askForFileCreation(diag, f)) {
456 // loading disabled, unlock
457 synchronized (this) {
462 // return now, to avoid tab creation
463 diagrams.remove(root);
470 * Create a visible window before loading
472 if (XcosTab.get(diag) == null) {
473 XcosTab.restore(diag);
476 if (openThePalette) {
477 PaletteManager.setVisible(true);
483 diag.transformAndLoadFile(controller, file);
488 * Log a loading error
491 * the error description
493 public void setLastError(String error) {
494 this.lastError = error;
498 * @return the Xcos view
500 public XcosView getXcosView() {
505 * @return the Browser view
507 public BrowserView getBrowser() {
508 if (browser == null) {
509 browser = new BrowserView();
510 JavaController.register_view(BrowserView.class.getSimpleName(), browser);
516 * Clear the browser state and unregister the current view.
518 public void clearBrowser() {
519 if (browser != null) {
520 JavaController.unregister_view(browser);
526 * Get an unmodifiable view of the diagrams for an UID
530 * @return the diagram collection
532 public Collection<XcosDiagram> getDiagrams(final ScicosObjectOwner root) {
533 final Collection<XcosDiagram> diags = diagrams.get(root);
537 return Collections.unmodifiableCollection(diags);
541 * Add a diagram to the diagram list for a file. Be sure to set the right opened status on the diagram before calling this method.
548 public void addDiagram(final ScicosObjectOwner root, final XcosDiagram diag) {
549 if (onDiagramIteration) {
550 throw new RuntimeException();
553 throw new IllegalArgumentException();
557 * Create the collection if it does not exist
559 List<XcosDiagram> diags = diagrams.get(root);
561 diags = createDiagramCollection();
562 diagrams.put(root, diags);
565 // insert the diagram
570 * Add a diagram to the opened list
572 * This method manage both super-block and root diagrams.
573 * @param diag the diagram to add
575 public void addDiagram(final XcosDiagram diag) {
576 ScicosObjectOwner root = findRoot(diag);
577 addDiagram(root, diag);
581 * Create a diagram collections (sorted List)
583 * @return the diagram collection
585 @SuppressWarnings("serial")
586 public List<XcosDiagram> createDiagramCollection() {
587 return new ArrayList<XcosDiagram>() {
589 public boolean add(XcosDiagram element) {
590 final boolean status = super.add(element);
591 DiagramComparator.sort(this);
596 public boolean addAll(Collection<? extends XcosDiagram> c) {
597 final boolean status = super.addAll(c);
598 DiagramComparator.sort(this);
605 * Try to close the graph (popup save dialog)
609 * @return if we can (or not) close the graph
611 public boolean canClose(final XcosDiagram graph) {
612 boolean canClose = false;
614 ScicosObjectOwner root = findRoot(graph);
616 final boolean wasLastOpened = openedDiagrams(root).size() <= 1;
617 final boolean isModified = isModified(root);
618 if (!(wasLastOpened && isModified)) {
623 final AnswerOption ans = ScilabModalDialog.show(XcosTab.get(graph), XcosMessages.DIAGRAM_MODIFIED, XcosMessages.XCOS, IconType.QUESTION_ICON,
624 ButtonType.YES_NO_CANCEL);
628 canClose = diagrams.get(root).iterator().next().saveDiagram();
631 canClose = true; // can close
634 canClose = false; // operation canceled
640 * Update configuration before the destroy call to validate the uuid
643 configuration.addToRecentTabs(graph);
644 configuration.saveConfig();
652 * This method must be called on the EDT thread.
655 * the diagram to close
657 public void destroy(XcosDiagram graph) {
658 ScicosObjectOwner root = findRoot(graph);
660 final boolean wasLastOpenedForFile = openedDiagrams(root).size() <= 1;
661 if (wasLastOpenedForFile) {
662 diagrams.remove(root);
664 diagrams.get(root).remove(graph);
667 if (openedDiagrams().size() <= 0) {
668 JavaController.end_simulation();
674 * the graph to handle
676 * the diagram to check
677 * @return diagram name for the "Are your sure ?" dialog
679 public String askForClosing(final XcosDiagram graph, final List<SwingScilabDockablePanel> list) {
682 if (wasLastOpened(list)) {
692 * Does Xcos will close or not ?
695 * the list to be closed
696 * @return true if all files will be close on tabs close.
698 public boolean wasLastOpened(final List<SwingScilabDockablePanel> list) {
699 final HashSet<String> opened = new HashSet<String>();
700 for (XcosDiagram diag : openedDiagrams()) {
701 opened.add(diag.getGraphTab());
704 final HashSet<String> tabs = new HashSet<String>();
705 for (SwingScilabDockablePanel tab : list) {
707 tabs.add(tab.getPersistentId());
711 opened.removeAll(tabs);
713 return opened.isEmpty();
717 * @return the external action list
719 public List<ExternalAction> getExternalActions() {
720 return externalActions;
724 * Close the current xcos session.
726 * This method must be called on the EDT thread. For other use, please use the {@link #closeXcosFromScilab()} method.
728 public static synchronized void closeSession(final boolean ask) {
729 if (!SwingUtilities.isEventDispatchThread()) {
730 LOG.severe(CALLED_OUTSIDE_THE_EDT_THREAD);
733 /* Doesn't instantiate xcos on close operation */
734 if (sharedInstance == null) {
739 * Try to close all opened files
741 final Xcos instance = sharedInstance;
744 final List<SwingScilabDockablePanel> tabs = new ArrayList<SwingScilabDockablePanel>();
745 for (final Collection<XcosDiagram> diags : instance.diagrams.values()) {
746 for (final XcosDiagram diag : diags) {
747 final SwingScilabDockablePanel tab = XcosTab.get(diag);
755 final boolean status = ClosingOperationsManager.startClosingOperation(tabs, ask, ask);
759 /* reset the shared instance state */
760 instance.diagrams.clear();
762 /* terminate any remaining simulation */
763 JavaController.end_simulation();
765 /* Saving modified data */
766 instance.palette.saveConfig();
767 instance.configuration.saveConfig();
772 * Scilab exported methods.
774 * All the following methods must use SwingUtilities method to assert that the operations will be called on the EDT thread.
776 * @see modules/xcos/src/jni/Xcos.giws.xml
778 * @see sci_gateway/xcos_gateway.xml
780 * @see modules/xcos/sci_gateway/cpp/sci_*.cpp
786 * This method invoke Xcos operation on the EDT thread.
789 * The filename (can be null)
791 * The Xcos DIAGRAM model ID (can be 0)
793 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
794 public static void xcos(final String file, final long diagramId) {
795 final Xcos instance = getInstance();
796 instance.lastError = null;
798 /* load scicos libraries (macros) */
799 InterpreterManagement.requestScilabExec(LOAD_XCOS_LIBS_LOAD_SCICOS);
801 synchronized (instance) {
805 SwingUtilities.invokeLater(new Runnable() {
809 instance.open(file, diagramId);
813 if (instance.lastError != null && !instance.lastError.isEmpty()) {
814 throw new RuntimeException(instance.lastError);
819 * Load or Save an xcos diagram without using Scilab at all.
822 * This support a reduced number of format and should be mainly used to test
827 * the diagram to load into
829 * flag used to indicate an export (true == export ; false == import)
833 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
834 public static void xcosDiagramToScilab(String file, long diagramId, boolean export) throws Exception {
835 XcosFileType filetype = XcosFileType.findFileType(file);
836 if (filetype == null) {
837 throw new IllegalArgumentException("not handled filetype");
840 if (XcosFileType.getAvailableSaveFormats().contains(filetype)) {
842 filetype.save(file, new XcosDiagram(new JavaController(), diagramId, Kind.DIAGRAM, ""));
844 filetype.load(file, new XcosDiagram(new JavaController(), diagramId, Kind.DIAGRAM, ""));
847 throw new IllegalArgumentException("not handled filetype");
852 * Close the current xcos session from any thread.
854 * This method invoke Xcos operation on the EDT thread. Please prefer using {@link #closeSession()} when the caller is on the EDT thread.
856 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
857 public static void closeXcosFromScilab() {
859 SwingUtilities.invokeAndWait(new Runnable() {
866 } catch (final InterruptedException e) {
868 } 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);
883 * Look in each diagram to find the block corresponding to the given uid and display a warning message.
885 * This method invoke Xcos operation on the EDT thread.
890 * The message to display.
892 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
893 public static void warnCellByUID(final String[] uids, final String message) {
895 SwingUtilities.invokeAndWait(new Runnable() {
898 getInstance().warnCell(uids, message);
901 } catch (final InterruptedException e) {
902 LOG.severe(e.toString());
903 } catch (final InvocationTargetException e) {
904 Throwable throwable = e;
905 String firstMessage = null;
906 while (throwable != null) {
907 firstMessage = throwable.getLocalizedMessage();
908 throwable = throwable.getCause();
911 throw new RuntimeException(firstMessage, e);
915 private void warnCell(final String[] uids, final String message) {
917 final mxCell[] cells = new mxCell[uids.length];
918 final XcosDiagram[] diags = new XcosDiagram[uids.length];
920 lookupForCells(uids, cells, diags);
921 for (int i = cells.length - 1; i >= 0; --i) {
922 mxCell cell = cells[i];
924 // perform the action on the last visible block
926 final XcosDiagram parent = diags[i];
927 parent.warnCellByUID(cell.getId(), message);
929 // Focus on an existing diagram
930 SwingUtilities.invokeLater(() -> {
931 XcosTab.get(parent).setCurrent();
940 public void lookupForCells(final String[] uid, final mxCell[] cells, final XcosDiagram[] diags) {
941 final List<XcosDiagram> all = openedDiagrams();
942 for (int i = 0; i < uid.length; i++) {
943 final String id = uid[i];
944 diags[i] = all.stream().filter(d -> ((XcosGraphModel) d.getModel()).getCell(id) != null)
945 .findFirst().orElse(null);
946 if (diags[i] != null) {
947 cells[i] = (mxCell) ((XcosGraphModel) diags[i].getModel()).getCell(id);
953 * Add a menu into xcos
958 * the callback (as a Scilab executable String)
960 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
961 public static void addToolsMenu(final String label, final String command) {
962 final ExternalAction action = new ExternalAction(null, command);
963 action.putValue(Action.NAME, label);
964 final Xcos instance = Xcos.getInstance();
967 * Store for future tabs
969 instance.externalActions.add(action);
974 for (final XcosDiagram d : instance.openedDiagrams()) {
975 final String uuid = d.getGraphTab();
976 final SwingScilabDockablePanel tab = ScilabTabFactory.getInstance().getFromCache(uuid);
979 final SwingScilabMenuBar bar = ((SwingScilabMenuBar) tab.getMenuBar().getAsSimpleMenuBar());
981 final Component[] comps = bar.getComponents();
982 for (Component component : comps) {
983 if (component instanceof SwingScilabMenu) {
984 final SwingScilabMenu menu = (SwingScilabMenu) component;
986 if (menu.getText() == XcosMessages.TOOLS) {
987 menu.add(new ExternalAction(action, d));
992 // Also update the parent window toolbar
993 BarUpdater.updateBars(tab.getParentWindowId(), tab.getMenuBar(), tab.getToolBar(), tab.getInfoBar(), tab.getName(), tab.getWindowIcon());
999 * Inform Xcos the simulator has just started
1002 @ScilabExported(module = "xcos", filename = "Xcos.giws.xml")
1003 public static void xcosSimulationStarted() {
1004 SwingUtilities.invokeLater(new Runnable() {
1007 GraphActionManager.setEnable(StopAction.class, true);
1013 * Look for the parent diagram of the cell in the diagram hierarchy.
1016 * the cell to search for
1017 * @return the associated diagram
1019 public static XcosDiagram findParent(Object cell) {
1020 final Xcos instance = getInstance();
1022 for (Collection<XcosDiagram> diags : instance.diagrams.values()) {
1023 for (XcosDiagram diag : diags) {
1024 final mxGraphModel model = (mxGraphModel) diag.getModel();
1026 // use the O(1) lookup
1027 if (cell instanceof mxICell && model.getCell(((mxICell) cell).getId()) != null) {
1037 * Look for the root object of the whole graph hierarchy
1038 * @param graph the graph
1039 * @return the root MVC object with Kind.DIAGRAM
1041 public static ScicosObjectOwner findRoot(XcosDiagram graph) {
1042 return findRoot(new JavaController(), graph);
1046 * Look for the root object of the whole graph hierarchy
1047 * @param controller the shared controller
1048 * @param graph the graph
1049 * @return the root MVC object with Kind.DIAGRAM
1051 public static ScicosObjectOwner findRoot(JavaController controller, XcosDiagram graph) {
1052 ScicosObjectOwner root;
1053 if (graph.getKind() == Kind.DIAGRAM) {
1054 root = new ScicosObjectOwner(controller, graph.getUID(), graph.getKind());
1056 long[] rootDiagram = new long[1];
1057 controller.getObjectProperty(graph.getUID(), graph.getKind(), ObjectProperties.PARENT_DIAGRAM, rootDiagram);
1058 root = new ScicosObjectOwner(controller, rootDiagram[0], Kind.DIAGRAM);
1066 * @see org.scilab.modules.gui.tabfactory.AbstractScilabTabFactory
1068 public static class XcosTabFactory extends AbstractScilabTabFactory {
1073 private DocumentType cachedDocumentType;
1076 * Default constructor
1078 public XcosTabFactory() {
1082 private XcosTabFactory(boolean instanciateXcos) {
1083 if (instanciateXcos) {
1089 * Create/restore a tab for a given uuid
1093 * @return the tab instance
1096 public synchronized SwingScilabDockablePanel getTab(final String uuid) {
1101 SwingScilabDockablePanel tab = ScilabTabFactory.getInstance().getFromCache(uuid);
1103 // Palette manager restore
1105 if (PaletteManagerView.DEFAULT_TAB_UUID.equals(uuid)) {
1106 PaletteManagerView.restore(null, false);
1107 tab = PaletteManagerView.get();
1111 // diagram (tab or viewport) restore
1114 if (cachedDocumentType == null) {
1118 final boolean isTab = uuid.equals(cachedDocumentType.getUuid());
1119 final boolean isViewport = uuid.equals(cachedDocumentType.getViewport());
1121 final XcosDiagram graph = getDiagram(isTab, isViewport);
1122 if (graph != null && isTab) {
1123 XcosTab.restore(graph, false);
1124 graph.fireEvent(new mxEventObject(mxEvent.ROOT));
1125 tab = XcosTab.get(graph);
1126 } else if (graph != null && isViewport) {
1127 ViewPortTab.restore(graph, false);
1128 tab = ViewPortTab.get(graph);
1130 ClosingOperationsManager.addDependency(XcosTab.get(graph), tab);
1131 WindowsConfigurationManager.makeDependency(graph.getGraphTab(), tab.getPersistentId());
1137 WindowsConfigurationManager.restorationFinished(tab);
1138 ScilabTabFactory.getInstance().addToCache(tab);
1143 private XcosDiagram getDiagram(boolean isTab, boolean isViewport) {
1144 final Xcos instance = getInstance();
1145 XcosDiagram graph = null;
1148 // load a new diagram
1149 graph = getInstance().configuration.loadDiagram(cachedDocumentType);
1150 } else if (isViewport) {
1151 // get the cached diagram
1152 final File f = instance.configuration.getFile(cachedDocumentType);
1153 final ScicosObjectOwner root = getInstance().openedDiagram(f);
1155 Collection<XcosDiagram> diags = instance.diagrams.getOrDefault(root, Collections.emptyList());
1156 for (XcosDiagram d : diags) {
1157 final String id = d.getGraphTab();
1158 if (id != null && id.equals(cachedDocumentType.getUuid())) {
1169 public synchronized boolean isAValidUUID(String uuid) {
1170 // check the Palette manager view (static uuid)
1171 if (PaletteManagerView.DEFAULT_TAB_UUID.equals(uuid)) {
1176 * Cache and check against cache to ease next getTab(uuid) call
1179 return cachedDocumentType != null;
1183 * Cache the {@link DocumentType} for the specific uuid
1188 private void cache(String uuid) {
1190 * Handle a non null cache
1192 if (cachedDocumentType != null) {
1193 final boolean isTab = uuid.equals(cachedDocumentType.getUuid());
1194 final boolean isViewport = uuid.equals(cachedDocumentType.getViewport());
1196 if (isTab || isViewport) {
1199 cachedDocumentType = null;
1204 * Invalid cache, look for the right one
1206 final ConfigurationManager config = getInstance().configuration;
1207 final List<DocumentType> docs = config.getSettings().getTab();
1208 for (DocumentType d : docs) {
1209 final boolean isTab = uuid.equals(d.getUuid());
1210 final boolean isViewport = uuid.equals(d.getViewport());
1212 if (isTab || isViewport) {
1213 cachedDocumentType = d;
1220 public String getPackage() {
1225 public String getClassName() {
1226 return XcosTabFactory.class.getName();
1230 public String getApplication() {
1235 // CSON: ClassDataAbstractionCoupling
1236 // CSON: ClassFanOutComplexity