KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > xam > ui > search > SearchFieldPanel


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.xml.xam.ui.search;
21
22 import java.awt.Color JavaDoc;
23 import java.awt.event.ActionEvent JavaDoc;
24 import java.awt.event.ActionListener JavaDoc;
25 import java.awt.event.FocusEvent JavaDoc;
26 import java.awt.event.FocusListener JavaDoc;
27 import java.awt.event.KeyEvent JavaDoc;
28 import java.awt.event.KeyListener JavaDoc;
29 import java.awt.event.MouseEvent JavaDoc;
30 import java.awt.event.MouseListener JavaDoc;
31 import java.util.Collection JavaDoc;
32 import java.util.Collections JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Map JavaDoc;
37 import javax.swing.AbstractButton JavaDoc;
38 import javax.swing.ButtonModel JavaDoc;
39 import javax.swing.JCheckBoxMenuItem JavaDoc;
40 import javax.swing.JMenuItem JavaDoc;
41 import javax.swing.JPanel JavaDoc;
42 import javax.swing.JRadioButtonMenuItem JavaDoc;
43 import javax.swing.JSeparator JavaDoc;
44 import javax.swing.UIManager JavaDoc;
45 import javax.swing.event.DocumentEvent JavaDoc;
46 import javax.swing.event.DocumentListener JavaDoc;
47 import javax.swing.event.EventListenerList JavaDoc;
48 import javax.swing.event.PopupMenuEvent JavaDoc;
49 import javax.swing.event.PopupMenuListener JavaDoc;
50 import org.openide.util.NbBundle;
51 import org.openide.util.WeakListeners;
52
53 /**
54  * Interface for searching an XML document.
55  *
56  * @author Nathan Fiedler
57  */

58 public class SearchFieldPanel extends JPanel JavaDoc
59         implements ActionListener JavaDoc, DocumentListener JavaDoc, FocusListener JavaDoc,
60         KeyListener JavaDoc, MouseListener JavaDoc, PopupMenuListener JavaDoc {
61     /** Color used to indicate no match. */
62     private static final Color JavaDoc MATCH_FAILED_COLOR = new Color JavaDoc(255, 102, 102);
63     /** silence compiler warnings */
64     static final long serialVersionUID = 1L;
65     /** A mapping of action command name to SearchProvider instances. */
66     private Map JavaDoc<String JavaDoc, SearchProvider> buttonProviderMap;
67     /** If true, the text field is expecting to get input from the user,
68      * otherwise it is displaying the search type label. */

69     private boolean expectingInput;
70     /** Starts the search from the selected component. */
71     private JCheckBoxMenuItem JavaDoc fromSelectedMenuItem;
72     /** Indicates if search phrase is a regular expression. */
73     private JCheckBoxMenuItem JavaDoc regexMenuItem;
74     /** List of search listeners. */
75     private EventListenerList JavaDoc searchListeners = new EventListenerList JavaDoc();
76
77     /**
78      * Creates new form SearchFieldPanel.
79      */

80     public SearchFieldPanel() {
81         initComponents();
82         typesButton.addActionListener(this);
83         searchTextField.addKeyListener(this);
84         searchTextField.addActionListener(this);
85         searchTextField.addFocusListener(this);
86         searchTextField.addMouseListener(this);
87         searchTextField.getDocument().addDocumentListener(this);
88         typesPopupMenu.addPopupMenuListener(this);
89         buttonProviderMap = new HashMap JavaDoc<String JavaDoc, SearchProvider>();
90     }
91
92     public void actionPerformed(ActionEvent JavaDoc e) {
93         Object JavaDoc src = e.getSource();
94         if (src == typesButton) {
95             typesPopupMenu.show(typesButton, 0, typesButton.getHeight());
96         } else if (src == searchTextField) {
97             fireSearchEvent(SearchEvent.Type.COMMENCED);
98             // Perform the search.
99
String JavaDoc text = searchTextField.getText();
100             if (text.length() > 0) {
101                 ButtonModel JavaDoc model = typeButtonGroup.getSelection();
102                 SearchProvider provider = buttonProviderMap.get(
103                         model.getActionCommand());
104                 boolean selected = fromSelectedMenuItem.isSelected();
105                 boolean regex = regexMenuItem.isSelected();
106                 Query query = new Query(text, selected, regex);
107                 try {
108                     List JavaDoc<Object JavaDoc> results = provider.search(query);
109                     if (results.isEmpty()) {
110                         indicateFailure();
111                     } else {
112                         clearFailure(false);
113                     }
114                     fireSearchComplete(results);
115                 } catch (SearchException se) {
116                     fireSearchFailed(se);
117                 }
118             } else {
119                 // Notify listeners that the search was empty.
120
List JavaDoc<Object JavaDoc> empty = Collections.emptyList();
121                 fireSearchComplete(empty);
122             }
123         } else if (src instanceof JMenuItem JavaDoc) {
124             if (!expectingInput) {
125                 // One of the serach type menu items was selected, need to
126
// update the search text field appropriately.
127
indicateSearchType();
128             } else {
129                 // Need to set the text field tooltip appropriately.
130
ButtonModel JavaDoc bm = typeButtonGroup.getSelection();
131                 SearchProvider sp = buttonProviderMap.get(bm.getActionCommand());
132                 searchTextField.setToolTipText(sp.getInputDescription());
133             }
134         }
135     }
136
137     /**
138      * Add the given search listener to this search interface. The listener
139      * will be notified when the user performs a search.
140      *
141      * @param l search listener.
142      */

143     public void addSearchListener(SearchListener l) {
144         searchListeners.add(SearchListener.class, l);
145     }
146
147     public void changedUpdate(DocumentEvent JavaDoc e) {
148     }
149
150     /**
151      * Reset the text field colors to their usual defaults.
152      *
153      * @param clear true to erase contents of text field, false to leave as-is.
154      */

155     private void clearFailure(boolean clear) {
156         Color JavaDoc color = UIManager.getDefaults().getColor("TextField.background");
157         setBackground(color);
158         searchTextField.setBackground(color);
159         color = UIManager.getDefaults().getColor("TextField.foreground");
160         searchTextField.setForeground(color);
161         if (clear) {
162             searchTextField.setText("");
163         }
164     }
165
166     /**
167      * Notify the search listeners that the search is complete.
168      *
169      * @return results list of search results.
170      */

171     protected void fireSearchComplete(List JavaDoc<Object JavaDoc> results) {
172         fireSearchEvent(new SearchEvent(this, SearchEvent.Type.FINISHED, results));
173     }
174
175     /**
176      * Notify the search listeners of a particular search event type.
177      *
178      * @param type search event type.
179      */

180     private void fireSearchEvent(SearchEvent.Type type) {
181         fireSearchEvent(new SearchEvent(this, type));
182     }
183
184     /**
185      * Notify the search listeners that the search failed.
186      *
187      * @return error the search exception that occurred.
188      */

189     protected void fireSearchFailed(SearchException error) {
190         fireSearchEvent(new SearchEvent(this, SearchEvent.Type.FAILED, error));
191     }
192
193     /**
194      * Notify the search listeners of a particular search event type.
195      */

196     private void fireSearchEvent(SearchEvent event) {
197         Object JavaDoc[] listeners = searchListeners.getListenerList();
198         SearchEvent.Type type = event.getType();
199         for (int ii = listeners.length - 2; ii >= 0; ii -= 2) {
200             if (listeners[ii] == SearchListener.class) {
201                 type.fireEvent(event, (SearchListener) listeners[ii + 1]);
202             }
203         }
204     }
205
206     public void focusGained(FocusEvent JavaDoc e) {
207         // Ignore focus changes due to switching between apps.
208
if (e.getSource() == searchTextField && !expectingInput) {
209             // Field is showing search type name, so clear it for user to
210
// enter input, otherwise it was user input, so leave it as-is.
211
clearFailure(true);
212             expectingInput = true;
213         }
214     }
215
216     public void focusLost(FocusEvent JavaDoc e) {
217         if (e.getSource() == searchTextField &&
218                 searchTextField.getText().length() == 0) {
219             clearFailure(false);
220             indicateSearchType();
221         }
222     }
223
224     /**
225      * Indicate that the user's query did not match anything.
226      */

227     private void indicateFailure() {
228         setBackground(MATCH_FAILED_COLOR);
229         searchTextField.setBackground(MATCH_FAILED_COLOR);
230         searchTextField.setForeground(Color.white);
231     }
232
233     /**
234      * Displays the search provider name in the text field in grey color.
235      */

236     private void indicateSearchType() {
237         // We are no longer expecting input from the user.
238
expectingInput = false;
239         ButtonModel JavaDoc bm = typeButtonGroup.getSelection();
240         if (bm == null) {
241             // No button is selected, most likely because there are no
242
// providers. Just have to wait for them to become available.
243
return;
244         }
245         SearchProvider provider = buttonProviderMap.get(bm.getActionCommand());
246         String JavaDoc name = provider.getDisplayName();
247         Color JavaDoc color = UIManager.getDefaults().getColor("textInactiveText");
248         searchTextField.setForeground(color);
249         searchTextField.setText(name);
250         searchTextField.setToolTipText(provider.getInputDescription());
251     }
252
253     public void insertUpdate(DocumentEvent JavaDoc e) {
254         // To ignore the "insert" performed by showing the search type,
255
// check if expectingInput is true or not. This was used to make
256
// the close button enable, but now the close button has moved.
257
}
258
259     public void keyPressed(KeyEvent JavaDoc e) {
260     }
261
262     public void keyReleased(KeyEvent JavaDoc e) {
263         if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
264             if (!expectingInput) {
265                 clearFailure(true);
266                 indicateSearchType();
267             }
268             fireSearchEvent(SearchEvent.Type.DISMISSED);
269             // Send the focus away from the text field.
270
typesButton.requestFocusInWindow();
271         }
272     }
273
274     public void keyTyped(KeyEvent JavaDoc e) {
275     }
276
277     public void mouseClicked(MouseEvent JavaDoc e) {
278     }
279
280     public void mouseEntered(MouseEvent JavaDoc e) {
281     }
282
283     public void mouseExited(MouseEvent JavaDoc e) {
284     }
285
286     public void mousePressed(MouseEvent JavaDoc e) {
287         // This handles the case where the user performs a quick-copy
288
// (on X Windows, select some text, then middle-click in a text field)
289
// and the text field is about to receive some text.
290
if (!expectingInput) {
291             clearFailure(true);
292             expectingInput = true;
293         }
294     }
295
296     public void mouseReleased(MouseEvent JavaDoc e) {
297     }
298
299     public void popupMenuWillBecomeVisible(PopupMenuEvent JavaDoc e) {
300         if (!expectingInput) {
301             clearFailure(true);
302         }
303     }
304
305     public void popupMenuWillBecomeInvisible(PopupMenuEvent JavaDoc e) {
306     }
307
308     public void popupMenuCanceled(PopupMenuEvent JavaDoc e) {
309     }
310
311     /**
312      * Make the search field ready for input from the user.
313      *
314      * @param clear if true, clear the input text field.
315      */

316     public void prepareForInput(boolean clear) {
317         clearFailure(false);
318         searchTextField.requestFocusInWindow();
319         if (clear) {
320             searchTextField.setText("");
321         } else {
322             searchTextField.selectAll();
323         }
324     }
325
326     /**
327      * Rmove the given search listener from this search interface.
328      *
329      * @param l search listener.
330      */

331     public void removeSearchListener(SearchListener l) {
332         searchListeners.remove(SearchListener.class, l);
333     }
334
335     public void removeUpdate(DocumentEvent JavaDoc e) {
336         if (e.getDocument().getLength() == 0) {
337             // Remove the error indicator colors.
338
clearFailure(false);
339         }
340     }
341
342     public void setEnabled(boolean enabled) {
343         super.setEnabled(enabled);
344         typesButton.setEnabled(enabled);
345         searchTextField.setEnabled(enabled);
346         if (!expectingInput) {
347             clearFailure(true);
348             indicateSearchType();
349         }
350     }
351
352     /**
353      * Set the collection of available SearchProvider implementations.
354      *
355      * @param providers collection of search providers, must be non-empty.
356      */

357     public void setProviders(Collection JavaDoc providers) {
358         if (providers.size() == 0) {
359             throw new IllegalArgumentException JavaDoc("providers must be non-empty");
360         }
361         buttonProviderMap.clear();
362         typesPopupMenu.removeAll();
363         Iterator JavaDoc iter = providers.iterator();
364         while (iter.hasNext()) {
365             SearchProvider provider = (SearchProvider) iter.next();
366             String JavaDoc name = provider.getDisplayName();
367             JRadioButtonMenuItem JavaDoc item = new JRadioButtonMenuItem JavaDoc(name);
368             item.addActionListener((ActionListener JavaDoc) WeakListeners.create(
369                     ActionListener JavaDoc.class, this, item));
370             item.setActionCommand(name);
371             item.setToolTipText(provider.getShortDescription());
372             buttonProviderMap.put(name, provider);
373             typeButtonGroup.add(item);
374             typesPopupMenu.add(item);
375         }
376         // Set the first item selected by default.
377
AbstractButton JavaDoc button = (AbstractButton JavaDoc) typesPopupMenu.getComponent(0);
378         button.setSelected(true);
379         if (!expectingInput) {
380             clearFailure(true);
381             indicateSearchType();
382         }
383
384         typesPopupMenu.add(new JSeparator JavaDoc());
385
386         if (fromSelectedMenuItem == null) {
387             fromSelectedMenuItem = new JCheckBoxMenuItem JavaDoc();
388             fromSelectedMenuItem.addActionListener((ActionListener JavaDoc) WeakListeners.create(
389                     ActionListener JavaDoc.class, this, fromSelectedMenuItem));
390             fromSelectedMenuItem.setText(NbBundle.getMessage(SearchFieldPanel.class,
391                     "LBL_SearchField_StartFromSelected"));
392         }
393         typesPopupMenu.add(fromSelectedMenuItem);
394
395         if (regexMenuItem == null) {
396             regexMenuItem = new JCheckBoxMenuItem JavaDoc();
397             regexMenuItem.addActionListener((ActionListener JavaDoc) WeakListeners.create(
398                     ActionListener JavaDoc.class, this, regexMenuItem));
399             regexMenuItem.setText(NbBundle.getMessage(SearchFieldPanel.class,
400                     "LBL_SearchField_RegularExpression"));
401         }
402         typesPopupMenu.add(regexMenuItem);
403     }
404
405     /** This method is called from within the constructor to
406      * initialize the form.
407      * WARNING: Do NOT modify this code. The content of this method is
408      * always regenerated by the Form Editor.
409      */

410     // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
411
private void initComponents() {
412         typesPopupMenu = new javax.swing.JPopupMenu JavaDoc();
413         typeButtonGroup = new javax.swing.ButtonGroup JavaDoc();
414         typesButton = new javax.swing.JButton JavaDoc();
415         searchTextField = new javax.swing.JTextField JavaDoc();
416
417         setBackground(javax.swing.UIManager.getDefaults().getColor("TextField.background"));
418         setBorder(javax.swing.BorderFactory.createEtchedBorder());
419         typesButton.setBackground(javax.swing.UIManager.getDefaults().getColor("TextField.background"));
420         typesButton.setIcon(new javax.swing.ImageIcon JavaDoc(getClass().getResource("/org/netbeans/modules/xml/xam/ui/search/search_types.png")));
421         typesButton.setToolTipText(java.util.ResourceBundle.getBundle("org/netbeans/modules/xml/xam/ui/search/Bundle").getString("HINT_SearchFieldPanel_Types"));
422         typesButton.setBorderPainted(false);
423         typesButton.setContentAreaFilled(false);
424         typesButton.setDisabledIcon(new javax.swing.ImageIcon JavaDoc(getClass().getResource("/org/netbeans/modules/xml/xam/ui/search/search_types_disabled.png")));
425         typesButton.setMargin(new java.awt.Insets JavaDoc(0, 0, 0, 0));
426
427         searchTextField.setColumns(15);
428         searchTextField.setBorder(null);
429
430         org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
431         this.setLayout(layout);
432         layout.setHorizontalGroup(
433             layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
434             .add(layout.createSequentialGroup()
435                 .add(typesButton)
436                 .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
437                 .add(searchTextField))
438         );
439         layout.setVerticalGroup(
440             layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
441             .add(typesButton)
442             .add(searchTextField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 22, Short.MAX_VALUE)
443         );
444     }// </editor-fold>//GEN-END:initComponents
445

446     // Variables declaration - do not modify//GEN-BEGIN:variables
447
private javax.swing.JTextField JavaDoc searchTextField;
448     private javax.swing.ButtonGroup JavaDoc typeButtonGroup;
449     private javax.swing.JButton JavaDoc typesButton;
450     private javax.swing.JPopupMenu JavaDoc typesPopupMenu;
451     // End of variables declaration//GEN-END:variables
452
}
453
Popular Tags