Prefs: add a way to backup preferences file
[scilab.git] / scilab / modules / preferences / src / java / org / scilab / modules / preferences / Component / FileSelector.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2011 - Pierre GRADIT
4  * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13
14 package org.scilab.modules.preferences.Component;
15
16 import java.awt.BorderLayout;
17 import java.awt.Color;
18 import java.awt.Dimension;
19 import java.awt.GridBagConstraints;
20 import java.awt.GridBagLayout;
21
22 import java.awt.event.ActionEvent;
23 import java.awt.event.ActionListener;
24 import java.io.File;
25
26 import javax.swing.GroupLayout;
27 import javax.swing.JButton;
28 import javax.swing.JFrame;
29 import javax.swing.JPanel;
30 import javax.swing.JTextField;
31 import javax.swing.SwingUtilities;
32 import javax.swing.event.DocumentEvent;
33 import javax.swing.event.DocumentListener;
34
35 import org.scilab.modules.commons.ScilabCommonsUtils;
36 import org.scilab.modules.preferences.XCommonManager;
37 import org.scilab.modules.preferences.XComponent;
38 import org.scilab.modules.preferences.XChooser;
39 import org.scilab.modules.preferences.XConfigManager;
40 import org.scilab.modules.gui.bridge.filechooser.SwingScilabFileChooser;
41
42 import org.w3c.dom.Node;
43
44 /** Implementation of Entry compliant with extended management.
45  *
46  * @author Calixte DENIZET
47  *
48  */
49 public class FileSelector extends Panel implements XComponent, XChooser, DocumentListener {
50
51     /** Universal identifier for serialization.
52      *
53      */
54     private static final long serialVersionUID = -7007541669965737408L;
55
56     private static final Color NORMALCOLOR = Color.BLACK;
57     private static final Color ERRORCOLOR = Color.RED;
58
59     private ActionListener actionListener;
60     private JTextField textField;
61     private JButton button;
62     private String currentDir = System.getProperty("user.home");
63     private boolean dirSelection;
64     private boolean checkEntry;
65     private String previousPath;
66
67     /** Constructor.
68      *
69      * @param peer : associated view DOM node.
70      */
71     public FileSelector(final Node peer) {
72         super(peer);
73         setLayout(new GridBagLayout());
74
75         textField = new JTextField();
76         textField.setEditable(true);
77         textField.setColumns(10);
78         textField.getDocument().addDocumentListener(this);
79
80         button = new JButton("...");
81         button.setPreferredSize(new Dimension(button.getPreferredSize().width, textField.getPreferredSize().height));
82         button.addActionListener(new ActionListener() {
83             public void actionPerformed(ActionEvent e) {
84                 JFrame frame = (JFrame) SwingUtilities.getAncestorOfClass(JFrame.class, FileSelector.this);
85                 SwingScilabFileChooser fileChooser = new SwingScilabFileChooser();
86                 fileChooser.setInitialDirectory(currentDir);
87                 fileChooser.setParentFrame(frame);
88                 fileChooser.setMultipleSelection(false);
89                 fileChooser.setFileSelectionMode(dirSelection ? SwingScilabFileChooser.DIRECTORIES_ONLY : SwingScilabFileChooser.FILES_ONLY);
90                 String mask = XCommonManager.getAttribute(peer, "mask");
91                 String desc = XCommonManager.getAttribute(peer, "desc");
92                 if (!mask.equals(XCommonManager.NAV) && !desc.equals(XCommonManager.NAV)) {
93                     fileChooser.addMask(new String[] {mask}, new String[] {desc});
94                 }
95                 fileChooser.displayAndWait();
96
97                 String[] paths = fileChooser.getSelection();
98                 if (paths != null && paths.length != 0 && !paths[0].isEmpty()) {
99                     File file = new File(paths[0]);
100                     if (dirSelection) {
101                         currentDir = file.getAbsolutePath();
102                     } else {
103                         currentDir = file.getParentFile().getAbsolutePath();
104                     }
105
106                     textField.setText(file.getAbsolutePath());
107                 }
108             }
109         });
110
111         GridBagConstraints gbc = new GridBagConstraints();
112         gbc.gridx = 0;
113         gbc.gridy = 0;
114         gbc.weightx = 1;
115         gbc.fill = GridBagConstraints.HORIZONTAL;
116         add(textField, gbc);
117         gbc.gridx = 1;
118         gbc.weightx = 0;
119         add(button, gbc);
120
121         textField.setRequestFocusEnabled(true);
122         textField.setFocusable(true);
123         button.setRequestFocusEnabled(true);
124         button.setFocusable(true);
125
126         String href = XConfigManager.getAttribute(peer, "href");
127         href(href);
128
129         String dirsel = XCommonManager.getAttribute(peer, "dir-selection", "false");
130         dirSelection = dirsel.equals("true");
131
132         String checkentry = XConfigManager.getAttribute(peer, "check-entry", "true");
133         checkEntry = checkentry.equals("true");
134     }
135
136     public void addDocumentListener(DocumentListener listener) {
137         textField.getDocument().addDocumentListener(listener);
138     }
139
140     /** Define the set of actuators.
141      *
142      * @return array of actuator names.
143      */
144     public final String[] actuators() {
145         String[] actuators = {"enable", "href", "desc", "mask", "dir-selection", "check-entry"};
146         return actuators;
147     }
148
149     /** Refresh the component by the use of actuators.
150      *
151      * @param peer the corresponding view DOM node
152      */
153     public final void refresh(final Node peer) {
154         String href = XCommonManager.getAttribute(peer, "href");
155         if (!href.equals(href())) {
156             href(href);
157         }
158
159         String dirsel = XCommonManager.getAttribute(peer, "dir-selection", "false");
160         dirSelection = dirsel.equals("true");
161
162         String enable = XConfigManager.getAttribute(peer, "enable", "true");
163         textField.setEnabled(enable.equals("true"));
164         button.setEnabled(enable.equals("true"));
165
166         String checkentry = XConfigManager.getAttribute(peer, "check-entry", "true");
167         checkEntry = checkentry.equals("true");
168     }
169
170     /** Sensor for 'href' attribute.
171      *
172      * @return the attribute value.
173      */
174     public final String href() {
175         if (checkPath()) {
176             return textField.getText();
177         }
178
179         return null;
180     }
181
182     /** Actuator for 'href' attribute.
183      *
184      * @param text : the attribute value.
185      */
186     public final void href(final String href) {
187         if (!href.equals(XCommonManager.NAV)) {
188             textField.setText(href);
189         }
190     }
191
192     /**
193      * {@inheritDoc}
194      */
195     public void changedUpdate(DocumentEvent e) { }
196
197     /**
198      * {@inheritDoc}
199      */
200     public void insertUpdate(DocumentEvent e) {
201         update();
202     }
203
204     /**
205      * {@inheritDoc}
206      */
207     public void removeUpdate(DocumentEvent e) {
208         update();
209     }
210
211     private void update() {
212         if (checkPath() && actionListener != null) {
213             ActionEvent transmit = new ActionEvent(this, 0, "File change", System.currentTimeMillis(), 0);
214             actionListener.actionPerformed(transmit);
215         }
216     }
217
218     private boolean checkPath() {
219         String path = textField.getText();
220         if (path.isEmpty()) {
221             return false;
222         }
223
224         path = ScilabCommonsUtils.getCorrectedPath(path);
225
226         File file = new File(path);
227         boolean ok = false;
228         if (file.exists()) {
229             if (dirSelection) {
230                 ok = file.isDirectory();
231             } else {
232                 ok = file.isFile();
233             }
234         }
235
236         if (!checkEntry || ok) {
237             textField.setForeground(NORMALCOLOR);
238         } else {
239             textField.setForeground(ERRORCOLOR);
240         }
241
242         return checkEntry ? ok : true;
243     }
244
245     /** Actual response read by the listener.
246      *
247      * @return response read by the listener.
248      */
249     public final Object choose() {
250         return href();
251     }
252
253     /** Developer serialization method.
254      *
255      * @return equivalent signature.
256      */
257     public final String toString() {
258         String signature = "FileSelector";
259         String href = href();
260         if (href != null && !href.equals(XCommonManager.NAV)) {
261             signature += " href='" + href + "'";
262         }
263
264         return signature;
265     }
266
267     /** Registration of a single listener.
268      * @param listener for the unique actionListener.
269      */
270     public final void addActionListener(final ActionListener listener) {
271         actionListener = listener;
272     }
273
274 }
275