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