KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > prefuse > util > ui > JSearchPanel


1 package prefuse.util.ui;
2
3 import java.awt.Color JavaDoc;
4 import java.awt.Dimension JavaDoc;
5 import java.awt.Font JavaDoc;
6 import java.awt.Graphics JavaDoc;
7 import java.awt.event.ActionEvent JavaDoc;
8 import java.awt.event.ActionListener JavaDoc;
9 import java.awt.event.MouseEvent JavaDoc;
10 import java.awt.event.MouseListener JavaDoc;
11
12 import javax.swing.BorderFactory JavaDoc;
13 import javax.swing.Box JavaDoc;
14 import javax.swing.BoxLayout JavaDoc;
15 import javax.swing.JComponent JavaDoc;
16 import javax.swing.JLabel JavaDoc;
17 import javax.swing.JPanel JavaDoc;
18 import javax.swing.JTextField JavaDoc;
19 import javax.swing.event.DocumentEvent JavaDoc;
20 import javax.swing.event.DocumentListener JavaDoc;
21 import javax.swing.text.Document JavaDoc;
22
23 import prefuse.Visualization;
24 import prefuse.data.Tuple;
25 import prefuse.data.event.TupleSetListener;
26 import prefuse.data.search.PrefixSearchTupleSet;
27 import prefuse.data.search.SearchTupleSet;
28 import prefuse.data.tuple.TupleSet;
29 import prefuse.util.ColorLib;
30
31 /**
32  * Swing component that enables keyword search over prefuse data tuples.
33  *
34  * @author <a HREF="http://jheer.org">jeffrey heer</a>
35  * @see prefuse.data.query.SearchQueryBinding
36  */

37 public class JSearchPanel extends JPanel JavaDoc
38     implements DocumentListener JavaDoc, ActionListener JavaDoc
39 {
40     private Object JavaDoc m_lock;
41     private SearchTupleSet m_searcher;
42
43     private JTextField JavaDoc m_queryF = new JTextField JavaDoc(15);
44     private JLabel JavaDoc m_resultL = new JLabel JavaDoc(" ");
45     private JLabel JavaDoc m_searchL = new JLabel JavaDoc("search >> ");
46     private Box JavaDoc m_sbox = new Box JavaDoc(BoxLayout.X_AXIS);
47
48     private String JavaDoc[] m_fields;
49     
50     private Color JavaDoc m_cancelColor = ColorLib.getColor(255,75,75);
51     
52     private boolean m_includeHitCount = false;
53     private boolean m_monitorKeys = false;
54     private boolean m_autoIndex = true;
55     
56     private boolean m_showBorder = true;
57     private boolean m_showCancel = true;
58
59     // ------------------------------------------------------------------------
60
// Free form constructors
61

62     /**
63      * Create a new JSearchPanel.
64      * @param search the search tuple set conducting the searches
65      * @param field the data field being searched
66      */

67     public JSearchPanel(SearchTupleSet search, String JavaDoc field) {
68         this(search, field, false);
69     }
70     
71     /**
72      * Create a new JSearchPanel.
73      * @param search the search tuple set conducting the searches
74      * @param field the data field being searched
75      * @param monitorKeystrokes indicates if each keystroke event should result
76      * in a new search being issued (true) or if searches should only be
77      * initiated by hitting the enter key (false)
78      */

79     public JSearchPanel(SearchTupleSet search, String JavaDoc field,
80             boolean monitorKeystrokes)
81     {
82         this(null, search, new String JavaDoc[] {field}, false, monitorKeystrokes);
83     }
84     
85     /**
86      * Create a new JSearchPanel.
87      * @param source the source set of tuples that should be searched over
88      * @param search the search tuple set conducting the searches
89      * @param fields the data fields being searched
90      * @param monitorKeystrokes indicates if each keystroke event should result
91      * in a new search being issued (true) or if searches should only be
92      * initiated by hitting the enter key (false)
93      */

94     public JSearchPanel(TupleSet source, SearchTupleSet search,
95             String JavaDoc[] fields, boolean autoIndex, boolean monitorKeystrokes)
96     {
97         m_lock = new Object JavaDoc();
98         m_fields = fields;
99         m_autoIndex = autoIndex;
100         m_monitorKeys = monitorKeystrokes;
101
102         m_searcher = ( search != null ? search : new PrefixSearchTupleSet() );
103         
104         init(source);
105     }
106     
107     // ------------------------------------------------------------------------
108
// Visualization-based constructors
109

110     /**
111      * Create a new JSearchPanel. The default search tuple set for the
112      * visualization will be used.
113      * @param vis the Visualization to search over
114      * @param field the data field being searched
115      */

116     public JSearchPanel(Visualization vis, String JavaDoc field) {
117         this(vis, Visualization.ALL_ITEMS, field, true);
118     }
119     
120     /**
121      * Create a new JSearchPanel. The default search tuple set for the
122      * visualization will be used.
123      * @param vis the Visualization to search over
124      * @param group the particular data group to search over
125      * @param field the data field being searched
126      */

127     public JSearchPanel(Visualization vis, String JavaDoc group, String JavaDoc field) {
128         this(vis, group, field, true);
129     }
130     
131     /**
132      * Create a new JSearchPanel. The default search tuple set for the
133      * visualization will be used.
134      * @param vis the Visualization to search over
135      * @param group the particular data group to search over
136      * @param field the data field being searched
137      * @param autoIndex indicates if items should be automatically
138      * indexed and unindexed as their membership in the source group
139      * changes.
140      */

141     public JSearchPanel(Visualization vis, String JavaDoc group, String JavaDoc field,
142             boolean autoIndex)
143     {
144         this(vis, group, Visualization.SEARCH_ITEMS,
145                 new String JavaDoc[] {field}, autoIndex, false);
146     }
147     
148     /**
149      * Create a new JSearchPanel. The default search tuple set for the
150      * visualization will be used.
151      * @param vis the Visualization to search over
152      * @param group the particular data group to search over
153      * @param field the data field being searched
154      * @param autoIndex indicates if items should be automatically
155      * indexed and unindexed as their membership in the source group
156      * changes.
157      * @param monitorKeystrokes indicates if each keystroke event should result
158      * in a new search being issued (true) or if searches should only be
159      * initiated by hitting the enter key (false)
160      */

161     public JSearchPanel(Visualization vis, String JavaDoc group, String JavaDoc field,
162             boolean autoIndex, boolean monitorKeystrokes)
163     {
164         this(vis, group, Visualization.SEARCH_ITEMS,
165                 new String JavaDoc[] {field}, autoIndex, true);
166     }
167     
168     /**
169      * Create a new JSearchPanel.
170      * @param vis the Visualization to search over
171      * @param group the particular data group to search over
172      * @param searchGroup the group name that resolves to the SearchTupleSet
173      * to use
174      * @param field the data field being searched
175      * @param autoIndex indicates if items should be automatically
176      * indexed and unindexed as their membership in the source group
177      * changes.
178      * @param monitorKeystrokes indicates if each keystroke event should result
179      * in a new search being issued (true) or if searches should only be
180      * initiated by hitting the enter key (false)
181      */

182     public JSearchPanel(Visualization vis, String JavaDoc group, String JavaDoc searchGroup,
183             String JavaDoc field, boolean autoIndex, boolean monitorKeystrokes)
184     {
185         this(vis, group, searchGroup, new String JavaDoc[] {field}, autoIndex,
186                 monitorKeystrokes);
187     }
188     
189     /**
190      * Create a new JSearchPanel.
191      * @param vis the Visualization to search over
192      * @param group the particular data group to search over
193      * @param searchGroup the group name that resolves to the SearchTupleSet
194      * to use
195      * @param fields the data fields being searched
196      * @param autoIndex indicates if items should be automatically
197      * indexed and unindexed as their membership in the source group
198      * changes.
199      * @param monitorKeystrokes indicates if each keystroke event should result
200      * in a new search being issued (true) or if searches should only be
201      * initiated by hitting the enter key (false)
202      */

203     public JSearchPanel(Visualization vis, String JavaDoc group, String JavaDoc searchGroup,
204             String JavaDoc[] fields, boolean autoIndex, boolean monitorKeystrokes)
205     {
206         m_lock = vis;
207         m_fields = fields;
208         m_autoIndex = autoIndex;
209         m_monitorKeys = monitorKeystrokes;
210
211         TupleSet search = vis.getGroup(searchGroup);
212
213         if ( search != null ) {
214             if ( search instanceof SearchTupleSet ) {
215                 m_searcher = (SearchTupleSet)search;
216             } else {
217                 throw new IllegalStateException JavaDoc(
218                     "Search focus set not instance of SearchTupleSet!");
219             }
220         } else {
221             m_searcher = new PrefixSearchTupleSet();
222             vis.addFocusGroup(searchGroup, m_searcher);
223         }
224         
225         init(vis.getGroup(group));
226     }
227
228     // ------------------------------------------------------------------------
229
// Initialization
230

231     private void init(TupleSet source) {
232         if ( m_autoIndex && source != null ) {
233             // index everything already there
234
for ( int i=0; i < m_fields.length; i++ )
235                 m_searcher.index(source.tuples(), m_fields[i]);
236             
237             // add a listener to dynamically build search index
238
source.addTupleSetListener(new TupleSetListener() {
239                 public void tupleSetChanged(TupleSet tset,
240                         Tuple[] add, Tuple[] rem)
241                 {
242                     if ( add != null ) {
243                         for ( int i=0; i<add.length; ++i ) {
244                             for ( int j=0; j<m_fields.length; j++ )
245                                 m_searcher.index(add[i], m_fields[j]);
246                         }
247                     }
248                     if ( rem != null && m_searcher.isUnindexSupported() ) {
249                         for ( int i=0; i<rem.length; ++i ) {
250                             for ( int j=0; j<m_fields.length; j++ )
251                                 m_searcher.unindex(rem[i], m_fields[j]);
252                         }
253                     }
254                 }
255             });
256         }
257         
258         m_queryF.addActionListener(this);
259         if ( m_monitorKeys )
260             m_queryF.getDocument().addDocumentListener(this);
261         m_queryF.setMaximumSize(new Dimension JavaDoc(400, 100));
262         m_queryF.setPreferredSize(new Dimension JavaDoc(200, 20));
263         m_queryF.setBorder(null);
264         setBackground(Color.WHITE);
265         initUI();
266     }
267     
268     private void initUI() {
269         this.removeAll();
270         this.setLayout(new BoxLayout JavaDoc(this, BoxLayout.X_AXIS));
271         
272         m_sbox.removeAll();
273         m_sbox.add(Box.createHorizontalStrut(3));
274         m_sbox.add(m_queryF);
275         m_sbox.add(Box.createHorizontalStrut(3));
276         if ( m_showCancel ) {
277             m_sbox.add(new CancelButton());
278             m_sbox.add(Box.createHorizontalStrut(3));
279         }
280         if ( m_showBorder )
281             m_sbox.setBorder(BorderFactory.createLineBorder(getForeground()));
282         else
283             m_sbox.setBorder(null);
284         m_sbox.setMaximumSize(new Dimension JavaDoc(400, 100));
285         m_sbox.setPreferredSize(new Dimension JavaDoc(171, 20));
286         
287         Box JavaDoc b = new Box JavaDoc(BoxLayout.X_AXIS);
288         if ( m_includeHitCount ) {
289             b.add(m_resultL);
290             b.add(Box.createHorizontalStrut(10));
291             //b.add(Box.createHorizontalGlue());
292
}
293         b.add(m_searchL);
294         b.add(Box.createHorizontalStrut(3));
295         b.add(m_sbox);
296         
297         this.add(b);
298     }
299     
300     // ------------------------------------------------------------------------
301

302     /**
303      * Request the keyboard focus for this component.
304      */

305     public void requestFocus() {
306         this.m_queryF.requestFocus();
307     }
308     
309     /**
310      * Set the lock, an object to synchronize on while issuing queries.
311      * @param lock the synchronization lock
312      */

313     public void setLock(Object JavaDoc lock) {
314         m_lock = lock;
315     }
316     
317     /**
318      * Indicates if the component should show the number of search results.
319      * @param b true to show the result count, false to hide it
320      */

321     public void setShowResultCount(boolean b) {
322         this.m_includeHitCount = b;
323         initUI();
324         validate();
325     }
326     
327     /**
328      * Indicates if the component should show a border around the text field.
329      * @param b true to show the text field border, false to hide it
330      */

331     public void setShowBorder(boolean b) {
332         m_showBorder = b;
333         initUI();
334         validate();
335     }
336     
337     /**
338      * Indicates if the component should show the cancel query button.
339      * @param b true to show the cancel query button, false to hide it
340      */

341     public void setShowCancel(boolean b) {
342         m_showCancel = b;
343         initUI();
344         validate();
345     }
346     
347     /**
348      * Update the search results based on the current query.
349      */

350     protected void searchUpdate() {
351         String JavaDoc query = m_queryF.getText();
352         synchronized ( m_lock ) {
353             m_searcher.search(query);
354             if ( m_searcher.getQuery().length() == 0 )
355                 m_resultL.setText(null);
356             else {
357                 int r = m_searcher.getTupleCount();
358                 m_resultL.setText(r + " match" + (r==1?"":"es"));
359             }
360         }
361     }
362     
363     /**
364      * Set the query string in the text field.
365      * @param query the query string to use
366      */

367     public void setQuery(String JavaDoc query) {
368         Document JavaDoc d = m_queryF.getDocument();
369         d.removeDocumentListener(this);
370         m_queryF.setText(query);
371         if ( m_monitorKeys )
372             d.addDocumentListener(this);
373         searchUpdate();
374     }
375     
376     /**
377      * Get the query string in the text field.
378      * @return the current query string
379      */

380     public String JavaDoc getQuery() {
381         return m_queryF.getText();
382     }
383     
384     /**
385      * Set the fill color of the cancel 'x' button that appears
386      * when the button has the mouse pointer over it.
387      * @param c the cancel color
388      */

389     public void setCancelColor(Color JavaDoc c) {
390         m_cancelColor = c;
391     }
392     
393     /**
394      * @see java.awt.Component#setBackground(java.awt.Color)
395      */

396     public void setBackground(Color JavaDoc bg) {
397         super.setBackground(bg);
398         if ( m_queryF != null ) m_queryF.setBackground(bg);
399         if ( m_resultL != null ) m_resultL.setBackground(bg);
400         if ( m_searchL != null ) m_searchL.setBackground(bg);
401     }
402     
403     /**
404      * @see java.awt.Component#setForeground(java.awt.Color)
405      */

406     public void setForeground(Color JavaDoc fg) {
407         super.setForeground(fg);
408         if ( m_queryF != null ) {
409             m_queryF.setForeground(fg);
410             m_queryF.setCaretColor(fg);
411         }
412         if ( m_resultL != null ) m_resultL.setForeground(fg);
413         if ( m_searchL != null ) m_searchL.setForeground(fg);
414         if ( m_sbox != null && m_showBorder )
415             m_sbox.setBorder(BorderFactory.createLineBorder(fg));
416     }
417     
418     /**
419      * @see javax.swing.JComponent#setOpaque(boolean)
420      */

421     public void setOpaque(boolean opaque) {
422         super.setOpaque(opaque);
423         if ( m_queryF != null ) {
424             m_queryF.setOpaque(opaque);
425         }
426         if ( m_resultL != null ) m_resultL.setOpaque(opaque);
427         if ( m_searchL != null ) m_searchL.setOpaque(opaque);
428     }
429
430     /**
431      * @see java.awt.Component#setFont(java.awt.Font)
432      */

433     public void setFont(Font JavaDoc f) {
434         super.setFont(f);;
435         if ( m_queryF != null ) m_queryF.setFont(f);
436         if ( m_resultL != null ) m_resultL.setFont(f);
437         if ( m_searchL != null ) m_searchL.setFont(f);
438     }
439     
440     /**
441      * Set the label text used on this component.
442      * @param text the label text, use null to show no label
443      */

444     public void setLabelText(String JavaDoc text) {
445         m_searchL.setText(text);
446     }
447     
448     
449     /**
450      * @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
451      */

452     public void changedUpdate(DocumentEvent JavaDoc e) {
453         searchUpdate();
454     }
455     /**
456      * @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.DocumentEvent)
457      */

458     public void insertUpdate(DocumentEvent JavaDoc e) {
459         searchUpdate();
460     }
461     /**
462      * @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.DocumentEvent)
463      */

464     public void removeUpdate(DocumentEvent JavaDoc e) {
465         searchUpdate();
466     }
467
468     /**
469      * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
470      */

471     public void actionPerformed(ActionEvent JavaDoc e) {
472         Object JavaDoc src = e.getSource();
473         if ( src == m_queryF ) {
474             searchUpdate();
475         }
476     }
477
478     /**
479      * A button depicted as an "X" that allows users to cancel the current query
480      * and clear the query field.
481      */

482     public class CancelButton extends JComponent JavaDoc implements MouseListener JavaDoc {
483
484         private boolean hover = false;
485         private int[] outline = new int[] {
486             0,0, 2,0, 4,2, 5,2, 7,0, 9,0, 9,2, 7,4, 7,5, 9,7, 9,9,
487             7,9, 5,7, 4,7, 2,9, 0,9, 0,7, 2,5, 2,4, 0,2, 0,0
488         };
489         private int[] fill = new int[] {
490             1,1,8,8, 1,2,7,8, 2,1,8,7, 7,1,1,7, 8,2,2,8, 1,8,8,1
491         };
492         
493         public CancelButton() {
494             // set button size
495
Dimension JavaDoc d = new Dimension JavaDoc(10,10);
496             this.setPreferredSize(d);
497             this.setMinimumSize(d);
498             this.setMaximumSize(d);
499             
500             // prevent the widget from getting the keyboard focus
501
this.setFocusable(false);
502             
503             // add callbacks
504
this.addMouseListener(this);
505         }
506         
507         public void paintComponent(Graphics JavaDoc g) {
508             if ( hover ) { // draw fill
509
g.setColor(m_cancelColor);
510                 for ( int i=0; i+3 < fill.length; i+=4 ) {
511                     g.drawLine(fill[i],fill[i+1],fill[i+2],fill[i+3]);
512                 }
513             }
514             g.setColor(JSearchPanel.this.getForeground());
515             for ( int i=0; i+3 < outline.length; i+=2 ) {
516                 g.drawLine(outline[i], outline[i+1],
517                            outline[i+2], outline[i+3]);
518             }
519         }
520
521         public void mouseClicked(MouseEvent JavaDoc arg0) {
522             setQuery(null);
523         }
524
525         public void mousePressed(MouseEvent JavaDoc arg0) {
526         }
527
528         public void mouseReleased(MouseEvent JavaDoc arg0) {
529         }
530
531         public void mouseEntered(MouseEvent JavaDoc arg0) {
532             hover = true;
533             repaint();
534         }
535
536         public void mouseExited(MouseEvent JavaDoc arg0) {
537             hover = false;
538             repaint();
539         }
540         
541     } // end of class CancelButton
542

543 } // end of class JSearchPanel
544
Popular Tags