a4536164c8931b1a7af5a697dfd538a415d374cc
[scilab.git] / scilab / modules / ui_data / src / java / org / scilab / modules / ui_data / filebrowser / ScilabFileSelectorFilter.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2011 - DIGITEO - Calixte DENIZET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  *
11  */
12
13 package org.scilab.modules.ui_data.filebrowser;
14
15 import java.awt.Color;
16 import java.awt.ContainerOrderFocusTraversalPolicy;
17 import java.awt.GridBagConstraints;
18 import java.awt.GridBagLayout;
19 import java.awt.event.ActionEvent;
20 import java.awt.event.ActionListener;
21 import java.awt.event.FocusEvent;
22 import java.awt.event.FocusListener;
23 import java.awt.event.KeyEvent;
24 import java.util.regex.Pattern;
25
26 import javax.swing.Icon;
27 import javax.swing.ImageIcon;
28 import javax.swing.JButton;
29 import javax.swing.JCheckBox;
30 import javax.swing.JMenuItem;
31 import javax.swing.JPanel;
32 import javax.swing.JPopupMenu;
33 import javax.swing.JTextField;
34 import javax.swing.KeyStroke;
35 import javax.swing.border.EmptyBorder;
36 import javax.swing.event.DocumentEvent;
37 import javax.swing.event.DocumentListener;
38 import javax.swing.text.DefaultEditorKit;
39
40 import org.scilab.modules.commons.OS;
41 import org.scilab.modules.commons.gui.FindIconHelper;
42 import org.scilab.modules.gui.events.callback.CommonCallBack;
43 import org.scilab.modules.ui_data.utils.UiDataMessages;
44
45 /**
46  * A panel with file filter and the combo to set the cwd.
47  * @author Calixte DENIZET
48  */
49 @SuppressWarnings(value = { "serial" })
50 public class ScilabFileSelectorFilter extends JPanel {
51
52     private static boolean isWindows = (OS.get() == OS.WINDOWS);
53     private static final int GAP = 3;
54     private static final Icon VALIDATE = new ImageIcon(FindIconHelper.findIcon("filter"));
55
56     private MyJTextField textfield;
57     private final SwingScilabTreeTable stt;
58     private JCheckBox caseSensitive;
59     private JCheckBox regexp;
60     private JButton validate;
61
62     /**
63      * Default constructor
64      * @param stt the SwingScilabTree containing the cwd
65      * @param comboPath the combobox where to set the path
66     */
67     public ScilabFileSelectorFilter(SwingScilabTreeTable stt) {
68         super();
69         this.stt = stt;
70         initPanel();
71     }
72
73     /**
74      * Init the panel
75      */
76     private void initPanel() {
77         setBorder(new EmptyBorder(0, 0, GAP, 0));
78         setLayout(new GridBagLayout());
79         textfield = new MyJTextField();
80         setFocusCycleRoot(true);
81         setFocusTraversalPolicy(new ContainerOrderFocusTraversalPolicy());
82
83         validate = new JButton(new CommonCallBack(null) {
84             @Override
85             public void callBack() {
86                 stt.setFilter(getPattern());
87             }
88         });
89         validate.setIcon(VALIDATE);
90
91         caseSensitive = new JCheckBox(UiDataMessages.CASESENSITIVE, !isWindows);
92         regexp = new JCheckBox(UiDataMessages.REGEXP, false);
93
94         GridBagConstraints gbc = new GridBagConstraints();
95
96         gbc.gridx = 0;
97         gbc.gridy = 0;
98         gbc.gridwidth = 2;
99         gbc.gridheight = 1;
100         gbc.weightx = 1;
101         gbc.fill = GridBagConstraints.BOTH;
102         gbc.anchor = GridBagConstraints.LINE_START;
103         add(textfield, gbc);
104
105         gbc.gridx = 2;
106         gbc.gridwidth = gbc.gridheight = 1;
107         gbc.weightx = 0;
108         gbc.fill = GridBagConstraints.VERTICAL;
109         gbc.anchor = GridBagConstraints.LINE_START;
110         add(validate, gbc);
111
112         gbc.gridx = 0;
113         gbc.gridy = 1;
114         gbc.gridwidth = gbc.gridheight = 1;
115         gbc.weightx = 0;
116         gbc.fill = GridBagConstraints.NONE;
117         gbc.anchor = GridBagConstraints.LINE_START;
118         add(caseSensitive, gbc);
119
120         gbc.gridx = 1;
121         gbc.gridwidth = gbc.gridheight = 1;
122         gbc.weightx = 0;
123         gbc.fill = GridBagConstraints.NONE;
124         gbc.anchor = GridBagConstraints.LINE_START;
125         add(regexp, gbc);
126     }
127
128     /**
129      * Test the pattern and change the color of the text in textfield if the pattern is invalid
130      */
131     private void testPattern() {
132         if (regexp.isSelected()) {
133             if (getPattern() == null) {
134                 textfield.setForeground(Color.RED);
135             } else {
136                 textfield.setForeground(textfield.defaultFg);
137             }
138         }
139     }
140
141     /**
142      * Get the pattern according to the textfield content
143      * @return the pattern
144      */
145     private Pattern getPattern() {
146         String text = textfield.getText();
147         if (text != null && !text.isEmpty()) {
148             if (!regexp.isSelected()) {
149                 text = text.replaceAll("\\*", "\\\\E.*\\\\Q").replaceAll("\\?", "\\\\E.?\\\\Q");
150                 text = "\\Q" + text + "\\E";
151             }
152             if (!caseSensitive.isSelected()) {
153                 text = "(?i)" + text;
154             }
155
156             if (regexp.isSelected()) {
157                 text = "(?m)" + text;
158             }
159
160             try {
161                 return Pattern.compile(text);
162             } catch (Exception e) { }
163         }
164
165         return null;
166     }
167
168     /**
169      * Inner class to have the possibility to add a default text in the textfield but in this case the textfield is empty !
170      * It is a workaround for a GTK bug which avoids me to paint directly in the field.
171      */
172     private class MyJTextField extends JTextField implements DocumentListener, FocusListener {
173
174         boolean isEmpty = true;
175         Color defaultFg;
176
177         /**
178          * {@inheritDoc}
179          */
180         MyJTextField() {
181             super();
182             defaultFg = getForeground();
183             setEditable(true);
184             setComponentPopupMenu(createPopup());
185             addFocusListener(this);
186             getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "ENTER");
187             getActionMap().put("ENTER", new CommonCallBack(null) {
188                 @Override
189                 public void callBack() {
190                     stt.setFilter(getPattern());
191                 }
192             });
193             toggleContents();
194         }
195
196         /**
197          * Toggle the contents
198          */
199         private void toggleContents() {
200             if (isEmpty) {
201                 setForeground(Color.LIGHT_GRAY);
202                 setText(UiDataMessages.FILEFILTER);
203             }
204         }
205
206         /**
207          * {@inheritDoc}
208          */
209         @Override
210         public String getText() {
211             if (isEmpty) {
212                 return "";
213             }
214
215             return super.getText();
216         }
217
218         /**
219          * {@inheritDoc}
220          */
221         @Override
222         public void focusGained(FocusEvent e) {
223             getDocument().addDocumentListener(this);
224             if (isEmpty) {
225                 setForeground(defaultFg);
226                 setText("");
227             }
228         }
229
230         /**
231          * {@inheritDoc}
232          */
233         @Override
234         public void focusLost(FocusEvent e) {
235             getDocument().removeDocumentListener(this);
236             isEmpty = super.getText().isEmpty();
237             toggleContents();
238         }
239
240         /**
241          * {@inheritDoc}
242          */
243         @Override
244         public void insertUpdate(DocumentEvent e) {
245             isEmpty = super.getText().isEmpty();
246             testPattern();
247         }
248
249         /**
250          * {@inheritDoc}
251          */
252         @Override
253         public void removeUpdate(DocumentEvent e) {
254             isEmpty = super.getText().isEmpty();
255             testPattern();
256         }
257
258         /**
259          * {@inheritDoc}
260          */
261         @Override
262         public void changedUpdate(DocumentEvent e) { }
263
264         /**
265          * @return the popup menu used in this textfield
266          */
267         private JPopupMenu createPopup() {
268             JPopupMenu popup = new JPopupMenu();
269
270             JMenuItem item = new JMenuItem(UiDataMessages.CUT);
271             item.addActionListener(new DefaultEditorKit.CutAction());
272             popup.add(item);
273
274             item = new JMenuItem(UiDataMessages.COPY);
275             item.addActionListener(new DefaultEditorKit.CopyAction());
276             popup.add(item);
277
278             item = new JMenuItem(UiDataMessages.PASTE);
279             item.addActionListener(new DefaultEditorKit.PasteAction());
280             popup.add(item);
281
282             item = new JMenuItem(UiDataMessages.CLEAR);
283             item.addActionListener(new ActionListener() {
284                 @Override
285                 public void actionPerformed(ActionEvent e) {
286                     MyJTextField.this.setText("");
287                 }
288             });
289             popup.add(item);
290
291             return popup;
292         }
293     }
294 }