Bug 13316 fixed: There were missing tooltips on filebrowser buttons
[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         validate.setToolTipText(UiDataMessages.RUNFILTER);
91
92         caseSensitive = new JCheckBox(UiDataMessages.CASESENSITIVE, !isWindows);
93         regexp = new JCheckBox(UiDataMessages.REGEXP, false);
94
95         GridBagConstraints gbc = new GridBagConstraints();
96
97         gbc.gridx = 0;
98         gbc.gridy = 0;
99         gbc.gridwidth = 2;
100         gbc.gridheight = 1;
101         gbc.weightx = 1;
102         gbc.fill = GridBagConstraints.BOTH;
103         gbc.anchor = GridBagConstraints.LINE_START;
104         add(textfield, gbc);
105
106         gbc.gridx = 2;
107         gbc.gridwidth = gbc.gridheight = 1;
108         gbc.weightx = 0;
109         gbc.fill = GridBagConstraints.VERTICAL;
110         gbc.anchor = GridBagConstraints.LINE_START;
111         add(validate, gbc);
112
113         gbc.gridx = 0;
114         gbc.gridy = 1;
115         gbc.gridwidth = gbc.gridheight = 1;
116         gbc.weightx = 0;
117         gbc.fill = GridBagConstraints.NONE;
118         gbc.anchor = GridBagConstraints.LINE_START;
119         add(caseSensitive, gbc);
120
121         gbc.gridx = 1;
122         gbc.gridwidth = gbc.gridheight = 1;
123         gbc.weightx = 0;
124         gbc.fill = GridBagConstraints.NONE;
125         gbc.anchor = GridBagConstraints.LINE_START;
126         add(regexp, gbc);
127     }
128
129     /**
130      * Test the pattern and change the color of the text in textfield if the pattern is invalid
131      */
132     private void testPattern() {
133         if (regexp.isSelected()) {
134             if (getPattern() == null) {
135                 textfield.setForeground(Color.RED);
136             } else {
137                 textfield.setForeground(textfield.defaultFg);
138             }
139         }
140     }
141
142     /**
143      * Get the pattern according to the textfield content
144      * @return the pattern
145      */
146     private Pattern getPattern() {
147         String text = textfield.getText();
148         if (text != null && !text.isEmpty()) {
149             if (!regexp.isSelected()) {
150                 text = text.replaceAll("\\*", "\\\\E.*\\\\Q").replaceAll("\\?", "\\\\E.?\\\\Q");
151                 text = "\\Q" + text + "\\E";
152             }
153             if (!caseSensitive.isSelected()) {
154                 text = "(?i)" + text;
155             }
156
157             if (regexp.isSelected()) {
158                 text = "(?m)" + text;
159             }
160
161             try {
162                 return Pattern.compile(text);
163             } catch (Exception e) { }
164         }
165
166         return null;
167     }
168
169     /**
170      * Inner class to have the possibility to add a default text in the textfield but in this case the textfield is empty !
171      * It is a workaround for a GTK bug which avoids me to paint directly in the field.
172      */
173     private class MyJTextField extends JTextField implements DocumentListener, FocusListener {
174
175         boolean isEmpty = true;
176         Color defaultFg;
177
178         /**
179          * {@inheritDoc}
180          */
181         MyJTextField() {
182             super();
183             defaultFg = getForeground();
184             setEditable(true);
185             setComponentPopupMenu(createPopup());
186             addFocusListener(this);
187             getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "ENTER");
188             getActionMap().put("ENTER", new CommonCallBack(null) {
189                 @Override
190                 public void callBack() {
191                     stt.setFilter(getPattern());
192                 }
193             });
194             toggleContents();
195         }
196
197         /**
198          * Toggle the contents
199          */
200         private void toggleContents() {
201             if (isEmpty) {
202                 setForeground(Color.LIGHT_GRAY);
203                 setText(UiDataMessages.FILEFILTER);
204             }
205         }
206
207         /**
208          * {@inheritDoc}
209          */
210         @Override
211         public String getText() {
212             if (isEmpty) {
213                 return "";
214             }
215
216             return super.getText();
217         }
218
219         /**
220          * {@inheritDoc}
221          */
222         @Override
223         public void focusGained(FocusEvent e) {
224             getDocument().addDocumentListener(this);
225             if (isEmpty) {
226                 setForeground(defaultFg);
227                 setText("");
228             }
229         }
230
231         /**
232          * {@inheritDoc}
233          */
234         @Override
235         public void focusLost(FocusEvent e) {
236             getDocument().removeDocumentListener(this);
237             isEmpty = super.getText().isEmpty();
238             toggleContents();
239         }
240
241         /**
242          * {@inheritDoc}
243          */
244         @Override
245         public void insertUpdate(DocumentEvent e) {
246             isEmpty = super.getText().isEmpty();
247             testPattern();
248         }
249
250         /**
251          * {@inheritDoc}
252          */
253         @Override
254         public void removeUpdate(DocumentEvent e) {
255             isEmpty = super.getText().isEmpty();
256             testPattern();
257         }
258
259         /**
260          * {@inheritDoc}
261          */
262         @Override
263         public void changedUpdate(DocumentEvent e) { }
264
265         /**
266          * @return the popup menu used in this textfield
267          */
268         private JPopupMenu createPopup() {
269             JPopupMenu popup = new JPopupMenu();
270
271             JMenuItem item = new JMenuItem(UiDataMessages.CUT);
272             item.addActionListener(new DefaultEditorKit.CutAction());
273             popup.add(item);
274
275             item = new JMenuItem(UiDataMessages.COPY);
276             item.addActionListener(new DefaultEditorKit.CopyAction());
277             popup.add(item);
278
279             item = new JMenuItem(UiDataMessages.PASTE);
280             item.addActionListener(new DefaultEditorKit.PasteAction());
281             popup.add(item);
282
283             item = new JMenuItem(UiDataMessages.CLEAR);
284             item.addActionListener(new ActionListener() {
285                 @Override
286                 public void actionPerformed(ActionEvent e) {
287                     MyJTextField.this.setText("");
288                 }
289             });
290             popup.add(item);
291
292             return popup;
293         }
294     }
295 }