source: trunk/gli/src/org/greenstone/gatherer/gui/Filter.java@ 5350

Last change on this file since 5350 was 5301, checked in by jmt12, 21 years ago

Fixed 203B113 - custom filters now persistant throughout session

  • Property svn:keywords set to Author Date Id Revision
File size: 12.6 KB
Line 
1package org.greenstone.gatherer.gui;
2/**
3 *#########################################################################
4 *
5 * A component of the Gatherer application, part of the Greenstone digital
6 * library suite from the New Zealand Digital Library Project at the
7 * University of Waikato, New Zealand.
8 *
9 * <BR><BR>
10 *
11 * Author: John Thompson, Greenstone Digital Library, University of Waikato
12 *
13 * <BR><BR>
14 *
15 * Copyright (C) 1999 New Zealand Digital Library Project
16 *
17 * <BR><BR>
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * <BR><BR>
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 *
31 * <BR><BR>
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36 *########################################################################
37 */
38import java.awt.*;
39import java.awt.event.*;
40import java.util.*;
41import java.util.regex.*;
42import javax.swing.*;
43import javax.swing.tree.*;
44import org.greenstone.gatherer.Gatherer;
45import org.greenstone.gatherer.file.FileSystemModel;
46import org.greenstone.gatherer.gui.tree.DragTree;
47/** <p>This object allows the user to set a filter on one of the workspace trees, specifying a preset type, or a regular expression that a files must match to be in the tree. Note that all directories are included. This class includes the controls for editing the filter. The trick is that several instances of the Filter class can share the same internal data (termed a 'run' of filters), so that the filter set on the CollectionPane and the MetaEditPane are virtually the same.</p>
48 * <p>The regular expression typed can uses '*' as a wildcard character (equivelent to '.*'), and does not use '.' to match any single character (use '?' instead).</p>
49 * @author John Thompson, Greenstone Digital Library, University of Waikato
50 * @version 2.3
51 */
52public class Filter
53 extends JPanel {
54 /** The other filters in this run of filters, used to ensure they all show the same thing. */
55 private ArrayList others = null;
56 /** Is this the filter filter of this run of filters created (later filters will share the same information). */
57 private boolean first = true;
58 /** Prevent any changes we make in the class from causing events which we then process causing events... */
59 private boolean ignore = false;
60 /** A reference to ourselves so inner classes can refer to us. */
61 private Filter this_filter = null;
62 /** The check box to enabled/diable filter. */
63 private JCheckBox checkbox = null;
64 /** The editable combobox where you either choose a predefined filter, or type a new pseudo-regular expression. */
65 private GComboBox combobox = null;
66 /** The label shown on the filter controls. */
67 private JLabel label = null;
68 /** A reference to the tree this filter is being applied to. */
69 private DragTree tree = null;
70 /** The default size for the label. */
71 static final private Dimension SIZE = new Dimension(100,25);
72 /** Preprogrammed default filters. */
73 static final private String DEFAULTS[] = {"^.*\\.html?$", "^.*\\.xml$", "^.*\\.txt$", "(^.*\\.jpe?g$)|(^.*\\.png$)|(^.\\.gif$)|(^.\\.bmp$)|(^.\\.tif$)"};
74 /** Constructor.
75 * @param tree A reference to the <strong>JTree</strong> being affected.
76 */
77 public Filter(DragTree tree) {
78 this(tree, null);
79 }
80 /** Constructor.
81 * @param tree A reference to the <strong>JTree</strong> being affected.
82 * @param others An <strong>ArrayList</strong> of the other Filters already in this run.
83 */
84 public Filter(DragTree tree, ArrayList others) {
85 super();
86 if(others == null) {
87 this.others = new ArrayList();
88 }
89 else {
90 this.others = others;
91 }
92 this.others.add(this);
93 this.this_filter = this;
94 this.tree = tree;
95 // Create components.
96 combobox = new GComboBox();
97 combobox.add(new Entry());
98 for(int i = 0; i < DEFAULTS.length; i++) {
99 try {
100 Entry entry = new Entry(get((new Integer(i)).toString(), null), Pattern.compile(DEFAULTS[i]));
101 combobox.add(entry);
102 }
103 catch (Exception error) {
104 error.printStackTrace();
105 }
106 }
107 combobox.setEditable(true);
108 label = new JLabel(get("Filter_Tree"));
109 label.setPreferredSize(SIZE);
110 // Add listeners.
111 combobox.addActionListener(new ComboBoxListener());
112 // Layout.
113 label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
114
115 setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
116 setLayout(new BorderLayout());
117 add(label, BorderLayout.WEST);
118 add(combobox, BorderLayout.CENTER);
119 }
120 /** Retrieve the combobox associated with this filter.
121 * @return A <strong>GComboBox</strong>.
122 */
123 public GComboBox getComboBox() {
124 return combobox;
125 }
126
127 /** Change the background color of the filter.
128 * @param color The new background <strong>Color</strong>.
129 */
130 public void setBackground(Color color) {
131 super.setBackground(color);
132 }
133
134 /** Used to restore the filter state to enabled, the normal state during collection editing.
135 * @param state The new state for the filter. <i>true</i> for enabled, <i>false</i> otherwise.
136 */
137 public void setEnabled(boolean state) {
138 ignore = true;
139 combobox.setEditable(state);
140 combobox.setEnabled(state);
141 ignore = false;
142 }
143 /** Set the combobox model for this filter.
144 * @param model The new <strong>ComboBoxModel</strong> to use.
145 */
146 public void setComboBoxModel(ComboBoxModel model) {
147 combobox.setModel(model);
148 }
149 /** Ensure that a certain entry is selected from the combobox.
150 * @param selection The <strong>Entry</strong> that should be selected.
151 */
152 public void setComboBoxSelection(Entry selection) {
153 ignore = true;
154 combobox.setSelectedItem(selection);
155 ignore = false;
156 }
157 /** Set to signify that this filter is the first in a new run of filters.
158 * @param first <i>true</i> if this is the first filter in a run, <i>false</i> if it will just be added to the current run.
159 */
160 public void setFirst(boolean first) {
161 this.first = first;
162 }
163 /** Spawn produces a copy of this filter, which has new controls, but shares listeners wih this filter, and vice versa. Thus we can have two synchronized, but differing sets of controls.
164 * @param tree_spawn The <strong>JTree</strong> this filter will affect.
165 * @return A new <strong>Filter</strong> which is in the same run as this filter.
166 */
167 public Filter spawn(DragTree tree_spawn) {
168 Filter filter = new Filter(tree_spawn, others);
169 filter.setFirst(false); // No spawned copies should generate error messages, but fail silently.
170 filter.setComboBoxModel(combobox.getModel());
171 filter.setComboBoxSelection((Entry)combobox.getSelectedItem());
172 return filter;
173 }
174 /** Retrieve a phrase from the dictionary.
175 * @param key The unique identification <strong>String</strong> of a phrase from the dictionary.
176 */
177 private String get(String key) {
178 return get(key, null);
179 }
180 /** Retrieve a phrase from the dictionary, augmenting with the given text fragments
181 * @param key The unique identification <strong>String</strong> of a phrase from the dictionary.
182 * @param args A <strong>String[]</strong> of arguments to be used to fill out parameter fields in the phrase returned.
183 * @see org.greenstone.gatherer.Dictionary
184 * @see org.greenstone.gatherer.Gatherer
185 */
186 private String get(String key, String args[]) {
187 if(key.indexOf(".") == -1) {
188 key = "Filter." + key;
189 }
190 return Gatherer.dictionary.get(key, args);
191 }
192 /** Encode an expression in pseudo-regular expression into regular expression.
193 * @param raw The pseudo-regular expression <strong>String</strong> which includes several characters which differ in meaning from regular expression queries.
194 * @return A proper regular expression as a <strong>String</strong>.
195 */
196 private String encode(String raw) {
197 StringBuffer working = new StringBuffer();
198 for(int i = 0; i < raw.length(); i++) {
199 char c = raw.charAt(i);
200 switch(c) {
201 case '.':
202 working.append("\\.");
203 break;
204 case '*':
205 working.append(".*");
206 break;
207 case '?':
208 working.append(".");
209 break;
210 default:
211 working.append(Character.toLowerCase(c));
212 }
213 }
214 return working.toString();
215 }
216 /** This method applies the given pattern to the tree registered as belonging to this filter.*/
217 private void setFilter(Pattern pattern) {
218 // Show busy cursor.
219 Gatherer.g_man.wait(true);
220 FileSystemModel model = (FileSystemModel) tree.getModel();
221 // Apply filter
222 if(pattern != null) {
223 model.setFilter(pattern.pattern());
224 }
225 else {
226 model.setFilter(null);
227 }
228 // Ask tree to completely refresh
229 tree.refresh(null);
230 // Restore cursor
231 Gatherer.g_man.wait(false);
232 }
233 /** Listens for changes in the combobox as when one is detected attempts to compile a regular expression from whatever text was entered. If successful, or if the item chosen was a predefined filter, it then applies the filter to the target tree. */
234 private class ComboBoxListener
235 implements ActionListener {
236/** Called when a new item is selected from the filter combobox, we treat the new entry as a pseudo-regular expression, compile it and then apply it to the tree.
237 * @param event An <strong>ActionEvent</strong> containing more information about the change performed.
238 * @see org.greenstone.gatherer.gui.Filter.Entry
239 */
240 public void actionPerformed(ActionEvent event) {
241 try {
242 Object temp = combobox.getSelectedItem();
243 Entry entry = null;
244 if(temp instanceof String) {
245 String temp_str = (String) temp;
246 ///ystem.err.println("Filter = " + temp_str);
247 // Ignore any string which matches a predefined filter, starting with All Files.
248 if(temp_str.equals(get("All_Files"))) {
249 }
250 // HTM & HTML
251 else if(temp_str.equals(get("0"))) {
252 }
253 // XML
254 else if(temp_str.equals(get("1"))) {
255 }
256 // Text files
257 else if(temp_str.equals(get("2"))) {
258 }
259 // Images
260 else if(temp_str.equals(get("3"))) {
261 }
262 else {
263 ///ystem.err.println("Temporary Custom Filter");
264 entry = new Entry((String)temp, Pattern.compile(encode((String)temp)));
265 combobox.removeItem(temp);
266 int position = combobox.getItemCount();
267 combobox.insertItemAt(entry, position);
268 combobox.setSelectedIndex(position);
269 ///ystem.err.println("Inserting permanent custom filter.");
270 }
271 }
272 else {
273 ///ystem.err.println("Custom Filter");
274 entry = (Entry) temp;
275 }
276 if(entry != null) {
277 setFilter(entry.getPattern());
278 }
279 // Else we ignore this event as being one of the painfully erroneous events we receive because we've been silly enough to have an editable combobox.
280 }
281 catch (PatternSyntaxException error) {
282 if(first) {
283 JOptionPane.showMessageDialog(Gatherer.g_man, get("Invalid_Pattern"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
284 }
285 }
286 }
287 }
288 /** An object that holds a filter entry. This is string used for the filter pattern and, if not custom built, its name. */
289 private class Entry
290 implements Comparable {
291 /** The compiled pattern created from a regular expression. */
292 private Pattern pattern = null;
293 /** The name of this filter entry. */
294 private String name = null;
295 /** Constructor. */
296 public Entry() {
297 }
298 /** Constructor.
299 * @param name The name of this entry as a <strong>String</strong>.
300 * @param pattern The compiled regular expression as a <strong>Pattern</strong>.
301 */
302 public Entry(String name, Pattern pattern) {
303 this.name = name;
304 this.pattern = pattern;
305 }
306 /** Compare two Entrys for ordering.
307 * @param object The other Entry to compare to, as an <strong>Object</strong>.
308 * @return An <i>int</i> indicating the respective ordering, as defined in java.lang.String#compareTo
309 */
310 public int compareTo(Object object) {
311 return toString().compareTo(object.toString());
312 }
313 /** Retrieve the pattern associated with this entry.
314 * @return The <strong>Pattern</strong>.
315 */
316 public Pattern getPattern() {
317 return pattern;
318 }
319 /** Translate this entry into a textual representation.
320 * @return A <strong>String</strong> containing the representation.
321 */
322 public String toString() {
323 String result = null;
324 if(name != null) {
325 result = name;
326 }
327 else if(pattern == null) {
328 result = get("All_Files");
329 }
330 else {
331 result = pattern.pattern();
332 }
333 return result;
334 }
335 }
336}
Note: See TracBrowser for help on using the repository browser.