Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/greenstone/gatherer/gui/metaaudit/AutofilterDialog.java


1   /**
2    *#########################################################################
3    *
4    * A component of the Gatherer application, part of the Greenstone digital
5    * library suite from the New Zealand Digital Library Project at the
6    * University of Waikato, New Zealand.
7    *
8    * <BR><BR>
9    *
10   * Author: John Thompson, Greenstone Digital Library, University of Waikato
11   *
12   * <BR><BR>
13   *
14   * Copyright (C) 1999 New Zealand Digital Library Project
15   *
16   * <BR><BR>
17   *
18   * This program is free software; you can redistribute it and/or modify
19   * it under the terms of the GNU General Public License as published by
20   * the Free Software Foundation; either version 2 of the License, or
21   * (at your option) any later version.
22   *
23   * <BR><BR>
24   *
25   * This program is distributed in the hope that it will be useful,
26   * but WITHOUT ANY WARRANTY; without even the implied warranty of
27   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28   * GNU General Public License for more details.
29   *
30   * <BR><BR>
31   *
32   * You should have received a copy of the GNU General Public License
33   * along with this program; if not, write to the Free Software
34   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35   *########################################################################
36   */
37  package org.greenstone.gatherer.gui.metaaudit;
38  
39  import java.awt.*;
40  import java.awt.event.*;
41  import java.util.*;
42  import javax.swing.*;
43  import org.greenstone.gatherer.Dictionary;
44  import org.greenstone.gatherer.Gatherer;
45  import org.greenstone.gatherer.gui.metaaudit.Autofilter;
46  import org.greenstone.gatherer.gui.metaaudit.Filter;
47  import org.greenstone.gatherer.gui.metaaudit.MetaAuditFrame;
48  import org.greenstone.gatherer.gui.SimpleMenuBar;
49  import org.greenstone.gatherer.gui.ModalDialog;
50  
51  /** The autofilter concept comes from Microsoft Excel spreadsheets that use autofilters to filter to the sheet. When you click on the heading of a column, a new prompt allows you to specify what filter should be acting apon the selected column. Any new filter is conjoined with any previous filters to provide a sheet containing only rows that match all current filters. Each column must also provide an indicator for determining if a filter is set (in this case a special icon) and and a method for removing a filter (use the clear filter button within the autofilter dialog). Having recently discovered that most JVMs aren't very good at recoving memory used by dialog and frame windows, special care must be made to deallocate all references properly, as a user may open several dozen autofilter prompts over the lifetime of a session.
52   * @author John Thompson, Greenstone Digital Library, University of Waikato
53   * @version 2.3
54   */
55  public final class AutofilterDialog
56      extends ModalDialog {
57      /** The filter being edited. */
58      private Autofilter filter;
59      /** A reference to ourselves so our inner classes can reference us. */
60      private AutofilterDialog self;
61      /** The value returned from the filter dialog prompt. Used to determine if a prompt was set or unset, and what subsequent action to take. */
62      private byte return_value = 0;
63      /** The button used to cancel the prompt. */
64      private JButton cancel_button = null;
65      private JButton remove_button = null;
66      private JButton set_button = null;
67      /** Used to specify that the given filters should be applied conjunctly. */
68      private JRadioButton and_radiobutton = null;
69      /** The check box used to specify whether the first filter is case sensitive. */
70      private JCheckBox first_case = null;
71      /** Used to disable the second filter. */
72      private JRadioButton none_radiobutton = null;
73      /** Used to specify that the given filters should be applied disjunctly. */
74      private JRadioButton or_radiobutton = null;
75      /** The check box used to specify whether the second filter is case sensitive. */
76      private JCheckBox second_case = null;
77      /** Used to specify the order of the resulting set: Ascending or Descending. */
78      private JComboBox order = null;
79      /** The method used to match the first filter: Contains, Doesn't contain etc. */
80      private JComboBox first_method = null;
81      /** The value to be matched for the first filter. */
82      private JComboBox first_value = null;
83      /** The method used to match the first filter. Options as for the first method. */
84      private JComboBox second_method = null;
85      /** The value to be matched for the second filter. */
86      private JComboBox second_value = null;
87      /** Used for the most basic filter where an Equals, Case sensitive method is automatically used. */
88      private JComboBox value = null;
89      /** The label which displays the name of the currently selected column (the column that will be associated with the autofilter this dialog produces). */
90      private JLabel name;
91      /** The autofilter prompt contains two different panes, one for basic functionality and one for advanced. This containiner component is used to allow access to each via a 'tabbed' interface. */
92      private JTabbedPane control = null;
93      /** A reference back to the MetaAudit dialog that spawned this prompt. Used to make sure that any open dialog window is always in front of the audit pane. */
94      private MetaAuditFrame dialog;
95      /** The default size for the autofilter control. */
96      static final private Dimension SIZE = new Dimension(640, 245);
97  
98      /** Constructor.
99       * @param dialog A reference to the <strong>MetaAuditFrame</strong> that spawned this dialog.
100      * @see org.greenstone.gatherer.gui.metaaudit.Autofilter
101      * @see org.greenstone.gatherer.gui.metaaudit.AutofilterDialog.ButtonListener
102      * @see org.greenstone.gatherer.gui.metaaudit.AutofilterDialog.CheckListener
103      */
104     public AutofilterDialog(MetaAuditFrame dialog) {
105   super(Gatherer.g_man);
106   this.dialog = dialog;
107   this.self = this;
108   setModal(true);
109   setJMenuBar(new SimpleMenuBar("reviewingmetadata")); 
110   setSize(SIZE);
111   Dictionary.setText(this, "Autofilter.Title");
112 
113   // Creation
114   JPanel content_pane = (JPanel) getContentPane();
115   JPanel name_pane = new JPanel();
116   JLabel name_label = new JLabel();
117   Dictionary.setText(name_label, "Autofilter.Name");
118   JTextField name_template = new JTextField();
119   name = new JLabel();
120   name.setBorder(name_template.getBorder());
121   control = new JTabbedPane();
122   JPanel value_pane = new JPanel();
123   JPanel inner_value_pane = new JPanel();
124   JLabel value_label = new JLabel();
125   Dictionary.setText(value_label, "Autofilter.eqeq"); 
126   value = new JComboBox();
127   value.setEditable(false);
128   JPanel custom_pane = new JPanel();
129 
130   JPanel first_pane = new JPanel();
131   first_method = new JComboBox();
132   first_value = new JComboBox();
133   first_value.setEditable(true);
134   first_value.addItem("");
135   first_value.setSelectedItem("");
136   first_case = new JCheckBox();
137   Dictionary.setText(first_case, "Autofilter.Case_Sensitive");
138   JPanel operator_pane = new JPanel();
139   JLabel operator_label = new JLabel();
140   Dictionary.setText(operator_label, "Autofilter.Operator");
141   ButtonGroup operator_group = new ButtonGroup();
142   and_radiobutton = new JRadioButton();
143   and_radiobutton.setOpaque(false);
144   Dictionary.setText(and_radiobutton, "Autofilter.AND");
145   none_radiobutton = new JRadioButton();
146   none_radiobutton.setOpaque(false);
147   none_radiobutton.setSelected(true);
148   Dictionary.setText(none_radiobutton, "Autofilter.None");
149   or_radiobutton = new JRadioButton();
150   or_radiobutton.setOpaque(false);
151   Dictionary.setText(or_radiobutton, "Autofilter.OR");
152   operator_group.add(none_radiobutton);
153   operator_group.add(and_radiobutton);
154   operator_group.add(or_radiobutton);
155 
156   JPanel second_pane = new JPanel();
157   second_method = new JComboBox();
158   second_method.setEnabled(false);
159   second_value = new JComboBox();
160   second_value.setEditable(true);
161   second_value.setEnabled(false);
162   second_value.addItem("");
163   second_value.setSelectedItem("");
164   second_case = new JCheckBox();
165   Dictionary.setText(second_case, "Autofilter.Case_Sensitive"); 
166   JPanel lower_pane = new JPanel();
167   JPanel order_pane = new JPanel();
168   JLabel order_label = new JLabel();
169   Dictionary.setText(order_label, "Autofilter.Order");
170   order = new JComboBox();
171   order.addItem(Dictionary.get("Autofilter.Ascending"));
172   order.addItem(Dictionary.get("Autofilter.Descending"));
173   Dictionary.setTooltip(order, "Autofilter.Order_Tooltip");
174 
175   // Assign values to method comboboxes.
176   for(int i = 0; i < Autofilter.METHOD_LIST.length; i++) {
177       first_method.addItem(Dictionary.get("Autofilter." + Autofilter.METHOD_LIST[i]));
178       second_method.addItem(Dictionary.get("Autofilter." + Autofilter.METHOD_LIST[i]));
179   }
180   JPanel button_pane = new JPanel();
181   cancel_button = new JButton();
182   cancel_button.setMnemonic(KeyEvent.VK_C);
183   Dictionary.setBoth(cancel_button, "General.Cancel", "General.Pure_Cancel_Tooltip");
184   remove_button = new JButton();
185   remove_button.setMnemonic(KeyEvent.VK_R);
186   Dictionary.setBoth(remove_button, "Autofilter.Remove", "Autofilter.Remove_Tooltip");
187   set_button = new JButton();
188   set_button.setMnemonic(KeyEvent.VK_S);
189   Dictionary.setBoth(set_button, "Autofilter.Set", "Autofilter.Set_Tooltip");
190 
191   // Connection
192   and_radiobutton.addActionListener(new CheckListener(true));
193   none_radiobutton.addActionListener(new CheckListener(false));
194   or_radiobutton.addActionListener(new CheckListener(true));
195   cancel_button.addActionListener(new ButtonListener(false));
196   remove_button.addActionListener(new ButtonListener(false));
197   set_button.addActionListener(new ButtonListener(true));
198 
199   // Layout      
200   name_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
201 
202   name_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
203   name_pane.setLayout(new BorderLayout());
204   name_pane.add(name_label, BorderLayout.WEST);
205   name_pane.add(name, BorderLayout.CENTER);
206 
207   value_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
208 
209   inner_value_pane.setLayout(new BorderLayout());
210   inner_value_pane.add(value_label, BorderLayout.WEST);
211   inner_value_pane.add(value, BorderLayout.CENTER);
212 
213   value_pane.setBorder(BorderFactory.createEmptyBorder(5,10,5,10));
214   value_pane.setLayout(new BorderLayout());
215   value_pane.add(inner_value_pane, BorderLayout.NORTH);
216 
217   first_pane.setLayout(new BorderLayout());
218   first_pane.add(first_method, BorderLayout.WEST);
219   first_pane.add(first_value, BorderLayout.CENTER);
220   first_pane.add(first_case, BorderLayout.EAST);
221 
222   operator_pane.setLayout(new GridLayout(1,4));
223   operator_pane.add(operator_label);
224   operator_pane.add(none_radiobutton);
225   operator_pane.add(and_radiobutton);
226   operator_pane.add(or_radiobutton);
227 
228   second_pane.setLayout(new BorderLayout());
229   second_pane.add(second_method, BorderLayout.WEST);
230   second_pane.add(second_value, BorderLayout.CENTER);
231   second_pane.add(second_case, BorderLayout.EAST);
232 
233   order_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
234   order_pane.setLayout(new GridLayout(1,2));
235   order_pane.add(order_label);
236   order_pane.add(order);
237 
238   custom_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
239   custom_pane.setLayout(new GridLayout(3,1));
240   custom_pane.add(first_pane);
241   custom_pane.add(operator_pane);
242   custom_pane.add(second_pane);
243 
244   control.add(Dictionary.get("Autofilter.Filter_By_Value"), value_pane);
245   control.add(Dictionary.get("Autofilter.Custom_Filter"), custom_pane);
246 
247   button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
248   button_pane.setLayout(new GridLayout(1, 3));
249   button_pane.add(set_button);
250   button_pane.add(remove_button);
251   button_pane.add(cancel_button);
252 
253   lower_pane.setLayout(new BorderLayout());
254   lower_pane.add(order_pane, BorderLayout.CENTER);
255   lower_pane.add(button_pane, BorderLayout.SOUTH);
256 
257   content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
258   content_pane.setLayout(new BorderLayout());
259   content_pane.add(name_pane, BorderLayout.NORTH);
260   content_pane.add(control, BorderLayout.CENTER);
261   content_pane.add(lower_pane, BorderLayout.SOUTH);
262 
263   Dimension screen_size = Gatherer.config.screen_size;
264   setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
265   screen_size = null;
266     }
267 
268     /** Destructor. */
269     public void destroy() {
270   dispose();
271   first_case = null;
272   second_case = null;
273   order = null;
274   first_method = null;
275   first_value = null;
276   second_method = null;
277   second_value = null;
278   value = null;
279   control = null;
280   dialog = null;
281   self = null;
282   name = null;
283     }
284     /** Display the modal dialog box, allowing the user to define the filter. When the user presses one of the buttons, dispose and return to the caller providing an indication of which button was pressed.
285      * @return An <i>int</i> which indicates which button was pressed to dismiss the dialog.
286      */
287     public Autofilter display(Autofilter filter, ArrayList raw_values, String column_name) {
288   this.filter = filter;
289   name.setText(column_name);
290   // Prune values so it only contains unique entries, then order.
291   TreeSet values = new TreeSet(raw_values);
292   value.setModel(new DefaultComboBoxModel(values.toArray()));
293   String star = "*";
294   value.insertItemAt(star, 0);
295   value.setSelectedItem(star);
296   first_value.setModel(new DefaultComboBoxModel(values.toArray()));
297   second_value.setModel(new DefaultComboBoxModel(values.toArray()));
298   // Restore previous values.
299   if(filter != null && filter.value_one != null) {
300       value.setSelectedItem(filter.value_one);
301       first_method.setSelectedIndex(filter.method_one);
302       first_value.setSelectedItem(filter.value_one);
303       first_case.setSelected(filter.casesense_one);
304       if (filter.value_two == null) {
305     none_radiobutton.setSelected(true);
306       }
307       else {
308     if (filter.operation) {
309         and_radiobutton.setSelected(true);
310     }
311     else {
312         or_radiobutton.setSelected(true);
313     }
314     second_method.setSelectedIndex(filter.method_two);
315     second_value.setSelectedItem(filter.value_two);
316     second_case.setSelected(filter.casesense_two);
317       }
318       if(filter.sort) {
319     order.setSelectedIndex(0);
320       }
321       else {
322     order.setSelectedIndex(1);
323       }
324   }
325   // Display    
326   setVisible(true);
327   dialog.toFront();
328   return this.filter;
329     }
330 
331     /** Listens for actions on the button it is attached to, and when notified sets the return_value and disposes of the dialog. */
332     private final class ButtonListener
333   implements ActionListener {
334   private boolean return_filter;
335   /** Does an action on this button cause a filter to be returned. */
336   /** Constructor takes an associated return value as an argument.
337    * @param return_filter <i>true</i> if we update then return the filter, <i>false</i> to clear existing filter.
338    */
339   public ButtonListener(boolean return_filter) {
340       this.return_filter = return_filter;
341   }
342   /** When any registered component is actioned apon, set the value and hide the dialog. We hide rather than dispose, because hide assures the data values will be retained. 
343    * @param event An <strong>ActionEvent</strong> containing information about the action that caused this method call.
344    * @see org.greenstone.gatherer.gui.metaaudit.Autofilter
345    */
346   public void actionPerformed(ActionEvent event) {
347       if(return_filter) {
348     if(control.getSelectedIndex() == 0) {
349         filter.setFilter(1, 0, (String)value.getSelectedItem(), true);
350         filter.setFilter(2, 0, null, true);
351     }
352     else {
353         filter.setFilter(1, first_method.getSelectedIndex(), (String)first_value.getSelectedItem(), first_case.isSelected());
354         if(!none_radiobutton.isSelected()) {
355       if (and_radiobutton.isSelected()) {
356           filter.setOperation(Autofilter.AND);
357       }
358       else {
359           filter.setOperation(Autofilter.OR);
360       }
361       filter.setFilter(2, second_method.getSelectedIndex(), (String)second_value.getSelectedItem(), second_case.isSelected());
362         }
363     }
364     if(order.getSelectedIndex() == 0) {
365         filter.setSort(Autofilter.ASCENDING);
366     }
367     else {
368         filter.setSort(Autofilter.DESCENDING);
369     }
370       }
371       else {
372     filter = null;
373       }
374       setVisible(false);
375   }
376     }
377     /** Listens for actions on the check box it is attached to, and when notified sets the state of the second method and value to the specified state. */
378     private final class CheckListener
379   implements ActionListener {
380   /** The default desire state any check button this listens to. */
381   private boolean desired_state = false;
382   /** The constructor takes an associated desired state.
383    * @param desired_state The state that should be set when this is actioned, as a <i>boolean</i>.
384       */
385   public CheckListener(boolean desired_state) {
386       this.desired_state = desired_state;
387   }
388   /** Whenever our registered components are actioned apon, set the state of the second method and value to the desired state. */
389   public void actionPerformed(ActionEvent event) {
390       second_method.setEnabled(desired_state);
391       second_value.setEnabled(desired_state);
392   }
393     }
394 }