2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2007 - INRIA - Vincent Couvert
4 * Copyright (C) 2007 - INRIA - Bruno JOFRET
5 * Copyright (C) 2007 - INRIA - Marouane BEN JELLOUL
6 * Copyright (C) 2009 - DIGITEO - Sylvestre LEDRU (Mac OS X port)
7 * Copyright (C) 2011 - DIGITEO - Vincent Couvert
9 * This file must be used under the terms of the CeCILL.
10 * This source file is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at
13 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
17 package org.scilab.modules.gui.bridge.window;
19 import org.flexdock.docking.Dockable;
20 import org.flexdock.docking.DockingManager;
21 import org.flexdock.docking.DockingPort;
22 import org.flexdock.docking.activation.ActiveDockableTracker;
23 import org.flexdock.docking.defaults.DefaultDockingPort;
24 import org.flexdock.docking.defaults.DefaultDockingStrategy;
25 import org.flexdock.docking.drag.effects.EffectsManager;
26 import org.flexdock.docking.drag.preview.GhostPreview;
27 import org.flexdock.docking.event.hierarchy.DockingPortTracker;
28 import org.scilab.modules.action_binding.InterpreterManagement;
29 import org.scilab.modules.commons.gui.ScilabKeyStroke;
30 import org.scilab.modules.gui.bridge.menubar.SwingScilabMenuBar;
31 import org.scilab.modules.gui.bridge.tab.SwingScilabTab;
32 import org.scilab.modules.gui.bridge.textbox.SwingScilabTextBox;
33 import org.scilab.modules.gui.bridge.toolbar.SwingScilabToolBar;
34 import org.scilab.modules.gui.menubar.MenuBar;
35 import org.scilab.modules.gui.menubar.SimpleMenuBar;
36 import org.scilab.modules.gui.tab.SimpleTab;
37 import org.scilab.modules.gui.textbox.SimpleTextBox;
38 import org.scilab.modules.gui.textbox.TextBox;
39 import org.scilab.modules.gui.toolbar.SimpleToolBar;
40 import org.scilab.modules.gui.toolbar.ToolBar;
41 import org.scilab.modules.gui.utils.ClosingOperationsManager;
42 import org.scilab.modules.gui.utils.Position;
43 import org.scilab.modules.gui.utils.SciDockingListener;
44 import org.scilab.modules.gui.utils.ScilabSwingUtilities;
45 import org.scilab.modules.gui.utils.Size;
46 import org.scilab.modules.gui.window.SimpleWindow;
48 import javax.swing.ImageIcon;
49 import javax.swing.JComponent;
50 import javax.swing.JFrame;
51 import javax.swing.SwingUtilities;
52 import javax.swing.WindowConstants;
53 import java.awt.Dimension;
54 import java.awt.Frame;
55 import java.awt.event.ActionEvent;
56 import java.awt.event.ActionListener;
57 import java.awt.event.WindowAdapter;
58 import java.awt.event.WindowEvent;
59 import java.lang.reflect.InvocationTargetException;
60 import java.rmi.server.UID;
61 import java.util.Collections;
62 import java.util.HashMap;
63 import java.util.Iterator;
66 import java.util.UUID;
69 * Swing implementation for Scilab windows in GUIs
70 * This implementation uses FlexDock package
71 * @author Vincent COUVERT
72 * @author Bruno JOFRET
73 * @author Marouane BEN JELLOUL
74 * @author Sylvestre LEDRU (Mac OS X port)
77 public class SwingScilabWindow extends JFrame implements SimpleWindow {
79 private static final long serialVersionUID = -5661926417765805660L;
81 private static final int DEFAULTWIDTH = 500;
82 private static final int DEFAULTHEIGHT = 500;
84 public static Map<String, SwingScilabWindow> allScilabWindows = Collections.synchronizedMap(new HashMap<String, SwingScilabWindow>());
87 DefaultDockingStrategy.setDefaultResizeWeight(0.5);
88 DefaultDockingStrategy.keepConstantPercentage(true);
91 private DefaultDockingPort sciDockingPort;
92 private SciDockingListener sciDockingListener;
93 private SimpleMenuBar menuBar;
94 private SimpleToolBar toolBar;
95 private SimpleTextBox infoBar;
97 private int elementId; // the id of the Window which contains this SimpleWindow
98 private String windowUID;
99 private final boolean MAC_OS_X = (System.getProperty("os.name").toLowerCase().startsWith("mac os x"));
104 public SwingScilabWindow() {
106 this.uuid = UUID.randomUUID().toString();
108 setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
110 // By default ctrl+w close the window
111 ActionListener listener = new ActionListener() {
113 public void actionPerformed(ActionEvent e) {
114 processWindowEvent(new WindowEvent(SwingScilabWindow.this, WindowEvent.WINDOW_CLOSING));
117 getRootPane().registerKeyboardAction(listener, ScilabKeyStroke.getKeyStroke("OSSCKEY W"), JComponent.WHEN_IN_FOCUSED_WINDOW);
119 // TODO : Only for testing : Must be removed
120 this.setDims(new Size(DEFAULTWIDTH, DEFAULTHEIGHT));
121 this.setTitle("Scilab");
122 setIconImage(new ImageIcon(ScilabSwingUtilities.findIcon("scilab", "256x256")).getImage());
124 /* defining the Layout */
125 super.setLayout(new java.awt.BorderLayout());
127 /* Create automatically a docking port associated to the window */
128 sciDockingPort = new DefaultDockingPort();
130 EffectsManager.setPreview(new GhostPreview());
132 /* The docking port is the center of the Layout of the Window */
133 super.add(sciDockingPort, java.awt.BorderLayout.CENTER);
135 /* there is no menuBar, no toolBar and no infoBar at creation */
140 sciDockingListener = new SciDockingListener();
141 sciDockingPort.addDockingListener(sciDockingListener);
144 * Prevent the background RootPane to catch Focus.
145 * Causes trouble with Scicos use xclick & co.
147 //this.setFocusable(false);
149 // let the OS choose the window position if not specified by user.
150 setLocationByPlatform(true);
152 addWindowListener(new WindowAdapter() {
154 public void windowClosing(WindowEvent e) {
155 ClosingOperationsManager.startClosingOperation(SwingScilabWindow.this);
160 registerForMacOSXEvents();
163 windowUID = new UID().toString();
165 sciDockingListener.setAssociatedWindowId(windowUID);
167 allScilabWindows.put(windowUID, this);
171 * This method registers some methods against the specific Mac OS X API
172 * (in order to set the "special" mac os x menus)
174 private void registerForMacOSXEvents() {
176 // Generate and register the OSXAdapter, passing it a hash of all the methods we wish to
177 // use as delegates for various com.apple.eawt.ApplicationListener methods
178 OSXAdapter.setAboutHandler(this, getClass().getDeclaredMethod("macosxAbout", (Class[]) null));
179 OSXAdapter.setQuitHandler(this, getClass().getDeclaredMethod("macosxQuit", (Class[]) null));
180 OSXAdapter.setPreferencesHandler(this, getClass().getDeclaredMethod("macosxPreferences", (Class[]) null));
181 OSXAdapter.setDockIcon(new ImageIcon(ScilabSwingUtilities.findIcon("puffin", "256x256")));
182 } catch (java.lang.NoSuchMethodException e) {
183 System.err.println("OSXAdapter could not find the method: " + e.getLocalizedMessage());
188 * This method is called by the OSXAdapter class when the specific Mac
189 * OS X "About" menu is called. It is the only case where this method
192 public void macosxAbout() {
193 InterpreterManagement.requestScilabExec("about();");
197 * This method is called by the OSXAdapter class when the specific Mac
198 * OS X "Quit Scilab" menu is called. It is the only case where this method
201 public boolean macosxQuit() {
202 InterpreterManagement.requestScilabExec("exit();");
207 * This method is called by the OSXAdapter class when the specific Mac
208 * OS X "Preferences" menu is called. It is the only case where this method
211 public void macosxPreferences() {
212 InterpreterManagement.requestScilabExec("preferences();");
216 * @return the UUID associated with this window
218 public String getUUID() {
223 * @param uuid the UUID associated with this window
225 public void setUUID(String uuid) {
230 * Creates a swing Scilab window
231 * @return the created window
233 public static SimpleWindow createWindow() {
234 return new SwingScilabWindow();
238 * Draws a swing Scilab window
239 * @see org.scilab.modules.gui.uielement.UIElement#draw()
243 this.setVisible(true);
248 * Private method to raise to the front the window
250 private void raiseToFront() {
254 // deiconify the window if needed
257 // put it in front of others
262 * Deiconify the window and put it in front of other window
265 public void raise() {
266 // blocking call. So graphic synchronization must be desactivated here.
267 if (!SwingUtilities.isEventDispatchThread()) {
268 /* javasci bug: See bug 9544 why we are doing this check */
270 SwingUtilities.invokeAndWait(new Runnable() {
276 } catch (InterruptedException e) {
278 } catch (InvocationTargetException e) {
287 * Gets the dimensions (width and height) of a swing Scilab window
288 * @return the dimensions of the window
289 * @see org.scilab.modules.gui.uielement.UIElement#getDims()
292 public Size getDims() {
293 return new Size(getSize().width, getSize().height);
297 * Sets the dimensions (width and height) of a swing Scilab window
298 * @param newWindowSize the dimensions to set to the window
299 * @see org.scilab.modules.gui.uielement.UIElement#setDims(org.scilab.modules.gui.utils.Size)
302 public void setDims(Size newWindowSize) {
303 //if (!SwingUtilities.isEventDispatchThread()) {
304 if (getDims().getWidth() != newWindowSize.getWidth() || getDims().getHeight() != newWindowSize.getHeight()) {
305 Dimension finalDim = new Dimension(newWindowSize.getWidth(), newWindowSize.getHeight());
308 // validate so the new values are taken into account immediately
315 * Gets the position (X-coordinate and Y-coordinate) of a swing Scilab window
316 * @return the position of the window
317 * @see org.scilab.modules.gui.uielement.UIElement#getPosition()
320 public Position getPosition() {
321 return new Position(this.getX(), this.getY());
325 * Sets the position (X-coordinate and Y-coordinate) of a swing Scilab window
326 * @param newWindowPosition the position to set to the window
327 * @see org.scilab.modules.gui.uielement.UIElement#setPosition(org.scilab.modules.gui.utils.Position)
330 public void setPosition(Position newWindowPosition) {
331 //if (!SwingUtilities.isEventDispatchThread()) {
332 if (getPosition().getX() != newWindowPosition.getX() || getPosition().getY() != newWindowPosition.getY()) {
333 this.setLocation(newWindowPosition.getX(), newWindowPosition.getY());
339 * Gets the title of a swing Scilab window
340 * @return the title of the window
341 * @see javax.swing.JFrame#getTitle()
344 public String getTitle() {
345 return super.getTitle();
349 * Sets the title of a swing Scilab window
350 * @param newWindowTitle the title to set to the window
351 * @see java.awt.Frame#setTitle(java.lang.String)
354 public void setTitle(String newWindowTitle) {
355 // set only if required
356 if (newWindowTitle != null && !newWindowTitle.equals(getTitle())) {
357 super.setTitle(newWindowTitle);
365 public void setName(String name) {
371 * Gets the docking port associated to the window (created by default at window creation)
372 * @return the docking port associated to the window
374 public DockingPort getDockingPort() {
375 //return (DockingPort) centerFrame.getContentPane();
376 return sciDockingPort;
380 * Add a Scilab tab to a Scilab window
381 * @param newTab the Scilab tab to add to the Scilab window
382 * @see org.scilab.modules.gui.window.Window#addTab(org.scilab.modules.gui.tab.Tab)
385 public void addTab(SimpleTab newTab) {
386 SwingScilabTab tab = (SwingScilabTab) newTab;
387 tab.setParentWindowId(this.windowUID);
388 DockingManager.dock(tab, this.getDockingPort());
389 ActiveDockableTracker.requestDockableActivation(tab);
393 * Remove a Scilab tab from a Scilab window
394 * @param tabs the Scilab tabs to remove from the Scilab window
395 * @see org.scilab.modules.gui.window.Window#removeTab(org.scilab.modules.gui.tab.Tab)
397 public void removeTabs(SwingScilabTab[] tabs) {
398 for (SwingScilabTab tab : tabs) {
399 DockingManager.unregisterDockable((Dockable) tab);
401 DockingManager.close(tab);
404 if (getDockingPort() == null || getDockingPort().getDockables().isEmpty()) {
406 if (toolBar != null) {
407 ((SwingScilabToolBar) toolBar).close();
409 if (menuBar != null) {
410 ((SwingScilabMenuBar) menuBar).close();
417 /* Make sur a Tab is active */
418 Set<SwingScilabTab> docks = sciDockingPort.getDockables();
419 Iterator<SwingScilabTab> it = docks.iterator();
420 ActiveDockableTracker.requestDockableActivation(it.next());
425 * Remove a Scilab tab from a Scilab window
426 * @param tab the Scilab tab to remove from the Scilab window
427 * @see org.scilab.modules.gui.window.Window#removeTab(org.scilab.modules.gui.tab.Tab)
430 public void removeTab(SimpleTab tab) {
431 removeTabs(new SwingScilabTab[] {(SwingScilabTab) tab});
435 * Sets a Scilab MenuBar to a Scilab window
436 * @param newMenuBar the Scilab MenuBar to add to the Scilab window
437 * @see org.scilab.modules.gui.window.Window#addMenuBar(org.scilab.modules.gui.menubar.MenuBar)
440 public void addMenuBar(MenuBar newMenuBar) {
441 if (newMenuBar == null) {
442 if (this.menuBar != null) {
444 super.setJMenuBar(null);
446 // else nothing to do both are null
448 if (this.menuBar != newMenuBar.getAsSimpleMenuBar()) {
449 this.menuBar = newMenuBar.getAsSimpleMenuBar();
450 super.setJMenuBar((SwingScilabMenuBar) newMenuBar.getAsSimpleMenuBar());
452 // else nothing to do element alredy set
457 * Sets a Scilab ToolBar to a Scilab window
458 * @param newToolBar the Scilab ToolBar to set to the Scilab window
459 * @see org.scilab.modules.gui.window.Window#addToolBar(org.scilab.modules.gui.toolbar.ToolBar)
462 public void addToolBar(ToolBar newToolBar) {
463 if (newToolBar == null) {
464 if (this.toolBar != null) {
465 // Remove old InfoBar if already set
466 super.remove((SwingScilabToolBar) this.toolBar);
469 // else nothing to do both are null
471 if (this.toolBar != newToolBar.getAsSimpleToolBar()) {
472 if (this.toolBar != null) {
473 // Remove old InfoBar if already set
474 super.remove((SwingScilabToolBar) this.toolBar);
476 this.toolBar = newToolBar.getAsSimpleToolBar();
477 super.add((SwingScilabToolBar) this.toolBar, java.awt.BorderLayout.PAGE_START);
479 // else nothing to do element alredy set
484 * Sets a Scilab InfoBar to a Scilab window
485 * @param newInfoBar the Scilab InfoBar to set to the Scilab window
486 * @see org.scilab.modules.gui.window.Window#addInfoBar(org.scilab.modules.gui.textbox.TextBox)
489 public void addInfoBar(TextBox newInfoBar) {
490 if (newInfoBar == null) {
491 if (this.infoBar != null) {
492 // Remove old InfoBar if already set
493 super.remove((SwingScilabTextBox) this.infoBar);
496 // else nothing to do both are null
498 if (this.infoBar != newInfoBar.getAsSimpleTextBox()) {
499 if (this.infoBar != null) {
500 // Remove old InfoBar if already set
501 super.remove((SwingScilabTextBox) this.infoBar);
503 this.infoBar = newInfoBar.getAsSimpleTextBox();
504 super.add((SwingScilabTextBox) this.infoBar, java.awt.BorderLayout.PAGE_END);
506 // else nothing to do element alredy set
511 * Get the element id for this window
512 * @return id the id of the corresponding window object
515 public int getElementId() {
520 * Set the element id for this window
521 * @param id the id of the corresponding window object
524 public void setElementId(int id) {System.out.println("Window="+id);
526 //sciDockingListener.setAssociatedWindowId(id);
531 * @see org.scilab.modules.gui.window.SimpleWindow#close()
534 public void close() {
537 // disable docking port
538 ActiveDockableTracker.getTracker(this).setActive(null);
539 if (sciDockingPort != null) {
540 sciDockingPort.removeDockingListener(sciDockingListener);
541 sciDockingPort = null;
542 sciDockingListener = null;
544 DockingPortTracker.remove(this);
545 } catch (IllegalStateException e) {
546 enableInputMethods(false);
548 allScilabWindows.remove(windowUID);
552 * @return number of objects (tabs) docked in this window
555 public int getNbDockedObjects() {
556 return sciDockingPort.getDockables().size();
560 * Update the dimension of the window and its component.
561 * Only useful when the window is not yet visible
564 public void updateDimensions() {
572 public void windowDeiconified() {
573 super.setState(Frame.NORMAL);
580 public void windowIconified() {
581 super.setState(Frame.ICONIFIED);
588 public void windowMaximized() {
589 super.setExtendedState(Frame.MAXIMIZED_BOTH);
593 * Window is in the "normal" state.
596 public void windowNormal() {
597 super.setState(Frame.NORMAL);
604 public String getId() {