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