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)
8 * This file must be used under the terms of the CeCILL.
9 * This source file is licensed as described in the file COPYING, which
10 * you should have received as part of this distribution. The terms
11 * are also available at
12 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
16 package org.scilab.modules.gui.bridge.window;
18 import java.awt.Dimension;
19 import java.awt.Point;
20 import java.awt.Frame;
21 import java.awt.event.ActionEvent;
22 import java.awt.event.ActionListener;
23 import java.awt.event.WindowAdapter;
24 import java.awt.event.WindowEvent;
25 import java.lang.reflect.InvocationTargetException;
26 import java.util.ArrayList;
27 import java.util.Iterator;
28 import java.util.List;
30 import java.util.UUID;
32 import javax.swing.ImageIcon;
33 import javax.swing.JComponent;
34 import javax.swing.JFrame;
35 import javax.swing.JSplitPane;
36 import javax.swing.SwingUtilities;
37 import javax.swing.WindowConstants;
39 import org.flexdock.docking.Dockable;
40 import org.flexdock.docking.DockingConstants;
41 import org.flexdock.docking.DockingManager;
42 import org.flexdock.docking.DockingPort;
43 import org.flexdock.docking.DockingStrategy;
44 import org.flexdock.docking.activation.ActiveDockableTracker;
45 import org.flexdock.docking.defaults.DefaultDockingPort;
46 import org.flexdock.docking.defaults.DefaultDockingStrategy;
47 import org.flexdock.view.View;
48 import org.scilab.modules.action_binding.InterpreterManagement;
49 import org.scilab.modules.commons.gui.ScilabKeyStroke;
50 import org.scilab.modules.gui.bridge.menubar.SwingScilabMenuBar;
51 import org.scilab.modules.gui.bridge.tab.SwingScilabTab;
52 import org.scilab.modules.gui.bridge.textbox.SwingScilabTextBox;
53 import org.scilab.modules.gui.bridge.toolbar.SwingScilabToolBar;
54 import org.scilab.modules.gui.menubar.MenuBar;
55 import org.scilab.modules.gui.menubar.SimpleMenuBar;
56 import org.scilab.modules.gui.tab.Tab;
57 import org.scilab.modules.gui.textbox.SimpleTextBox;
58 import org.scilab.modules.gui.textbox.TextBox;
59 import org.scilab.modules.gui.toolbar.SimpleToolBar;
60 import org.scilab.modules.gui.toolbar.ToolBar;
61 import org.scilab.modules.gui.utils.ClosingOperationsManager;
62 import org.scilab.modules.gui.utils.Position;
63 import org.scilab.modules.gui.utils.SciDockingListener;
64 import org.scilab.modules.gui.utils.Size;
65 import org.scilab.modules.gui.utils.UIElementMapper;
66 import org.scilab.modules.gui.utils.WindowsConfigurationManager;
67 import org.scilab.modules.gui.window.SimpleWindow;
68 import org.scilab.modules.renderer.utils.RenderingCapabilities;
71 * Swing implementation for Scilab windows in GUIs
72 * This implementation uses FlexDock package
73 * @author Vincent COUVERT
74 * @author Bruno JOFRET
75 * @author Marouane BEN JELLOUL
76 * @author Sylvestre LEDRU (Mac OS X port)
79 public class SwingScilabWindow extends JFrame implements SimpleWindow {
81 private static final long serialVersionUID = -5661926417765805660L;
83 private static final int DEFAULTWIDTH = 500;
84 private static final int DEFAULTHEIGHT = 500;
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 boolean MAC_OS_X = (System.getProperty("os.name").toLowerCase().startsWith("mac os x"));
103 public SwingScilabWindow() {
105 this.uuid = UUID.randomUUID().toString();
107 setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
109 // By default ctrl+w close the window
110 ActionListener listener = new ActionListener() {
111 public void actionPerformed(ActionEvent e) {
112 processWindowEvent(new WindowEvent(SwingScilabWindow.this, WindowEvent.WINDOW_CLOSING));
115 getRootPane().registerKeyboardAction(listener, ScilabKeyStroke.getKeyStroke("OSSCKEY W"), JComponent.WHEN_IN_FOCUSED_WINDOW);
117 // TODO : Only for testing : Must be removed
118 this.setDims(new Size(DEFAULTWIDTH, DEFAULTHEIGHT));
119 this.setTitle("Scilab");
120 setIconImage(new ImageIcon(System.getenv("SCI") + "/modules/gui/images/icons/scilab.png").getImage());
122 /* defining the Layout */
123 super.setLayout(new java.awt.BorderLayout());
125 /* Create automatically a docking port associated to the window */
126 sciDockingPort = new DefaultDockingPort();
128 //EffectsManager.setPreview(new GhostPreview());
130 /* The docking port is the center of the Layout of the Window */
131 super.add(sciDockingPort, java.awt.BorderLayout.CENTER);
133 /* there is no menuBar, no toolBar and no infoBar at creation */
138 sciDockingListener = new SciDockingListener();
139 sciDockingPort.addDockingListener(sciDockingListener);
142 * Prevent the background RootPane to catch Focus.
143 * Causes trouble with Scicos use xclick & co.
145 this.setFocusable(false);
147 // let the OS choose the window position if not specified by user.
148 setLocationByPlatform(true);
150 addWindowListener(new WindowAdapter() {
151 public void windowClosing(WindowEvent e) {
152 ClosingOperationsManager.startClosingOperation(SwingScilabWindow.this);
157 registerForMacOSXEvents();
162 * This method registers some methods against the specific Mac OS X API
163 * (in order to set the "special" mac os x menus)
165 private void registerForMacOSXEvents() {
167 // Generate and register the OSXAdapter, passing it a hash of all the methods we wish to
168 // use as delegates for various com.apple.eawt.ApplicationListener methods
169 OSXAdapter.setAboutHandler(this, getClass().getDeclaredMethod("OSXabout", (Class[])null));
170 OSXAdapter.setQuitHandler(this, getClass().getDeclaredMethod("OSXquit", (Class[])null));
171 OSXAdapter.setDockIcon(System.getenv("SCI") + "/desktop/puffin.png");
172 } catch (java.lang.NoSuchMethodException e) {
173 System.err.println("OSXAdapter could not find the method: "+e.getLocalizedMessage());
178 * This method is called by the OSXAdapter class when the specific Mac
179 * OS X about menu is called. It is the only case where this method
182 public void OSXabout() {
183 InterpreterManagement.requestScilabExec("about()");
186 public void OSXquit() {
187 InterpreterManagement.requestScilabExec("exit()");
191 * @return the UUID associated with this window
193 public String getUUID() {
198 * @param uuid the UUID associated with this window
200 public void setUUID(String uuid) {
205 * Creates a swing Scilab window
206 * @return the created window
208 public static SimpleWindow createWindow() {
209 return new SwingScilabWindow();
213 * Draws a swing Scilab window
214 * @see org.scilab.modules.gui.UIElement#draw()
217 this.setVisible(true);
222 * Private method to raise to the front the window
224 private void raiseToFront() {
228 // deiconify the window if needed
231 // put it in front of others
236 * Deiconify the window and put it in front of other window
238 public void raise() {
239 // blocking call. So graphic synchronization must be desactivated here.
240 if (!SwingUtilities.isEventDispatchThread()) {
241 /* javasci bug: See bug 9544 why we are doing this check */
243 SwingUtilities.invokeAndWait(new Runnable() {
248 } catch (InterruptedException e) {
250 } catch (InvocationTargetException e) {
259 * Gets the dimensions (width and height) of a swing Scilab window
260 * @return the dimensions of the window
261 * @see org.scilab.modules.gui.UIElement#getDims()
263 public Size getDims() {
264 return new Size(getSize().width, getSize().height);
268 * Sets the dimensions (width and height) of a swing Scilab window
269 * @param newWindowSize the dimensions to set to the window
270 * @see org.scilab.modules.gui.UIElement#setDims(org.scilab.modules.gui.utils.Size)
272 public void setDims(Size newWindowSize) {
273 // get the greatest size we can use
274 int[] maxSize = RenderingCapabilities.getMaxWindowSize();
276 // make suze size is not greater than the max size
277 Dimension finalDim = new Dimension(Math.min(newWindowSize.getWidth(), maxSize[0]),
278 Math.min(newWindowSize.getHeight(), maxSize[1]));
281 // validate so the new values are taken into account immediately
286 * Gets the position (X-coordinate and Y-coordinate) of a swing Scilab window
287 * @return the position of the window
288 * @see org.scilab.modules.gui.UIElement#getPosition()
290 public Position getPosition() {
291 return new Position(this.getX(), this.getY());
295 * Sets the position (X-coordinate and Y-coordinate) of a swing Scilab window
296 * @param newWindowPosition the position to set to the window
297 * @see org.scilab.modules.gui.UIElement#setPosition(org.scilab.modules.gui.utils.Position)
299 public void setPosition(Position newWindowPosition) {
300 this.setLocation(newWindowPosition.getX(), newWindowPosition.getY());
304 * Gets the title of a swing Scilab window
305 * @return the title of the window
306 * @see java.awt.Frame#getTitle(java.lang.String)
308 public String getTitle() {
309 return super.getTitle();
313 * Sets the title of a swing Scilab window
314 * @param newWindowTitle the title to set to the window
315 * @see java.awt.Frame#setTitle(java.lang.String)
317 public void setTitle(String newWindowTitle) {
318 // set only if required
319 if (newWindowTitle != null && !newWindowTitle.equals(getTitle())) {
320 super.setTitle(newWindowTitle);
327 public void setName(String name) {
333 * Gets the docking port associated to the window (created by default at window creation)
334 * @return the docking port associated to the window
336 public DockingPort getDockingPort() {
337 //return (DockingPort) centerFrame.getContentPane();
338 return (DockingPort) sciDockingPort;
342 * Add a Scilab tab to a Scilab window
343 * @param newTab the Scilab tab to add to the Scilab window
344 * @see org.scilab.modules.gui.window.Window#addTab(org.scilab.modules.gui.tab.Tab)
346 public void addTab(Tab newTab) {
347 final SwingScilabTab tabImpl = ((SwingScilabTab) newTab.getAsSimpleTab());
349 tabImpl.setParentWindowId(this.elementId);
350 DockingManager.dock(tabImpl, this.getDockingPort());
351 ActiveDockableTracker.requestDockableActivation(tabImpl);
355 * Remove a Scilab tab from a Scilab window
356 * @param tab the Scilab tab to remove from the Scilab window
357 * @see org.scilab.modules.gui.window.Window#removeTab(org.scilab.modules.gui.tab.Tab)
359 public void removeTabs(SwingScilabTab[] tabs) {
360 for (SwingScilabTab tab : tabs) {
361 DockingManager.unregisterDockable((Dockable) tab);
363 DockingManager.close(tab);
365 if (getDockingPort().getDockables().isEmpty()) {
367 if (toolBar != null) {
368 ((SwingScilabToolBar) toolBar).close();
370 if (menuBar != null) {
371 UIElementMapper.removeMapping(menuBar.getElementId());
373 UIElementMapper.removeMapping(this.elementId);
379 // disable docking port
380 ActiveDockableTracker.getTracker(this).setActive(null);
381 sciDockingPort.removeDockingListener(sciDockingListener);
382 sciDockingPort = null;
383 sciDockingListener = null;
385 /* Make sur a Tab is active */
386 Set<SwingScilabTab> docks = sciDockingPort.getDockables();
387 Iterator<SwingScilabTab> it = docks.iterator();
388 ActiveDockableTracker.requestDockableActivation((SwingScilabTab) it.next());
393 * Remove a Scilab tab from a Scilab window
394 * @param tab the Scilab tab to remove from the Scilab window
395 * @see org.scilab.modules.gui.window.Window#removeTab(org.scilab.modules.gui.tab.Tab)
397 public void removeTab(Tab tab) {
398 removeTabs(new SwingScilabTab[]{(SwingScilabTab) tab.getAsSimpleTab()});
402 * Sets a Scilab MenuBar to a Scilab window
403 * @param newMenuBar the Scilab MenuBar to add to the Scilab window
404 * @see org.scilab.modules.gui.window.Window#setMenuBar(org.scilab.modules.gui.menubar.MenuBar)
406 public void addMenuBar(MenuBar newMenuBar) {
407 if (newMenuBar == null) {
408 if (this.menuBar != null) {
410 super.setJMenuBar(null);
413 // else nothing to do both are null
415 if (this.menuBar != newMenuBar.getAsSimpleMenuBar()) {
416 this.menuBar = newMenuBar.getAsSimpleMenuBar();
417 super.setJMenuBar((SwingScilabMenuBar) newMenuBar.getAsSimpleMenuBar());
420 // else nothing to do element alredy set
425 * Sets a Scilab ToolBar to a Scilab window
426 * @param newToolBar the Scilab ToolBar to set to the Scilab window
427 * @see org.scilab.modules.gui.window.Window#setToolBar(org.scilab.modules.gui.toolbar.ToolBar)
429 public void addToolBar(ToolBar newToolBar) {
430 if (newToolBar == null) {
431 if (this.toolBar != null) {
432 // Remove old InfoBar if already set
433 super.remove((SwingScilabToolBar) this.toolBar);
437 // else nothing to do both are null
439 if (this.toolBar != newToolBar.getAsSimpleToolBar()) {
440 if (this.toolBar != null) {
441 // Remove old InfoBar if already set
442 super.remove((SwingScilabToolBar) this.toolBar);
444 this.toolBar = newToolBar.getAsSimpleToolBar();
445 super.add((SwingScilabToolBar) this.toolBar, java.awt.BorderLayout.PAGE_START);
448 // else nothing to do element alredy set
453 * Sets a Scilab InfoBar to a Scilab window
454 * @param newInfoBar the Scilab InfoBar to set to the Scilab window
455 * @see org.scilab.modules.gui.window.Window#setInfoBar(org.scilab.modules.gui.textbox.TextBox)
457 public void addInfoBar(TextBox newInfoBar) {
458 if (newInfoBar == null) {
459 if (this.infoBar != null) {
460 // Remove old InfoBar if already set
461 super.remove((SwingScilabTextBox) this.infoBar);
465 // else nothing to do both are null
467 if (this.infoBar != newInfoBar.getAsSimpleTextBox()) {
468 if (this.infoBar != null) {
469 // Remove old InfoBar if already set
470 super.remove((SwingScilabTextBox) this.infoBar);
472 this.infoBar = newInfoBar.getAsSimpleTextBox();
473 super.add((SwingScilabTextBox) this.infoBar, java.awt.BorderLayout.PAGE_END);
476 // else nothing to do element alredy set
481 * Get the element id for this window
482 * @return id the id of the corresponding window object
484 public int getElementId() {
489 * Set the element id for this window
490 * @param id the id of the corresponding window object
492 public void setElementId(int id) {
494 sciDockingListener.setAssociatedWindowId(id);
499 * @see org.scilab.modules.gui.window.SimpleWindow#close()
501 public void close() {
506 * @return number of objects (tabs) docked in this window
508 public int getNbDockedObjects() {
509 return sciDockingPort.getDockables().size();
513 * Update the dimension of the window and its component.
514 * Only useful when the window is not yet visible
516 public void updateDimensions() {
523 public void windowDeiconified() {
524 super.setState(Frame.NORMAL);
530 public void windowIconified() {
531 super.setState(Frame.ICONIFIED);
537 public void windowMaximized() {
538 super.setExtendedState(Frame.MAXIMIZED_BOTH);
542 * Window is in the "normal" state.
544 public void windowNormal() {
545 super.setState(Frame.NORMAL);