2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010-2011 - DIGITEO - Clement DAVID
4 * Copyright (C) 2011-2017 - Scilab Enterprises - Clement DAVID
6 * Copyright (C) 2012 - 2016 - Scilab Enterprises
8 * This file is hereby licensed under the terms of the GNU GPL v2.0,
9 * pursuant to article 5.3.4 of the CeCILL v.2.1.
10 * This file was originally licensed under the terms of the CeCILL v2.1,
11 * and continues to be available under such terms.
12 * For more information, see the COPYING file which you should have received
13 * along with this program.
17 package org.scilab.modules.xcos;
19 import com.mxgraph.util.mxEvent;
20 import com.mxgraph.util.mxEventObject;
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.lang.ref.WeakReference;
24 import java.net.MalformedURLException;
26 import java.util.List;
27 import java.util.ListIterator;
28 import java.util.UUID;
29 import java.util.logging.Logger;
31 import javax.swing.JButton;
32 import javax.swing.JCheckBoxMenuItem;
34 import org.scilab.modules.graph.actions.CopyAction;
35 import org.scilab.modules.graph.actions.CutAction;
36 import org.scilab.modules.graph.actions.DeleteAction;
37 import org.scilab.modules.graph.actions.InvertSelectionAction;
38 import org.scilab.modules.graph.actions.PasteAction;
39 import org.scilab.modules.graph.actions.RedoAction;
40 import org.scilab.modules.graph.actions.SelectAllAction;
41 import org.scilab.modules.graph.actions.UndoAction;
42 import org.scilab.modules.graph.actions.ZoomInAction;
43 import org.scilab.modules.graph.actions.ZoomOutAction;
44 import org.scilab.modules.graph.event.ArrowKeyListener;
45 import org.scilab.modules.gui.bridge.menu.SwingScilabMenu;
46 import org.scilab.modules.gui.bridge.menuitem.SwingScilabMenuItem;
47 import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel;
48 import org.scilab.modules.gui.bridge.toolbar.SwingScilabToolBar;
49 import org.scilab.modules.gui.bridge.window.SwingScilabWindow;
50 import org.scilab.modules.gui.checkboxmenuitem.CheckBoxMenuItem;
51 import org.scilab.modules.gui.menu.Menu;
52 import org.scilab.modules.gui.menu.ScilabMenu;
53 import org.scilab.modules.gui.menubar.MenuBar;
54 import org.scilab.modules.gui.menubar.ScilabMenuBar;
55 import org.scilab.modules.gui.menuitem.MenuItem;
56 import org.scilab.modules.gui.menuitem.ScilabMenuItem;
57 import org.scilab.modules.gui.tab.SimpleTab;
58 import org.scilab.modules.gui.tabfactory.ScilabTabFactory;
59 import org.scilab.modules.gui.textbox.ScilabTextBox;
60 import org.scilab.modules.gui.toolbar.ScilabToolBar;
61 import org.scilab.modules.gui.toolbar.ToolBar;
62 import org.scilab.modules.gui.utils.BarUpdater;
63 import org.scilab.modules.gui.utils.ClosingOperationsManager;
64 import org.scilab.modules.gui.utils.WindowsConfigurationManager;
65 import org.scilab.modules.xcos.actions.AboutXcosAction;
66 import org.scilab.modules.xcos.actions.CloseAction;
67 import org.scilab.modules.xcos.actions.CompileAction;
68 import org.scilab.modules.xcos.actions.DebugLevelAction;
69 import org.scilab.modules.xcos.actions.DiagramBackgroundAction;
70 import org.scilab.modules.xcos.actions.EditFormatAction;
71 import org.scilab.modules.xcos.actions.ExportAction;
72 import org.scilab.modules.xcos.actions.ExportAllAction;
73 import org.scilab.modules.xcos.actions.ExternalAction;
74 import org.scilab.modules.xcos.actions.FitDiagramToViewAction;
75 import org.scilab.modules.xcos.actions.InitModelicaAction;
76 import org.scilab.modules.xcos.actions.NewDiagramAction;
77 import org.scilab.modules.xcos.actions.NormalViewAction;
78 import org.scilab.modules.xcos.actions.OpenAction;
79 import org.scilab.modules.xcos.actions.OpenInSciAction;
80 import org.scilab.modules.xcos.actions.PrintAction;
81 import org.scilab.modules.xcos.actions.QuitAction;
82 import org.scilab.modules.xcos.actions.RecentFileAction;
83 import org.scilab.modules.xcos.actions.SaveAction;
84 import org.scilab.modules.xcos.actions.SaveAsAction;
85 import org.scilab.modules.xcos.actions.SetContextAction;
86 import org.scilab.modules.xcos.actions.SetupAction;
87 import org.scilab.modules.xcos.actions.ShowHideShadowAction;
88 import org.scilab.modules.xcos.actions.StartAction;
89 import org.scilab.modules.xcos.actions.StopAction;
90 import org.scilab.modules.xcos.actions.ViewDiagramBrowserAction;
91 import org.scilab.modules.xcos.actions.ViewDiagramTreeShowAction;
92 import org.scilab.modules.xcos.actions.ViewGridAction;
93 import org.scilab.modules.xcos.actions.ViewViewportAction;
94 import org.scilab.modules.xcos.actions.XcosDemonstrationsAction;
95 import org.scilab.modules.xcos.actions.XcosDocumentationAction;
96 import org.scilab.modules.xcos.block.actions.AutoPositionSplitBlockAction;
97 import org.scilab.modules.xcos.block.actions.BlockDocumentationAction;
98 import org.scilab.modules.xcos.block.actions.BlockParametersAction;
99 import org.scilab.modules.xcos.block.actions.BorderColorAction;
100 import org.scilab.modules.xcos.block.actions.CodeGenerationAction;
101 import org.scilab.modules.xcos.block.actions.FilledColorAction;
102 import org.scilab.modules.xcos.block.actions.FlipAction;
103 import org.scilab.modules.xcos.block.actions.MirrorAction;
104 import org.scilab.modules.xcos.block.actions.RegionToSuperblockAction;
105 import org.scilab.modules.xcos.block.actions.RotateAction;
106 import org.scilab.modules.xcos.block.actions.ViewDetailsAction;
107 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockActionBottom;
108 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockActionCenter;
109 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockActionLeft;
110 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockActionMiddle;
111 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockActionRight;
112 import org.scilab.modules.xcos.block.actions.alignement.AlignBlockActionTop;
113 import org.scilab.modules.xcos.configuration.ConfigurationManager;
114 import org.scilab.modules.xcos.configuration.model.DocumentType;
115 import org.scilab.modules.xcos.configuration.utils.ConfigurationConstants;
116 import org.scilab.modules.xcos.graph.XcosDiagram;
117 import org.scilab.modules.xcos.link.actions.StyleHorizontalAction;
118 import org.scilab.modules.xcos.link.actions.StyleOptimalAction;
119 import org.scilab.modules.xcos.link.actions.StyleStraightAction;
120 import org.scilab.modules.xcos.link.actions.StyleVerticalAction;
121 import org.scilab.modules.xcos.palette.actions.ViewPaletteBrowserAction;
122 import org.scilab.modules.xcos.palette.view.PaletteManagerView;
123 import org.scilab.modules.xcos.preferences.XcosOptions;
124 import org.scilab.modules.xcos.utils.XcosMessages;
127 * Xcos tab operations
129 * This class implement specific operation of an Xcos Tab.
131 // CSOFF: ClassFanOutComplexity
132 // CSOFF: ClassDataAbstractionCoupling
133 @SuppressWarnings(value = { "serial" })
134 public class XcosTab extends SwingScilabDockablePanel implements SimpleTab {
135 public static final String DEFAULT_WIN_UUID = "xcos-default-window";
136 public static final String DEFAULT_TAB_UUID = "xcos-default-tab";
141 private MenuBar menuBar;
142 private Menu fileMenu;
143 private Menu recentsMenu;
146 private Menu simulate;
148 private Menu alignMenu;
149 private Menu blockPosition;
150 private Menu linkStyle;
154 private JCheckBoxMenuItem viewport;
156 private JButton openAction;
157 private JButton saveAction;
158 private JButton saveAsAction;
159 private JButton printAction;
160 private JButton newDiagramAction;
161 private JButton deleteAction;
162 private JButton undoAction;
163 private JButton redoAction;
164 private JButton fitDiagramToViewAction;
165 private JButton startAction;
166 private JButton stopAction;
167 private JButton zoomInAction;
168 private JButton zoomOutAction;
169 private JButton xcosDemonstrationAction;
170 private JButton xcosDocumentationAction;
172 private static class ClosingOperation implements org.scilab.modules.gui.utils.ClosingOperationsManager.ClosingOperation {
173 private final WeakReference<XcosDiagram> graph;
175 public ClosingOperation(XcosDiagram graph) {
176 this.graph = new WeakReference<XcosDiagram>(graph);
180 public int canClose() {
181 final XcosDiagram diag = graph.get();
186 return Xcos.getInstance().canClose(diag) ? 1 : 0;
190 public void destroy() {
191 final XcosDiagram diag = graph.get();
196 Xcos.getInstance().destroy(diag);
200 public String askForClosing(final List<SwingScilabDockablePanel> list) {
201 final XcosDiagram diag = graph.get();
206 return Xcos.getInstance().askForClosing(diag, list);
210 public void updateDependencies(List<SwingScilabDockablePanel> list, ListIterator<SwingScilabDockablePanel> it) {
211 final PaletteManagerView palette = PaletteManagerView.get();
214 * if palette is not visible, then break
216 if (palette == null) {
221 * If it already contains the palette, then break.
223 if (list.contains(palette)) {
227 final boolean wasLastOpened = Xcos.getInstance().wasLastOpened(list);
230 * Append the palette if all the xcos files will be closed
239 private static class EndedRestoration implements WindowsConfigurationManager.EndedRestoration {
240 private final WeakReference<XcosDiagram> graph;
242 public EndedRestoration(XcosDiagram graph) {
243 this.graph = new WeakReference<XcosDiagram>(graph);
247 public void finish() {
248 final XcosDiagram diag = graph.get();
253 diag.updateTabTitle();
255 ConfigurationManager.getInstance().removeFromRecentTabs(diag.getGraphTab());
260 * Default constructor
263 * The associated diagram
265 private XcosTab(XcosDiagram graph, String uuid) {
266 super(XcosMessages.XCOS, uuid);
268 setAssociatedXMLIDForHelp("xcos");
270 /** tab association */
271 graph.setGraphTab(uuid);
272 setWindowIcon(Xcos.ICON.getImage());
274 initComponents(graph);
276 graph.getAsComponent().addKeyListener(new ArrowKeyListener());
277 graph.getModel().addListener(mxEvent.CHANGE, (Object sender, mxEventObject evt) -> {
278 graph.setModified(true);
279 graph.updateTabTitle();
284 * Static API for Tabs
288 * Get the tab for a graph.
292 * @return the tab (can be null)
294 public static XcosTab get(XcosDiagram graph) {
295 final String uuid = graph.getGraphTab();
300 return (XcosTab) ScilabTabFactory.getInstance().getFromCache(uuid);
304 * Restore or create the viewport tab for the graph
309 public static void restore(XcosDiagram graph) {
310 restore(graph, true);
314 * Restore or create the tab for the graph
319 * should the tab should be visible
321 public static void restore(final XcosDiagram graph, final boolean visible) {
322 String uuid = graph.getGraphTab();
324 uuid = UUID.randomUUID().toString();
327 // FIXME: fix a crash on DnD and Tab restore
329 final XcosTab tab = new XcosTab(graph, uuid);
330 ScilabTabFactory.getInstance().addToCache(tab);
333 tab.createDefaultWindow().setVisible(true);
335 graph.updateTabTitle();
336 BarUpdater.updateBars(tab.getParentWindowId(), tab.getMenuBar(), tab.getToolBar(), tab.getInfoBar(), tab.getName(), tab.getWindowIcon());
339 ClosingOperationsManager.addDependencyWithRoot(tab);
340 ClosingOperationsManager.registerClosingOperation(tab, new ClosingOperation(graph));
341 WindowsConfigurationManager.registerEndedRestoration(tab, new EndedRestoration(graph));
345 * Specific implementation
349 * Instantiate all the subcomponents of this Tab.
354 private void initComponents(final XcosDiagram diagram) {
355 /* Create the menu bar */
356 menuBar = createMenuBar(diagram);
359 /* Create the toolbar */
360 final ToolBar toolBar = createToolBar(diagram);
363 // No SimpleTab.addMember(ScilabComponent ...) so perform a raw
365 setContentPane(diagram.getAsComponent());
367 /* Create the infoBar */
368 setInfoBar(ScilabTextBox.createTextBox());
372 * Create the windows menu bar
376 * @return the Xcos diagram menu bar
379 private MenuBar createMenuBar(final XcosDiagram diagram) {
381 menuBar = ScilabMenuBar.createMenuBar();
384 fileMenu = ScilabMenu.createMenu();
385 fileMenu.setText(XcosMessages.FILE);
386 fileMenu.setMnemonic('F');
388 fileMenu.add(NewDiagramAction.createMenu(diagram));
389 fileMenu.add(OpenAction.createMenu(diagram));
390 fileMenu.add(OpenInSciAction.createMenu(diagram));
391 recentsMenu = createRecentMenu();
392 fileMenu.add(recentsMenu);
393 fileMenu.addSeparator();
395 fileMenu.add(CloseAction.createMenu(diagram));
396 fileMenu.add(SaveAction.createMenu(diagram));
397 fileMenu.add(SaveAsAction.createMenu(diagram));
398 fileMenu.addSeparator();
400 fileMenu.add(ExportAction.createMenu(diagram));
401 fileMenu.add(ExportAllAction.createMenu(diagram));
402 fileMenu.addSeparator();
404 fileMenu.add(PrintAction.createMenu(diagram));
405 fileMenu.addSeparator();
406 fileMenu.add(QuitAction.createMenu(diagram));
408 menuBar.add(fileMenu);
411 edit = ScilabMenu.createMenu();
412 edit.setText(XcosMessages.EDIT);
413 edit.setMnemonic('E');
416 edit.add(UndoAction.undoMenu(diagram));
417 edit.add(RedoAction.redoMenu(diagram));
419 edit.add(CutAction.cutMenu(diagram));
420 edit.add(CopyAction.copyMenu(diagram));
421 edit.add(PasteAction.pasteMenu(diagram));
422 edit.add(DeleteAction.createMenu(diagram));
424 edit.add(SelectAllAction.createMenu(diagram));
425 edit.add(InvertSelectionAction.createMenu(diagram));
427 edit.add(BlockParametersAction.createMenu(diagram));
429 edit.add(RegionToSuperblockAction.createMenu(diagram));
432 view = ScilabMenu.createMenu();
433 view.setText(XcosMessages.VIEW);
434 view.setMnemonic('V');
437 view.add(ZoomInAction.zoominMenu(diagram));
438 view.add(ZoomOutAction.zoomoutMenu(diagram));
439 view.add(FitDiagramToViewAction.createMenu(diagram));
440 view.add(NormalViewAction.createMenu(diagram));
442 view.add(ViewPaletteBrowserAction.createCheckBoxMenu(diagram));
443 view.add(ViewDiagramTreeShowAction.createMenu(diagram));
444 view.add(ViewDiagramBrowserAction.createMenu(diagram));
445 final CheckBoxMenuItem menuItem = ViewViewportAction.createCheckBoxMenu(diagram);
446 viewport = (JCheckBoxMenuItem) menuItem.getAsSimpleCheckBoxMenuItem();
448 view.add(ViewDetailsAction.createMenu(diagram));
450 /** Simulation menu */
451 simulate = ScilabMenu.createMenu();
452 simulate.setText(XcosMessages.SIMULATION);
453 simulate.setMnemonic('S');
454 menuBar.add(simulate);
456 final MenuItem startMenu = StartAction.createMenu(diagram);
457 final MenuItem stopMenu = StopAction.createMenu(diagram);
459 simulate.add(SetupAction.createMenu(diagram));
460 simulate.add(DebugLevelAction.createMenu(diagram));
461 simulate.add(SetContextAction.createMenu(diagram));
462 simulate.add(CompileAction.createMenu(diagram));
463 simulate.add(InitModelicaAction.createMenu(diagram));
464 simulate.add(startMenu);
465 simulate.add(stopMenu);
468 format = ScilabMenu.createMenu();
469 format.setText(XcosMessages.FORMAT);
470 format.setMnemonic('O');
473 format.add(RotateAction.createMenu(diagram));
474 format.add(FlipAction.createMenu(diagram));
475 format.add(MirrorAction.createMenu(diagram));
476 format.add(ShowHideShadowAction.createMenu(diagram));
478 format.addSeparator();
479 alignMenu = ScilabMenu.createMenu();
480 alignMenu.setText(XcosMessages.ALIGN_BLOCKS);
481 alignMenu.add(AlignBlockActionLeft.createMenu(diagram));
482 alignMenu.add(AlignBlockActionCenter.createMenu(diagram));
483 alignMenu.add(AlignBlockActionRight.createMenu(diagram));
484 alignMenu.addSeparator();
485 alignMenu.add(AlignBlockActionTop.createMenu(diagram));
486 alignMenu.add(AlignBlockActionMiddle.createMenu(diagram));
487 alignMenu.add(AlignBlockActionBottom.createMenu(diagram));
488 format.add(alignMenu);
489 format.addSeparator();
491 format.add(EditFormatAction.createMenu(diagram));
492 format.add(BorderColorAction.createMenu(diagram));
493 format.add(FilledColorAction.createMenu(diagram));
494 format.addSeparator();
496 blockPosition = ScilabMenu.createMenu();
497 blockPosition.setText(XcosMessages.BLOCK_AUTO_POSITION);
498 blockPosition.add(AutoPositionSplitBlockAction.createMenu(diagram));
499 format.add(blockPosition);
500 format.addSeparator();
502 linkStyle = ScilabMenu.createMenu();
503 linkStyle.setText(XcosMessages.LINK_STYLE);
504 linkStyle.add(StyleHorizontalAction.createMenu(diagram));
505 linkStyle.add(StyleStraightAction.createMenu(diagram));
506 linkStyle.add(StyleVerticalAction.createMenu(diagram));
507 linkStyle.add(StyleOptimalAction.createMenu(diagram));
508 format.add(linkStyle);
509 format.addSeparator();
511 format.add(DiagramBackgroundAction.createMenu(diagram));
512 final CheckBoxMenuItem gridMenu = ViewGridAction.createCheckBoxMenu(diagram);
513 format.add(gridMenu);
516 tools = ScilabMenu.createMenu();
517 tools.setText(XcosMessages.TOOLS);
518 tools.setMnemonic('T');
521 tools.add(CodeGenerationAction.createMenu(diagram));
523 // add external action to the tools menu
524 final List<ExternalAction> externalActions = Xcos.getInstance().getExternalActions();
525 for (ExternalAction action : externalActions) {
526 final MenuItem item = ScilabMenuItem.createMenuItem();
528 final SwingScilabMenuItem swingItem = (SwingScilabMenuItem) item.getAsSimpleMenuItem();
529 swingItem.setAction(new ExternalAction(action, diagram));
535 help = ScilabMenu.createMenu();
536 help.setText(XcosMessages.HELP);
537 help.setMnemonic('?');
540 help.add(XcosDocumentationAction.createMenu(diagram));
541 help.add(BlockDocumentationAction.createMenu(diagram));
543 help.add(XcosDemonstrationsAction.createMenu(diagram));
545 help.add(AboutXcosAction.createMenu(diagram));
553 * Populate recent files menu according to xcos preferences
558 private void populateRecentMenu(final Menu recent) {
559 final ConfigurationManager manager = ConfigurationManager.getInstance();
560 final List<DocumentType> recentFiles = manager.getSettings().getRecent();
561 final int numberOfRecentlyOpen = XcosOptions.getPreferences().getNumberOfRecentlyOpen();
562 final int sizeOfMenu = Math.min(recentFiles.size(), numberOfRecentlyOpen);
563 for (int i = 0; i < sizeOfMenu; i++) {
566 url = new URL(recentFiles.get(i).getUrl());
567 } catch (final MalformedURLException e) {
568 Logger.getLogger(XcosTab.class.getName()).severe(e.toString());
571 recent.add(RecentFileAction.createMenu(url));
576 * Create the recent menu from the previously opened files
578 * @return the recent menu
580 private Menu createRecentMenu() {
583 recent = ScilabMenu.createMenu();
584 recent.setText(XcosMessages.RECENT_FILES);
586 populateRecentMenu(recent);
588 ConfigurationManager.getInstance().addPropertyChangeListener(ConfigurationConstants.RECENT_FILES_CHANGED, new PropertyChangeListener() {
590 public void propertyChange(final PropertyChangeEvent evt) {
591 assert evt.getPropertyName().equals(ConfigurationConstants.RECENT_FILES_CHANGED);
594 * Remove all items of the recent files menu
596 ((SwingScilabMenu) recent.getAsSimpleMenu()).removeAll();
599 * Populate recent files menu according to Xcos preferences
601 populateRecentMenu(recent);
609 * Create the Tab toolbar
612 * the associated diagram
615 private ToolBar createToolBar(final XcosDiagram diagram) {
616 final ToolBar toolBar = ScilabToolBar.createToolBar();
617 SwingScilabToolBar stb = (SwingScilabToolBar) toolBar.getAsSimpleToolBar();
619 newDiagramAction = NewDiagramAction.createButton(diagram);
620 stb.add(newDiagramAction);
622 openAction = OpenAction.createButton(diagram);
625 stb.add(OpenInSciAction.createButton(diagram));
629 saveAction = SaveAction.createButton(diagram);
631 saveAsAction = SaveAsAction.createButton(diagram);
632 stb.add(saveAsAction);
636 printAction = PrintAction.createButton(diagram);
637 stb.add(printAction);
641 deleteAction = DeleteAction.createButton(diagram);
642 stb.add(deleteAction);
647 undoAction = UndoAction.undoButton(diagram);
648 redoAction = RedoAction.redoButton(diagram);
654 fitDiagramToViewAction = FitDiagramToViewAction.createButton(diagram);
655 stb.add(fitDiagramToViewAction);
660 startAction = StartAction.createButton(diagram);
661 stopAction = StopAction.createButton(diagram);
663 stb.add(startAction);
669 zoomInAction = ZoomInAction.zoominButton(diagram);
670 stb.add(zoomInAction);
671 zoomOutAction = ZoomOutAction.zoomoutButton(diagram);
672 stb.add(zoomOutAction);
676 xcosDemonstrationAction = XcosDemonstrationsAction.createButton(diagram);
677 stb.add(xcosDemonstrationAction);
678 xcosDocumentationAction = XcosDocumentationAction.createButton(diagram);
679 stb.add(xcosDocumentationAction);
685 * Check/uncheck the viewport check box menu item
690 public void setViewportChecked(boolean status) {
691 viewport.setSelected(status);
695 * Get the check/uncheck status of the check box menu item
700 public boolean isViewportChecked() {
701 return viewport.isSelected();
704 private SwingScilabWindow createDefaultWindow() {
705 final SwingScilabWindow win;
707 final SwingScilabWindow configuration = WindowsConfigurationManager.createWindow(DEFAULT_WIN_UUID, false);
708 if (configuration != null) {
711 win = SwingScilabWindow.createWindow(true);
719 // CSON: ClassDataAbstractionCoupling
720 // CSON: ClassFanOutComplexity