Prefs: add a function preferences()
[scilab.git] / scilab / modules / preferences / src / java / org / scilab / modules / preferences / XConfigManager.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2011 - INRIA - Vincent COUVERT
4  * Copyright (C) 2011 -         Pierre GRADIT
5  * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET
6  *
7  * This file must be used under the terms of the CeCILL.
8  * This source file is licensed as described in the file COPYING, which
9  * you should have received as part of this distribution.  The terms
10  * are also available at
11  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
12  *
13  */
14
15 package org.scilab.modules.preferences;
16
17 import java.awt.Color;
18 import java.awt.Component;
19 import java.awt.BorderLayout;
20 import java.awt.Dimension;
21 import java.awt.Font;
22 import java.awt.Frame;
23 import java.awt.Toolkit;
24 import java.awt.event.ComponentAdapter;
25 import java.awt.event.ComponentEvent;
26 import java.awt.event.ComponentListener;
27 import java.awt.event.WindowAdapter;
28 import java.awt.event.WindowEvent;
29 import java.io.File;
30 import java.io.IOException;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34
35 import javax.swing.JDialog;
36
37 import org.w3c.dom.Document;
38 import org.w3c.dom.DocumentFragment;
39 import org.w3c.dom.Element;
40 import org.w3c.dom.Node;
41 import org.w3c.dom.NodeList;
42
43 import org.scilab.modules.commons.ScilabCommons;
44 import org.scilab.modules.commons.ScilabCommonsUtils;
45 import org.scilab.modules.commons.xml.XConfiguration;
46 import org.scilab.modules.gui.utils.Position;
47 import org.scilab.modules.gui.utils.Size;
48 import org.scilab.modules.gui.utils.ScilabSwingUtilities;
49 import org.scilab.modules.preferences.ScilabPreferences.ToolboxInfos;
50
51 /**
52  * Extended management of the Console configuration file.
53  *
54  * @author Pierre GRADIT
55  * @author Vincent COUVERT
56  */
57 public final class XConfigManager extends XCommonManager {
58
59     /** Exclusive activity flag between all XCommonManager descendants.*/
60     public static boolean active = false;
61
62     /** Scilab configuration file.*/
63     private static final String SCILAB_CONFIG_FILE = System.getenv("SCI") + "/modules/preferences/etc/XConfiguration.xml";
64
65     /** Scilab configuration stylesheet.*/
66     private static final String SCILAB_CONFIG_XSL = System.getenv("SCI") + "/modules/preferences/src/xslt/XConfiguration.xsl";
67
68     /** User configuration file.*/
69     private static final String USER_CONFIG_FILE = ScilabCommons.getSCIHOME() + "/XConfiguration.xml";
70
71     static {
72         //ScilabPreferences.addToolboxInfos("MyToolbox", System.getenv("SCI") + "/contrib/toolbox_skeleton/", System.getenv("SCI") + "/contrib/toolbox_skeleton/etc/toolbox_skeleton_preferences.xml");
73     }
74
75     /**
76      * Constructor blocked, singleton pattern.
77      */
78     private XConfigManager() {
79         throw new UnsupportedOperationException();
80     }
81
82     /** Display dialog and wait for events.
83      *
84      */
85     public static void displayAndWait() {
86         XConfigManager.active = true;
87         XWizardManager.active = false;
88
89         reloadTransformer(SCILAB_CONFIG_XSL);
90         Frame topWindow = XCommonManager.getTopLevel();
91
92         // Set up Swing Side
93         dialog = new JDialog(topWindow, "Scilab Preferences", true);
94         topSwing = dialog.getContentPane();
95         topSwing.setLayout(new BorderLayout());
96         // AWT implies to set layout at construction time.
97
98         // Set up DOM Side
99         readUserDocuments();
100         updated = false;
101
102         // Plug in resize
103         //dialog.setResizable(false);
104         dialog.addComponentListener(new ComponentAdapter() {
105             public void componentResized(ComponentEvent e) {
106                 Element element = document.getDocumentElement();
107                 Dimension dimension = dialog.getSize();
108                 int height = XConfigManager.getInt(element, "height", 0);
109                 int width = XConfigManager.getInt(element, "width",  0);
110                 if (Math.abs(((double) height) - dimension.getHeight()) > 0.1 && Math.abs(((double) width) - dimension.getWidth()) > 0.1 ) {
111                     element.setAttribute("height", Integer.toString((int) dimension.getHeight()));
112                     element.setAttribute("width", Integer.toString((int) dimension.getWidth()));
113                 }
114             }
115         });
116
117         dialog.addWindowListener(new WindowAdapter() {
118             @Override
119             public void windowClosing(WindowEvent e) {
120                 cancel();
121             }
122         });
123         ScilabSwingUtilities.closeOnEscape(dialog);
124
125         // Set up correspondence
126         correspondance = new HashMap<Component, XSentinel>();
127
128         // Let the show begin!
129         if (refreshDisplay()) {
130             // Center the dialog on the parent window
131             if (topWindow != null) {
132                 int x = topWindow.getX() + (topWindow.getWidth() - dialog.getWidth()) / 2;
133                 int y = topWindow.getY() + (topWindow.getHeight() - dialog.getHeight()) / 2;
134                 dialog.setLocation(x, y);
135             }
136
137             dialog.setVisible(true);
138         }
139     }
140
141     /**
142      * Opens a dialog to setup preferences.
143      */
144     public static void openPreferences() {
145         XConfigManager.displayAndWait();
146     }
147
148     /** Secondary dialog for help.*/
149     private static JDialog help = null;
150
151     /** Read files to modify (and possibly create it).
152      */
153     private static void readUserDocuments() {
154         /*
155          * The default document just contains an empty tag <toolboxes/>
156          * We add a body and the different toolbox entries to have something like
157          * <toolboxes>
158          *   <body/>
159          *   <mytoolbox1><body>...</body></mytoolbox1>
160          *   <mytoolbox2><body>...</body></mytoolbox2>
161          * </toolboxes>
162          */
163
164         document = XConfiguration.getXConfigurationDocument();
165
166         // We remove all the previous tags (should be empty but an error could have occured...)
167         NodeList toolboxes = document.getElementsByTagName("toolboxes");
168         for (int i = 0; i < toolboxes.getLength(); i++) {
169             try {
170                 document.getDocumentElement().removeChild(toolboxes.item(i));
171             } catch (Exception e) {
172                 // Maybe root is not the good parent...
173             }
174         }
175
176         Element tbxs = document.createElement("toolboxes");
177         document.getDocumentElement().appendChild(tbxs);
178
179         // Body (rendered as XConfiguration.xsl example)
180         Element body = document.createElement("body");
181         tbxs.appendChild(body);
182
183         List<ToolboxInfos> infos = ScilabPreferences.getToolboxesInfos();
184         for (ToolboxInfos info: infos) {
185             String filename = new File(info.getPrefFile()).getName();
186             String tbxTag = info.getName().replace(' ', '_');
187             String tbxFile = ScilabCommons.getSCIHOME() + "/" + filename;
188
189             // the copy is made only if needed
190             createUserCopy(info.getPrefFile(), tbxFile);
191
192             // Building document fragment
193             Element token = document.createElement(tbxTag);
194             token.setAttribute("title", info.getName());
195             DocumentFragment fragment = document.createDocumentFragment();
196             Document tbxDocument = readDocument(tbxFile);
197             Node transferred = tbxDocument.getDocumentElement();
198
199             transferred = document.importNode(transferred, true);
200             fragment.appendChild(transferred);
201             token.insertBefore(fragment, null);
202             tbxs.appendChild(token);
203         }
204     }
205
206     private static void WriteUserDocuments() {
207         // Toolboxes files
208         NodeList toolboxes = document.getElementsByTagName("toolboxes");
209         Element tbxs = null;
210         Element emptyTbxs;
211         if (toolboxes != null && toolboxes.getLength() != 0) {
212             tbxs = (Element) toolboxes.item(0);
213             List<ToolboxInfos> infos = ScilabPreferences.getToolboxesInfos();
214             for (ToolboxInfos info: infos) {
215                 String tbxTag = info.getName().replace(' ', '_');
216                 NodeList list = tbxs.getElementsByTagName(tbxTag);
217                 if (list != null && list.getLength() != 0) {
218                     Element mytbx = (Element) list.item(0);
219                     if (mytbx.hasChildNodes()) {
220                         String filename = new File(info.getPrefFile()).getName();
221                         String tbxFile = ScilabCommons.getSCIHOME() + "/" + filename;
222                         XConfiguration.writeDocument(tbxFile, mytbx.getFirstChild());
223                     }
224                 }
225             }
226         }
227
228         if (tbxs != null) {
229             document.getDocumentElement().removeChild(tbxs);
230         }
231
232         XConfiguration.writeDocument(USER_CONFIG_FILE, document);
233
234         if (tbxs != null) {
235             document.getDocumentElement().appendChild(tbxs);
236         }
237     }
238
239     private static void cancel() {
240         dialog.dispose();
241         XCommonManager.invalidateXSL();
242         XConfiguration.invalidate();
243         NodeList toolboxes = document.getElementsByTagName("toolboxes");
244         if (toolboxes != null && toolboxes.getLength() != 0) {
245             Element tbxs = (Element) toolboxes.item(0);
246             document.getDocumentElement().removeChild(tbxs);
247         }
248         updated = false;
249         refreshDisplay();
250     }
251
252     /** Interpret action.
253      *
254      * @param action : to be interpreted.
255      * @param source : component source of the action (only class is needed).
256      * @return whether event was treated or not.
257      */
258     public static boolean xEvent(final Node[] actions, final Component source) {
259         if (generixEvent(actions, source)) {
260             return true;
261         }
262
263         if (actions.length == 0) {
264             return false;
265         }
266
267         Node action = actions[0];
268         String callback = getAttribute(action, "callback");
269         /** help deprecated
270             if (callback.equals("Help")) {
271             // TODO it can be a contextual help.
272             //System.err.println("Help not implemented yet!");
273             if (differential) {
274             System.out.println(": Help.");
275             }
276             return true;
277             }
278         **/
279         if (callback.equals("Save Backup")) {
280             String path = getAttribute(action, "path");
281             writeDocument(ScilabCommonsUtils.getCorrectedPath(path), document);
282
283             return true;
284         }
285
286         if (callback.equals("Restore Backup")) {
287             String path = getAttribute(action, "path");
288             try {
289                 copyFile(new File(ScilabCommonsUtils.getCorrectedPath(path)), new File(USER_CONFIG_FILE));
290             } catch (IOException e) {
291                 System.err.println(e);
292             }
293
294             XConfiguration.invalidate();
295             XConfiguration.addModifiedPath("ALL");
296             reloadTransformer(SCILAB_CONFIG_XSL);
297             document = XConfiguration.createDocument();
298
299             List<ToolboxInfos> infos = ScilabPreferences.getToolboxesInfos();
300             for (ToolboxInfos info : infos) {
301                 String filename = new File(info.getPrefFile()).getName();
302                 String tbxFile = ScilabCommons.getSCIHOME() + "/" + filename;
303                 refreshUserCopy(info.getPrefFile(), tbxFile);
304             }
305             readUserDocuments();
306             updated = false;
307             refreshDisplay();
308
309             return true;
310         }
311
312         if (callback.equals("Ok")) {
313             WriteUserDocuments();
314             dialog.dispose();
315             XCommonManager.invalidateXSL();
316             updated = false;
317             XConfiguration.fireXConfigurationEvent();
318             XConfiguration.invalidate();
319             return true;
320         }
321         if (callback.equals("Apply")) {
322             updated = false;
323             WriteUserDocuments();
324             XConfiguration.fireXConfigurationEvent();
325             return true;
326         }
327         if (callback.equals("Default")) {
328             XConfiguration.invalidate();
329             XConfiguration.addModifiedPath("ALL");
330             reloadTransformer(SCILAB_CONFIG_XSL);
331             document = XConfiguration.createDocument();
332             writeDocument(USER_CONFIG_FILE, document);
333             List<ToolboxInfos> infos = ScilabPreferences.getToolboxesInfos();
334             for (ToolboxInfos info : infos) {
335                 String filename = new File(info.getPrefFile()).getName();
336                 String tbxFile = ScilabCommons.getSCIHOME() + "/" + filename;
337                 refreshUserCopy(info.getPrefFile(), tbxFile);
338             }
339             readUserDocuments();
340             updated = false;
341             refreshDisplay();
342
343             return true;
344         }
345         if (callback.equals("Cancel")) {
346             cancel();
347             return true;
348         }
349         return false;
350     }
351 }