7bbf96c642595703cb5da61a77a44a2ff29698ce
[scilab.git] / scilab / modules / core / src / java / org / scilab / modules / core / Scilab.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2007-2008 - INRIA - Allan CORNET
4  * Copyright (C) 2007-2008 - INRIA - Vincent COUVERT
5  * Copyright (C) 2007-2008 - INRIA - Sylvestre LEDRU
6  * Copyright (C) 2007-2008 - INRIA - Jean-Baptiste SILVY
7  * Copyright (C) 2007-2008 - INRIA - Bruno JOFRET
8  * Copyright (C) 2011 - Calixte DENIZET
9  *
10  * Copyright (C) 2012 - 2016 - Scilab Enterprises
11  *
12  * This file is hereby licensed under the terms of the GNU GPL v2.0,
13  * pursuant to article 5.3.4 of the CeCILL v.2.1.
14  * This file was originally licensed under the terms of the CeCILL v2.1,
15  * and continues to be available under such terms.
16  * For more information, see the COPYING file which you should have received
17  * along with this program.
18  *
19  */
20
21 package org.scilab.modules.core;
22
23 import java.awt.GraphicsEnvironment;
24 import java.awt.Toolkit;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 import javax.swing.JPopupMenu;
29 import javax.swing.SwingUtilities;
30
31 import org.flexdock.docking.DockingConstants;
32 import org.flexdock.docking.DockingManager;
33 import org.scilab.modules.commons.OS;
34 import org.scilab.modules.commons.ScilabCommonsUtils;
35 import org.scilab.modules.commons.ScilabConstants;
36 import org.scilab.modules.commons.xml.XConfiguration;
37 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
38 import org.scilab.modules.graphic_objects.graphicObject.GraphicObject.Type;
39 import org.scilab.modules.graphic_objects.utils.MenuBarBuilder;
40 import org.scilab.modules.gui.SwingView;
41 import org.scilab.modules.gui.bridge.console.SwingScilabConsole;
42 import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel;
43 import org.scilab.modules.gui.bridge.window.SwingScilabWindow;
44 import org.scilab.modules.gui.console.ScilabConsole;
45 import org.scilab.modules.gui.tabfactory.ScilabTabFactory;
46 import org.scilab.modules.gui.utils.ClosingOperationsManager;
47 import org.scilab.modules.gui.utils.ConfigManager;
48 import org.scilab.modules.gui.utils.LookAndFeelManager;
49 import org.scilab.modules.gui.utils.WindowsConfigurationManager;
50
51 /**
52  * Main Class for Scilab
53  * @author Allan CORNET
54  * @author Jean-Baptiste SILVY
55  * @author Vincent COUVERT
56  * @author Sylvestre Ledru
57  * @author Bruno JOFRET
58  * @author Calixte DENIZET
59  */
60 public class Scilab {
61
62     static {
63         System.setProperty("java.protocol.handler.pkgs", "org.scilab.modules.commons");
64         XConfiguration.getXConfigurationDocument();
65     }
66
67     /** Index of windows vista version */
68     private static final double VISTA_VERSION = 6.0;
69
70     private static final String ENABLE_JAVA2D_OPENGL_PIPELINE = "sun.java2d.opengl";
71     private static final String ENABLE = "true";
72     private static final String DISABLE = "false";
73     private static final String DISABLE_DDRAW = "sun.java2d.noddraw";
74     private static final String OSNAME = "os.name";
75     private static final String MACOS = "mac";
76
77     private static boolean success;
78     private static boolean finish;
79     private static boolean exitCalled;
80     private static int mode;
81
82     private static List<Runnable> finalhooks = new ArrayList<Runnable>();
83     private static List<Runnable> initialhooks = new ArrayList<Runnable>();
84
85     /**
86      * WARNING : mainView is directly referenced from a JNI even it's private.
87      * TODO : Better add getter for this variable.
88      */
89     private SwingScilabWindow mainView;
90
91     /**
92      * Constructor Scilab Class.
93      * @param mode Mode Scilab -NW -NWNI -STD -API
94      */
95     public Scilab(int mode) {
96         Scilab.mode = mode;
97         ScilabConstants.setMode(mode);
98
99         DockingManager.setDockableFactory(ScilabTabFactory.getInstance());
100
101         /*
102          * Set Scilab directory. Note that it is done in the constructor
103          * and not as directly when setting the member because we had some
104          * race condition. See bug #4419
105          */
106         try {
107             /*
108              * Set Java directories to Scilab ones
109              */
110             if (mode != 1) {
111                 /* only modify these properties if Scilab is not called by another application */
112                 /* In this case, we let the calling application to use its own properties */
113                 System.setProperty("java.io.tmpdir", ScilabConstants.TMPDIR.getCanonicalPath());
114                 System.setProperty("user.home", ScilabConstants.SCIHOME.getCanonicalPath());
115             }
116
117         } catch (Exception e) {
118             System.err.println("Cannot retrieve the variable SCI. Please report on http://bugzilla.scilab.org/");
119             System.err.println(e.getLocalizedMessage());
120             System.exit(-1);
121         }
122
123         /*
124          * Set options for JOGL
125          * they must be set before creating GUI
126          */
127         setJOGLFlags();
128         SwingView.registerSwingView();
129
130         /*
131          * if not API mode
132          * bug 3673 by default in API mode we dont modify look n feel
133          * If SCI_JAVA_ENABLE_HEADLESS is set, do not set the look and feel.
134          * (needed when building the documentation under *ux)
135          */
136         if (mode != 1 && System.getenv("SCI_JAVA_ENABLE_HEADLESS") == null) {
137             /* http://java.sun.com/docs/books/tutorial/uiswing/lookandfeel/plaf.html */
138             try {
139
140                 String scilabLookAndFeel = "javax.swing.plaf.metal.MetalLookAndFeel";
141
142                 if (OS.get() == OS.WINDOWS) {
143                     scilabLookAndFeel = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
144                 } else if (System.getProperty(OSNAME).toLowerCase().indexOf(MACOS) != -1) {
145                     /** OPTION ADDED TO ALLOW DOCKING UNDER MACOSX */
146                     System.setProperty(DockingConstants.HEAVYWEIGHT_DOCKABLES, ENABLE);
147                     scilabLookAndFeel = "apple.laf.AquaLookAndFeel";
148                 } else {
149                     scilabLookAndFeel = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
150
151                     /*
152                      * Linux specific desktop integration
153                      */
154                     if (!GraphicsEnvironment.isHeadless()) {
155                         try {
156                             Toolkit xToolkit = Toolkit.getDefaultToolkit();
157                             java.lang.reflect.Field awtAppClassNameField =
158                                 xToolkit.getClass().getDeclaredField("awtAppClassName");
159                             awtAppClassNameField.setAccessible(true);
160
161                             awtAppClassNameField.set(xToolkit, "Scilab");
162                         } catch (Exception e) {
163                             System.err.println("Unable to set WM_CLASS, please report a bug on http://bugzilla.scilab.org/.");
164                             System.err.println("Error: " + e.getLocalizedMessage());
165                         }
166                     }
167                 }
168
169                 /* Init the LookAndFeelManager all the time since we can
170                  * create windows in the NW mode */
171                 if (!GraphicsEnvironment.isHeadless()) {
172                     LookAndFeelManager lookAndFeel = new LookAndFeelManager();
173
174                     if (lookAndFeel.isSupportedLookAndFeel(scilabLookAndFeel)) {
175                         lookAndFeel.setLookAndFeel(scilabLookAndFeel);
176                     } else {
177                         lookAndFeel.setSystemLookAndFeel();
178                     }
179                 }
180             } catch (java.lang.NoClassDefFoundError exception) {
181                 System.err.println("Could not initialize graphics Environment");
182                 System.err.println("Scilab Graphical option may not be working correctly.");
183                 System.err.println("An error occurred: " + exception.getLocalizedMessage());
184             }
185         }
186
187         if (mode == 2) { /* Mode GUI */
188             // Create a user config file if not already exists
189             ConfigManager.createUserCopy();
190
191             Integer consoleId = GraphicController.getController().askObject(Type.JAVACONSOLE);
192             MenuBarBuilder.buildConsoleMenuBar(consoleId);
193
194             SwingScilabConsole sciConsole = ((SwingScilabConsole) ScilabConsole.getConsole().getAsSimpleConsole());
195             SwingScilabDockablePanel consoleTab = (SwingScilabDockablePanel) sciConsole.getParent();
196
197             WindowsConfigurationManager.restorationFinished(consoleTab);
198
199             mainView = SwingScilabWindow.allScilabWindows.get(consoleTab.getParentWindowId());
200         } else {
201             GraphicController.getController().askObject(Type.CONSOLE);
202         }
203     }
204
205     /**
206      * @return the current mode
207      */
208     public static int getMode() {
209         return mode;
210     }
211
212     /**
213      * Sets the prompt displayed in Scilab console
214      * @param prompt the prompt to be displayed as a String
215      */
216     public void setPrompt(String prompt) {
217         ScilabConsole.getConsole().setPrompt(prompt);
218     }
219
220     /**
221      * Set the command line flags to the JVM
222      */
223     public static void setJOGLFlags() {
224
225         // Must give popUpMenu heavy weight
226         // in case we enable GLCanvas
227         JPopupMenu.setDefaultLightWeightPopupEnabled(false);
228         // Uneash OpenGL power
229         // Not yet
230         //System.setProperty(ENABLE_JAVA2D_OPENGL_PIPELINE, ENABLE_WITH_DEBUG);
231         System.setProperty(ENABLE_JAVA2D_OPENGL_PIPELINE, DISABLE);
232
233         if (OS.get() == OS.WINDOWS) {
234             if ((Double) OS.get().getVersion() >= VISTA_VERSION) {
235                 // don't enable OpenGL because of aero
236                 System.setProperty(ENABLE_JAVA2D_OPENGL_PIPELINE, DISABLE);
237             }
238             // desactivate direct3d and direct draw under windows
239             System.setProperty(DISABLE_DDRAW, ENABLE);
240         }
241     }
242
243     /**
244      * Call from canCloseMainScilabObject (call itself from sci_exit)
245      * @return true if the console is closed
246      */
247     public static boolean canClose() {
248         final Object lock = new Object();
249
250         SwingUtilities.invokeLater(new Runnable() {
251             @Override
252             public void run() {
253                 exitCalled = true;
254                 success = ClosingOperationsManager.startClosingOperationOnRoot();
255                 exitCalled = false;
256
257                 finish = true;
258                 synchronized (lock) {
259                     lock.notify();
260                 }
261             }
262         });
263
264         try {
265             synchronized (lock) {
266                 while (!finish) {
267                     lock.wait();
268                 }
269             }
270         } catch (InterruptedException e) {
271             System.err.println(e);
272         }
273         finish = false;
274
275         return success;
276     }
277
278     /**
279      * Call from forceCloseMainScilabObject (call itself from sci_exit)
280      */
281     public static void forceClose() {
282         final Object lock = new Object();
283
284         SwingUtilities.invokeLater(new Runnable() {
285             @Override
286             public void run() {
287                 exitCalled = true;
288                 ClosingOperationsManager.forceClosingOperationOnRoot();
289                 exitCalled = false;
290
291                 finish = true;
292                 synchronized (lock) {
293                     lock.notify();
294                 }
295             }
296         });
297
298         try {
299             synchronized (lock) {
300                 while (!finish) {
301                     lock.wait();
302                 }
303             }
304         } catch (InterruptedException e) {
305             System.err.println(e);
306         }
307         finish = false;
308     }
309
310     /**
311      * @return true if exit has been called from command line
312      */
313     public static boolean getExitCalled() {
314         return exitCalled;
315     }
316
317     /**
318      * Register a hook to execute just before the JVM shutdown.
319      * A hook should not contain threads, there is no warranty that they will be fully executed.
320      */
321     public static void registerFinalHook(Runnable hook) {
322         finalhooks.add(hook);
323     }
324
325     /**
326      * Remove a hook
327      */
328     public static void removeFinalHook(Runnable hook) {
329         finalhooks.remove(hook);
330     }
331
332     /**
333      * This method should be called from jni (finishMainScilabObject())
334      */
335     public static void executeFinalHooks() {
336         for (Runnable hook : finalhooks) {
337             hook.run();
338         }
339     }
340
341     /**
342      * Register a hook to execute after the Scilab initialization.
343      * A hook should not contain threads, there is no warranty that they will be fully executed.
344      */
345     public static void registerInitialHook(Runnable hook) {
346         initialhooks.add(hook);
347     }
348
349     /**
350      * Remove a hook
351      */
352     public static void removeInitialHook(Runnable hook) {
353         initialhooks.remove(hook);
354     }
355
356     /**
357      * This method should be called from C (realmain)
358      */
359     public static void executeInitialHooks() {
360         ScilabCommonsUtils.registerScilabThread();
361
362         for (final Runnable hook : initialhooks) {
363             hook.run();
364         }
365     }
366 }
367 /*--------------------------------------------------------------------------*/