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

Quick Search    Search Deep

Source code: com/virtuosotechnologies/asaph/maingui/SearchGui.java


1   /*
2   ================================================================================
3   
4     FILE:  SearchGui.java
5     
6     PROJECT:
7     
8       Asaph
9     
10    CONTENTS:
11    
12      Song list filter gui
13    
14    PROGRAMMERS:
15    
16      Daniel Azuma (DA)  <dazuma@kagi.com>
17    
18    COPYRIGHT:
19    
20      Copyright (C) 2003  Daniel Azuma  (dazuma@kagi.com)
21      
22      This program is free software; you can redistribute it and/or
23      modify it under the terms of the GNU General Public License as
24      published by the Free Software Foundation; either version 2
25      of the License, or (at your option) any later version.
26      
27      This program is distributed in the hope that it will be useful,
28      but WITHOUT ANY WARRANTY; without even the implied warranty of
29      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30      GNU General Public License for more details.
31      
32      You should have received a copy of the GNU General Public
33      License along with this program; if not, write to
34        Free Software Foundation, Inc.
35        59 Temple Place, Suite 330
36        Boston, MA 02111-1307 USA
37  
38  ================================================================================
39  */
40  
41  
42  package com.virtuosotechnologies.asaph.maingui;
43  
44  
45  import java.awt.GridBagConstraints;
46  import java.awt.GridBagLayout;
47  import java.awt.BorderLayout;
48  import java.awt.FlowLayout;
49  import java.awt.Insets;
50  import java.awt.event.ActionListener;
51  import java.awt.event.ActionEvent;
52  import java.util.List;
53  import java.util.ArrayList;
54  import java.util.Iterator;
55  import java.util.Map;
56  import java.util.HashMap;
57  import javax.swing.JDialog;
58  import javax.swing.JPanel;
59  import javax.swing.JButton;
60  import javax.swing.JRadioButton;
61  import javax.swing.ButtonGroup;
62  import javax.swing.JScrollPane;
63  import javax.swing.JLabel;
64  import javax.swing.JComboBox;
65  import javax.swing.JTextField;
66  import javax.swing.BorderFactory;
67  
68  import com.virtuosotechnologies.lib.asyncjob.AsyncJobRunner;
69  import com.virtuosotechnologies.lib.asyncjob.AsyncJobListener;
70  import com.virtuosotechnologies.lib.asyncjob.ThreadWorkerAsyncJobRunner;
71  import com.virtuosotechnologies.lib.asyncjob.BasicAsyncJobListener;
72  import com.virtuosotechnologies.lib.asyncjob.AsyncJobFailedEvent;
73  import com.virtuosotechnologies.lib.asyncjob.AsyncJobException;
74  import com.virtuosotechnologies.lib.asyncjob.AsyncJob;
75  import com.virtuosotechnologies.lib.asyncjob.AbstractAsyncJob;
76  import com.virtuosotechnologies.lib.asyncjob.AsyncJobProgressReporter;
77  import com.virtuosotechnologies.lib.swing.DetailedMessageDialog;
78  import com.virtuosotechnologies.lib.swing.SwingUtils;
79  import com.virtuosotechnologies.lib.util.ExceptionUtils;
80  
81  import com.virtuosotechnologies.asaph.model.Song;
82  import com.virtuosotechnologies.asaph.model.opsemantics.SearchBodyPredicateSemantics;
83  import com.virtuosotechnologies.asaph.model.opsemantics.SearchFieldPredicateSemantics;
84  import com.virtuosotechnologies.asaph.model.opsemantics.SearchParameters;
85  import com.virtuosotechnologies.asaph.model.opsemantics.PredicateSemantics;
86  import com.virtuosotechnologies.asaph.model.opsemantics.TruePredicateSemantics;
87  import com.virtuosotechnologies.asaph.model.opsemantics.AndPredicateSemantics;
88  import com.virtuosotechnologies.asaph.model.opsemantics.OrPredicateSemantics;
89  import com.virtuosotechnologies.asaph.modelutils.SongUtils;
90  
91  
92  /**
93   * Song list filter gui
94   */
95  /*package*/ class SearchGui
96  {
97    /*package*/ static class ComboBoxItem
98    {
99      private static Map itemMap_ = new HashMap();
100     
101     private Object data_;
102     private String representation_;
103     
104     /*package*/ ComboBoxItem(
105       Object data,
106       String representation)
107     {
108       representation_ = representation;
109       data_ = data;
110       itemMap_.put(data_, this);
111     }
112     
113     /*package*/ Object getData()
114     {
115       return data_;
116     }
117     
118     public String toString()
119     {
120       return representation_;
121     }
122     
123     /*package*/ static ComboBoxItem findItem(
124       Object data,
125       ComboBoxItem defaultValue)
126     {
127       ComboBoxItem ret = (ComboBoxItem)itemMap_.get(data);
128       if (ret == null)
129       {
130         ret = defaultValue;
131       }
132       return ret;
133     }
134   }
135   
136   
137   private static final String STR_Dialog_DatabaseErrorTitle =
138     ResourceAccess.Strings.buildString("Dialog_DatabaseErrorTitle");
139   private static final String STR_Dialog_ErrorHeader =
140     ResourceAccess.Strings.buildString("Dialog_ErrorHeader");
141   private static final String STR_Dialog_FirstExceptionTemplate =
142     ResourceAccess.Strings.buildString("Dialog_FirstExceptionTemplate");
143   private static final String STR_Dialog_NextExceptionTemplate =
144     ResourceAccess.Strings.buildString("Dialog_NextExceptionTemplate");
145   private static final String STR_Message_InternalError =
146     ResourceAccess.Strings.buildString("Message_InternalError");
147   private static final String STR_Command_Filtering =
148     ResourceAccess.Strings.buildString("Command_Filtering");
149   
150   private static final String STR_Search_DialogTitle =
151     ResourceAccess.Strings.buildString("Search_DialogTitle");
152   private static final String STR_Search_AnyOfRadio =
153     ResourceAccess.Strings.buildString("Search_AnyOfRadio");
154   private static final String STR_Search_AllOfRadio =
155     ResourceAccess.Strings.buildString("Search_AllOfRadio");
156   private static final String STR_Search_Prompt =
157     ResourceAccess.Strings.buildString("Search_Prompt");
158   private static final String STR_Search_AddButton =
159     ResourceAccess.Strings.buildString("Search_AddButton");
160   private static final String STR_Search_DeleteButton =
161     ResourceAccess.Strings.buildString("Search_DeleteButton");
162   private static final String STR_Search_OKButton =
163     ResourceAccess.Strings.buildString("Search_OKButton");
164   private static final String STR_Search_CancelButton =
165     ResourceAccess.Strings.buildString("Search_CancelButton");
166   
167   private static final ComboBoxItem mainTitleFieldItem = new ComboBoxItem(
168     Song.MAINTITLE_FIELD, ResourceAccess.Strings.buildString("Search_MainTitle"));
169   private static final ComboBoxItem authorFieldItem = new ComboBoxItem(
170     Song.AUTHOR_FIELD, ResourceAccess.Strings.buildString("Search_Author"));
171   private static final ComboBoxItem commentFieldItem = new ComboBoxItem(
172     Song.COMMENT_FIELD, ResourceAccess.Strings.buildString("Search_Comment"));
173   private static final ComboBoxItem copyrightFieldItem = new ComboBoxItem(
174     Song.COPYRIGHT_FIELD, ResourceAccess.Strings.buildString("Search_Copyright"));
175   private static final ComboBoxItem altTitlesFieldItem = new ComboBoxItem(
176     Song.ALTERNATETITLELIST_FIELD, ResourceAccess.Strings.buildString("Search_AltTitles"));
177   private static final ComboBoxItem keywordsFieldItem = new ComboBoxItem(
178     Song.KEYWORDLIST_FIELD, ResourceAccess.Strings.buildString("Search_Keywords"));
179   private static final ComboBoxItem bodyFieldItem = new ComboBoxItem(
180     SearchBodyPredicateSemantics.ENTIRE_BODY, ResourceAccess.Strings.buildString("Search_SongBody"));
181   private static final ComboBoxItem firstLineFieldItem = new ComboBoxItem(
182     SearchBodyPredicateSemantics.FIRST_LINE, ResourceAccess.Strings.buildString("Search_FirstLine"));
183   
184   private static final ComboBoxItem containsPositionItem = new ComboBoxItem(
185     SearchParameters.CONTAINS, ResourceAccess.Strings.buildString("Search_Contains"));
186   private static final ComboBoxItem startsWithPositionItem = new ComboBoxItem(
187     SearchParameters.STARTS_WITH, ResourceAccess.Strings.buildString("Search_StartsWith"));
188   private static final ComboBoxItem endsWithPositionItem = new ComboBoxItem(
189     SearchParameters.ENDS_WITH, ResourceAccess.Strings.buildString("Search_EndsWith"));
190   private static final ComboBoxItem equalsPositionItem = new ComboBoxItem(
191     SearchParameters.EQUALS, ResourceAccess.Strings.buildString("Search_Equals"));
192   
193   private static final ComboBoxItem primaryStrengthItem = new ComboBoxItem(
194     SearchParameters.PRIMARY_STRENGTH, ResourceAccess.Strings.buildString("Search_PrimaryStrength"));
195   private static final ComboBoxItem secondaryStrengthItem = new ComboBoxItem(
196     SearchParameters.SECONDARY_STRENGTH, ResourceAccess.Strings.buildString("Search_SecondaryStrength"));
197   private static final ComboBoxItem tertiaryStrengthItem = new ComboBoxItem(
198     SearchParameters.TERTIARY_STRENGTH, ResourceAccess.Strings.buildString("Search_TertiaryStrength"));
199   
200   
201   private AsyncJobRunner jobRunner_;
202   private AsyncJobListener jobListener_;
203   private GuiEnvironmentManager guiEnviron_;
204   private ListsImpl listsImpl_;
205   private SongUtils songUtils_;
206   
207   private boolean okPressed_;
208   private boolean allOf_;
209   private List predicates_;
210   
211   
212   /*package*/ SearchGui(
213     GuiEnvironmentManager guiEnviron,
214     ListsImpl listsImpl,
215     SongUtils songUtils)
216   {
217     guiEnviron_ = guiEnviron;
218     listsImpl_ = listsImpl;
219     songUtils_ = songUtils;
220     
221     jobRunner_ = new ThreadWorkerAsyncJobRunner(1);
222     guiEnviron_.registerAsyncJobRunner(jobRunner_);
223     jobRunner_.addAsyncJobListener(
224       jobListener_ = new BasicAsyncJobListener()
225       {
226         public void jobFailed(
227           final AsyncJobFailedEvent ev)
228         {
229           SwingUtils.invokeOnSwingThread(
230             new Runnable()
231             {
232               public void run()
233               {
234                 AsyncJobException ex = ev.getException();
235                 Throwable cause = ex.getCause();
236                 DetailedMessageDialog dialog = DetailedMessageDialog.create(
237                   guiEnviron_.getDialogParent(), STR_Dialog_DatabaseErrorTitle,
238                   STR_Message_InternalError, STR_Dialog_ErrorHeader,
239                   ExceptionUtils.getDescriptionFor(cause,
240                     STR_Dialog_FirstExceptionTemplate, STR_Dialog_NextExceptionTemplate),
241                   null);
242                 dialog.show();
243               }
244             });
245         }
246       });
247   }
248   
249   
250   /*package*/ void doFindSongs()
251   {
252     PredicateSemantics oldPredicate = listsImpl_.getFilter();
253     allOf_ = true;
254     okPressed_ = false;
255     predicates_ = new ArrayList();
256     if (oldPredicate instanceof AndPredicateSemantics)
257     {
258       AndPredicateSemantics andPredicate = (AndPredicateSemantics)oldPredicate;
259       predicates_.addAll(andPredicate.getChildren());
260     }
261     else if (oldPredicate instanceof OrPredicateSemantics)
262     {
263       allOf_ = false;
264       OrPredicateSemantics orPredicate = (OrPredicateSemantics)oldPredicate;
265       predicates_.addAll(orPredicate.getChildren());
266     }
267     
268     JDialog dialog = buildDialog();
269     dialog.show();
270     
271     if (okPressed_)
272     {
273       PredicateSemantics newPredicate;
274       if (predicates_.isEmpty())
275       {
276         newPredicate = new TruePredicateSemantics.DefaultImplementation();
277       }
278       else if (allOf_)
279       {
280         newPredicate = new AndPredicateSemantics.DefaultImplementation(predicates_.iterator());
281       }
282       else
283       {
284         newPredicate = new OrPredicateSemantics.DefaultImplementation(predicates_.iterator());
285       }
286       final PredicateSemantics predicate = newPredicate;
287       predicates_ = null;
288       
289       jobRunner_.startJob(
290         new AbstractAsyncJob(STR_Command_Filtering, false, AsyncJob.INDETERMINATE_PROGRESS, null)
291         {
292           public Object run(
293             AsyncJobProgressReporter reporter)
294           throws
295             AsyncJobException
296           {
297             listsImpl_.setFilter(predicate);
298             return null;
299           }
300         });
301     }
302   }
303   
304   
305   private JDialog buildDialog()
306   {
307     final JDialog dialog = SwingUtils.createJDialog(guiEnviron_.getDialogParent(),
308       STR_Search_DialogTitle, true);
309     dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
310     
311     JPanel mainPanel = new JPanel(new GridBagLayout());
312     dialog.setContentPane(mainPanel);
313     
314     final JPanel filterListPanel = new JPanel(new GridBagLayout());
315     filterListPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
316     JPanel filterListContainer = new JPanel(new BorderLayout());
317     filterListContainer.add(filterListPanel, BorderLayout.NORTH);
318     JScrollPane scroller = new JScrollPane(filterListContainer,
319       JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
320     
321     JRadioButton allOfRadio = new JRadioButton(STR_Search_AllOfRadio, allOf_);
322     JRadioButton anyOfRadio = new JRadioButton(STR_Search_AnyOfRadio, !allOf_);
323     allOfRadio.addActionListener(
324       new ActionListener()
325       {
326         public void actionPerformed(
327           ActionEvent ev)
328         {
329           allOf_ = true;
330         }
331       });
332     anyOfRadio.addActionListener(
333       new ActionListener()
334       {
335         public void actionPerformed(
336           ActionEvent ev)
337         {
338           allOf_ = false;
339         }
340       });
341     
342     JButton addFilterButton = new JButton(STR_Search_AddButton);
343     addFilterButton.addActionListener(
344       new ActionListener()
345       {
346         public void actionPerformed(
347           ActionEvent ev)
348         {
349           PredicateSemantics predicate = new SearchFieldPredicateSemantics.DefaultImplementation(
350             Song.MAINTITLE_FIELD, new SearchParameters(
351               SearchParameters.EQUALS, "", SearchParameters.PRIMARY_STRENGTH));
352           predicates_.add(predicate);
353           addFilterGui(predicate, filterListPanel);
354           filterListPanel.revalidate();
355         }
356       });
357     
358     ButtonGroup buttonGroup = new ButtonGroup();
359     buttonGroup.add(allOfRadio);
360     buttonGroup.add(anyOfRadio);
361     
362     JButton okButton = new JButton(STR_Search_OKButton);
363     okButton.addActionListener(
364       new ActionListener()
365       {
366         public void actionPerformed(
367           ActionEvent ev)
368         {
369           okPressed_ = true;
370           fillInPredicates(filterListPanel);
371           dialog.dispose();
372         }
373       });
374     
375     JButton cancelButton = new JButton(STR_Search_CancelButton);
376     cancelButton.addActionListener(
377       new ActionListener()
378       {
379         public void actionPerformed(
380           ActionEvent ev)
381         {
382           dialog.dispose();
383         }
384       });
385     
386     GridBagConstraints gbc = new GridBagConstraints();
387     
388     gbc.gridx = 0;
389     gbc.gridy = 0;
390     gbc.gridwidth = 3;
391     gbc.anchor = GridBagConstraints.WEST;
392     gbc.fill = GridBagConstraints.NONE;
393     gbc.insets = new Insets(10, 10, 10, 10);
394     mainPanel.add(new JLabel(STR_Search_Prompt), gbc);
395     
396     gbc.gridy = 1;
397     gbc.gridwidth = 1;
398     gbc.insets = new Insets(0, 10, 10, 10);
399     mainPanel.add(allOfRadio, gbc);
400     
401     gbc.gridx = 1;
402     gbc.insets = new Insets(0, 0, 10, 10);
403     mainPanel.add(anyOfRadio, gbc);
404     
405     gbc.gridx = 2;
406     gbc.weightx = 1;
407     gbc.insets = new Insets(0, 0, 10, 10);
408     gbc.anchor = GridBagConstraints.EAST;
409     mainPanel.add(addFilterButton, gbc);
410     
411     gbc.weightx = 0;
412     gbc.gridwidth = 3;
413     gbc.gridx = 0;
414     gbc.gridy = 2;
415     gbc.weighty = 1;
416     gbc.insets = new Insets(0, 10, 5, 10);
417     gbc.anchor = GridBagConstraints.WEST;
418     gbc.fill = GridBagConstraints.BOTH;
419     mainPanel.add(scroller, gbc);
420     
421     JPanel buttonPanel = new JPanel(new FlowLayout());
422     gbc.weighty = 0;
423     gbc.gridy = 3;
424     mainPanel.add(buttonPanel, gbc);
425     buttonPanel.add(okButton);
426     buttonPanel.add(cancelButton);
427     
428     for (Iterator iter = predicates_.iterator(); iter.hasNext(); )
429     {
430       PredicateSemantics predicate = (PredicateSemantics)iter.next();
431       addFilterGui(predicate, filterListPanel);
432     }
433     
434     dialog.setSize(750, 300);
435     
436     return dialog;
437   }
438   
439   
440   private void addFilterGui(
441     PredicateSemantics initialPredicate,
442     final JPanel panel)
443   {
444     SearchParameters searchParams;
445     ComboBoxItem initialFieldItem;
446     if (initialPredicate instanceof SearchFieldPredicateSemantics)
447     {
448       SearchFieldPredicateSemantics searchField = (SearchFieldPredicateSemantics)initialPredicate;
449       initialFieldItem = ComboBoxItem.findItem(searchField.getFieldName(), mainTitleFieldItem);
450       searchParams = searchField.getSearchParameters();
451     }
452     else if (initialPredicate instanceof SearchBodyPredicateSemantics)
453     {
454       SearchBodyPredicateSemantics searchBody = (SearchBodyPredicateSemantics)initialPredicate;
455       initialFieldItem = ComboBoxItem.findItem(searchBody.getPartConstraint(), bodyFieldItem);
456       searchParams = searchBody.getSearchParameters();
457     }
458     else
459     {
460       initialFieldItem = mainTitleFieldItem;
461       searchParams = new SearchParameters(SearchParameters.EQUALS, "",
462         SearchParameters.PRIMARY_STRENGTH);
463     }
464     
465     JComboBox fieldCombo = new JComboBox(new ComboBoxItem[]{
466       mainTitleFieldItem, authorFieldItem, commentFieldItem, copyrightFieldItem,
467       altTitlesFieldItem, keywordsFieldItem, bodyFieldItem, firstLineFieldItem});
468     fieldCombo.setSelectedItem(initialFieldItem);
469     JComboBox positionCombo = new JComboBox(new ComboBoxItem[]{
470       containsPositionItem, startsWithPositionItem, endsWithPositionItem, equalsPositionItem});
471     positionCombo.setSelectedItem(ComboBoxItem.findItem(
472       searchParams.getPositionConstraint(), containsPositionItem));
473     JComboBox strengthCombo = new JComboBox(new ComboBoxItem[]{
474       primaryStrengthItem, secondaryStrengthItem, tertiaryStrengthItem});
475     strengthCombo.setSelectedItem(ComboBoxItem.findItem(
476       searchParams.getStrength(), primaryStrengthItem));
477     JTextField textField = new JTextField(searchParams.getText());
478     final JButton deleteButton = new JButton(STR_Search_DeleteButton);
479     
480     deleteButton.addActionListener(
481       new ActionListener()
482       {
483         public void actionPerformed(
484           ActionEvent ev)
485         {
486           int index = SwingUtils.getIndexOfComponent(panel, deleteButton)-4;
487           for (int i=0; i<5; ++i)
488           {
489             panel.remove(index);
490           }
491           panel.revalidate();
492         }
493       });
494     
495     GridBagConstraints gbc = new GridBagConstraints();
496     gbc.weighty = 1;
497     gbc.weightx = 0;
498     gbc.fill = GridBagConstraints.HORIZONTAL;
499     gbc.insets = new Insets(3, 3, 3, 3);
500     
501     gbc.gridx = 0;
502     panel.add(fieldCombo, gbc);
503     gbc.gridx = 1;
504     panel.add(positionCombo, gbc);
505     gbc.gridx = 2;
506     panel.add(strengthCombo, gbc);
507     gbc.gridx = 3;
508     gbc.weightx = 1;
509     panel.add(textField, gbc);
510     gbc.gridx = 4;
511     gbc.weightx = 0;
512     gbc.insets = new Insets(3, 8, 3, 3);
513     panel.add(deleteButton, gbc);
514   }
515   
516   
517   private void fillInPredicates(
518     JPanel panel)
519   {
520     predicates_ = new ArrayList();
521     for (int i=0; i<panel.getComponentCount(); i+=5)
522     {
523       JComboBox fieldCombo = (JComboBox)panel.getComponent(i);
524       Object fieldItem = ((ComboBoxItem)fieldCombo.getSelectedItem()).getData();
525       JComboBox positionCombo = (JComboBox)panel.getComponent(i+1);
526       SearchParameters.PositionConstraint positionItem = (SearchParameters.PositionConstraint)
527         ((ComboBoxItem)positionCombo.getSelectedItem()).getData();
528       JComboBox strengthCombo = (JComboBox)panel.getComponent(i+2);
529       SearchParameters.Strength strengthItem = (SearchParameters.Strength)
530         ((ComboBoxItem)strengthCombo.getSelectedItem()).getData();
531       JTextField textField = (JTextField)panel.getComponent(i+3);
532       String text = textField.getText();
533       
534       SearchParameters params = new SearchParameters(positionItem, text, strengthItem);
535       if (fieldItem instanceof String)
536       {
537         predicates_.add(new SearchFieldPredicateSemantics.DefaultImplementation(
538           (String)fieldItem, params));
539       }
540       else
541       {
542         predicates_.add(new SearchBodyPredicateSemantics.DefaultImplementation(
543           songUtils_, (SearchBodyPredicateSemantics.PartConstraint)fieldItem, params));
544       }
545     }
546   }
547   
548   
549   /*package*/ void doFindAllSongs()
550   {
551     listsImpl_.setFilter(new TruePredicateSemantics.DefaultImplementation());
552   }
553 }