KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > swingwtx > custom > JLookupPopup


1 /*
2    SwingWT
3    Copyright(c)2003-2004, R. Rawson-Tetley
4
5    For more information on distributing and using this program, please
6    see the accompanying "COPYING" file.
7
8    Contact me by electronic mail: bobintetley@users.sourceforge.net
9
10    $Log: JLookupPopup.java,v $
11    Revision 1.6 2004/02/23 12:11:21 bobintetley
12    JScrollPane bug fixed, tabbing in JTextArea fixed
13
14    Revision 1.5 2004/02/23 11:15:52 bobintetley
15    Fixes to popup
16
17    Revision 1.4 2004/02/20 22:43:16 bobintetley
18    Textfield accessor
19
20    Revision 1.3 2004/02/20 22:40:45 bobintetley
21    requestFocus() mapping
22
23    Revision 1.2 2004/02/20 22:38:59 bobintetley
24    Overridden focus methods
25
26    Revision 1.1 2004/02/20 13:56:58 bobintetley
27    JLookupPopup - A high speed alternative to JComboBox
28
29
30 */

31 package swingwtx.custom;
32
33 import swingwt.awt.*;
34 import swingwt.awt.event.*;
35 import swingwtx.swing.*;
36 import swingwtx.swing.event.*;
37
38 import java.util.*;
39
40 /**
41  * Very similar to JComboBox, this component is an uneditable text
42  * field with a button instead to popup a list of selectable items.
43  *
44  * A field at the top of the popup allows text searching.
45  * In addition, hotkeys in the text field allow searching like
46  * a combo box.
47  *
48  * I have designed this as a fast alternative for JComboBox as I
49  * discovered JComboBox performs very poorly under Linux/GTK2 with
50  * 200+ objects
51  *
52  * @author Robin Rawson-Tetley
53  */

54 public class JLookupPopup extends JPanel {
55     
56     /** The list of selectable objects */
57     protected Vector items = new Vector();
58     /** Popup menu events */
59     protected Vector popupListeners = new Vector();
60     /** Item events */
61     protected Vector itemListeners = new Vector();
62     
63     protected JTextField text = new JTextField();
64     protected JButton button = new JButton("...");
65     protected int selectedIndex = -1;
66     
67     /** Creates a new JLookupPopup */
68     public JLookupPopup() {
69         super();
70         setLayout(new BorderLayout());
71         
72         // Initialise text
73
text.addKeyListener(new KeyAdapter() {
74             public void keyPressed(KeyEvent e) {
75                 if (e.getKeyCode() == 16777218) {
76                     nextItem(); // Go the next item with cursor down
77
e.consume();
78                 }
79                 else if (e.getKeyCode() == 16777217) {
80                     previousItem(); // Go to the previous item with cursor up
81
e.consume();
82                 }
83                 else if (e.getKeyChar() == ' ') {
84                     buttonPressed(); // If space is pressed, pretend the button was hit
85
e.consume();
86                 }
87                 else {
88                     alphaSearchItem(e.getKeyChar());// Otherwise, try and find a match for the key char pressed
89
e.consume();
90                 }
91             }
92         });
93         
94         // Initialise button
95
button.addActionListener(new ActionListener() {
96             public void actionPerformed(ActionEvent e) {
97                 buttonPressed();
98             }
99         });
100         
101         // Add the components
102
add(text, BorderLayout.CENTER);
103         add(button, BorderLayout.EAST);
104     }
105     
106     protected final static int CANCELED = 0;
107     protected final static int INVISIBLE = 1;
108     protected final static int VISIBLE = 2;
109     
110     public void addFocusListener(FocusListener l) {
111         text.addFocusListener(l);
112     }
113     public void removeFocusListener(FocusListener l) {
114         text.removeFocusListener(l);
115     }
116     public void addKeyListener(KeyListener l) {
117         text.addKeyListener(l);
118     }
119     public void removeKeyListener(KeyListener l) {
120         text.removeKeyListener(l);
121     }
122     public void addPopupMenuListener(PopupMenuListener l) {
123         popupListeners.add(l);
124     }
125     
126     public void removePopupMenuListener(PopupMenuListener l) {
127         popupListeners.remove(l);
128     }
129     
130     public void addItemListener(ItemListener l) {
131         itemListeners.add(l);
132     }
133     
134     public void removeItemListener(ItemListener l) {
135         itemListeners.remove(l);
136     }
137     
138     public void processPopupMenuEvent(int id) {
139         Iterator i = popupListeners.iterator();
140         PopupMenuEvent e = new PopupMenuEvent(this);
141         while (i.hasNext()) {
142             PopupMenuListener l = (PopupMenuListener) i.next();
143             switch(id) {
144                 case CANCELED: l.popupMenuCanceled(e); break;
145                 case INVISIBLE: l.popupMenuWillBecomeInvisible(e); break;
146                 case VISIBLE: l.popupMenuWillBecomeVisible(e); break;
147             }
148         }
149     }
150     
151     public void processItemEvent(ItemEvent e) {
152         Iterator i = itemListeners.iterator();
153         while (i.hasNext()) {
154             ItemListener l = (ItemListener) i.next();
155             l.itemStateChanged(e);
156         }
157     }
158     
159     /** Add a selection to the list */
160     public void addItem(Object JavaDoc item) {
161         items.add(item);
162         // If this is the first item, auto select it
163
if (items.size() == 1)
164             setSelectedIndex(0);
165     }
166     
167     /** Remove a selection from the list */
168     public void removeItem(Object JavaDoc item) {
169         items.remove(item);
170     }
171     
172     /** Returns the selected item by it's index */
173     public int getSelectedIndex() {
174         return selectedIndex;
175     }
176     /** Sets the selected item in the list */
177     public void setSelectedIndex(int i) {
178         selectedIndex = i;
179         text.setText( items.get(i).toString() );
180     }
181     /**
182      * Sets the selected item
183      */

184     public void setSelectedItem(Object JavaDoc o) {
185         text.setText(o.toString());
186         selectedIndex = items.indexOf(o);
187     }
188     /**
189      * Returns the selected item
190      */

191     public Object JavaDoc getSelectedItem() {
192         return items.get(selectedIndex);
193     }
194     /** Returns the number of items in the list */
195     public int getItemCount() {
196        return items.size();
197     }
198     /** Returns the item at a given position */
199     public Object JavaDoc getItemAt(int index) {
200         return items.get(index);
201     }
202     /** Clears the list */
203     public void removeAllItems() {
204         items.removeAllElements();
205         text.setText("");
206         selectedIndex = -1;
207     }
208     /**
209      * Sets whether the lookup is enabled
210      */

211     public void setEnabled(boolean b) {
212         text.setEnabled(b);
213         button.setEnabled(b);
214     }
215     /**
216      * Returns true if the lookup is enabled
217      */

218     public boolean isEnabled() {
219         return button.isEnabled();
220     }
221     /** Returns the tooltip text for the component */
222     public String JavaDoc getToolTipText() {
223         return text.getToolTipText();
224     }
225     /** Sets the tooltiptext for the component */
226     public void setToolTipText(String JavaDoc tip) {
227         text.setToolTipText(tip);
228     }
229     
230     /** We don't care for this component - it just keeps compatibility with JComboBox */
231     public void setMaximumRowCount(int i) {}
232     
233     /**
234      * Gets called when the user presses the button. The
235      * dialog should be popped up to prompt the user for
236      * a new selection.
237      */

238     protected void buttonPressed() {
239         new LookupPopup(this);
240     }
241     
242     protected void previousItem() {
243         // Do nothing if no items
244
if (items.size() == 0) return;
245         // If nothing selected, go to the first
246
if (getSelectedIndex() == -1)
247             setSelectedIndex(0);
248         if (getSelectedIndex() > 0)
249             setSelectedIndex(getSelectedIndex() - 1);
250     }
251     protected void nextItem() {
252         // Do nothing if no items
253
if (items.size() == 0) return;
254         // If nothing selected, go to the first
255
if (getSelectedIndex() == -1)
256             setSelectedIndex(0);
257         if (getSelectedIndex() < (items.size() - 1))
258             setSelectedIndex(getSelectedIndex() + 1);
259     }
260     
261     /**
262      * Performs an alpha search for the next item based
263      * on the key pressed
264      */

265     protected void alphaSearchItem(char cs) {
266         
267         // See what's already selected - this way we can cycle
268
// up the list like Swing does.
269
int currentlySelected = getSelectedIndex();
270
271         // The current character we are dealing with
272
String JavaDoc curChar = "";
273         if (currentlySelected != -1)
274             curChar = getSelectedItem().toString().substring(0, 1).toLowerCase();
275
276         boolean foundMatch = false;
277
278         for (int i = 0; i < items.size(); i++) {
279             String JavaDoc s = items.get(i).toString();
280             // This item start with the same letter?
281
if (s.substring(0, 1).toLowerCase().equals(new String JavaDoc(new char[] { cs }).toLowerCase())) {
282
283                 // Was the last keystroke on this letter? If so, the index must be higher
284
if (curChar.equals(new String JavaDoc(new char[] { cs }).toLowerCase()))
285                     i = currentlySelected + 1;
286
287                 // If we've run out of letters, don't do anything
288
if (i >= items.size())
289                     break;
290
291                 // Now that we've moved the match up, make sure the letters still
292
// match - if they don't, then we've gone too far - don't do
293
// anything
294
if (!items.get(i).toString().substring(0, 1).toLowerCase().equals(new String JavaDoc(new char[] { cs }).toLowerCase()))
295                     break;
296                 
297                 // We have a match and it's ok - set it and finish
298
setSelectedIndex(i);
299                 break;
300                 
301             }
302         }
303     }
304
305     public void requestFocus() {
306         text.requestFocus();
307     }
308
309     public void grabFocus() {
310     text.grabFocus();
311     }
312
313     public JTextField getJTextField() {
314     return text;
315     }
316     
317     /**
318      * The popup form. This consists of
319      * a dialog with a search box, a list of
320      * items, Ok/Cancel buttons and a progress
321      * bar to show it's fill progress (it opens
322      * immediately and shows how far it has gotten
323      * filling the list).
324      *
325      * Hitting ok updates the currently selected
326      * item in the many control
327      *
328      * @author Robin Rawson-Tetley
329      */

330     private class LookupPopup extends JFrame {
331         
332         private JLookupPopup popup = null;
333         private JList lst = null;
334         
335         public LookupPopup(JLookupPopup selector) {
336             
337             popup = selector;
338             
339             // Create the list
340

341             SwingUtilities.invokeSync( new Runnable JavaDoc() {
342                 public void run() {
343                     
344                     lst = new JList(popup.items);
345                     lst.addMouseListener( new MouseAdapter() {
346                         public void mouseClicked(MouseEvent e) {
347                             if (e.getClickCount() == 2)
348                                 btnOkPressed();
349                         }
350                     });
351
352                     // Buttons
353
JButton btnOk = new JButton("Ok");
354                     btnOk.setMnemonic('o');
355                     btnOk.addActionListener(new ActionListener() {
356                         public void actionPerformed(ActionEvent e) {
357                             btnOkPressed();
358                         }
359                     });
360
361                     JButton btnCancel = new JButton("Cancel");
362                     btnCancel.setMnemonic('c');
363                     btnCancel.addActionListener(new ActionListener() {
364                         public void actionPerformed(ActionEvent e) {
365                             btnCancelPressed();
366                         }
367                     });
368
369                     JPanel pnlButtons = new JPanel();
370                     pnlButtons.setLayout(new FlowLayout());
371                     pnlButtons.add(btnOk);
372                     pnlButtons.add(btnCancel);
373
374                     getContentPane().setLayout(new BorderLayout());
375                     getContentPane().add(lst, BorderLayout.CENTER);
376                     getContentPane().add(pnlButtons, BorderLayout.SOUTH);
377                 }
378             });
379             
380             // Calculate the mouse position on screen.
381
int mouseX = SwingWTUtils.getDisplay().getCursorLocation().x;
382             int mouseY = SwingWTUtils.getDisplay().getCursorLocation().y;
383             Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
384             
385             // If the mouse position is greater than 400 pixels from the screen edge, then
386
// make it 400 pixels from the edge
387
if (mouseX > (screen.width - 400))
388                 mouseX = screen.width - 400;
389             if (mouseY > (screen.height - 400))
390                 mouseY = screen.height- 400;
391             
392             setSize(400, 400);
393             setLocation(mouseX, mouseY);
394             setTitle("Select");
395             
396             show();
397             
398             SwingUtilities.invokeIn(new Runnable JavaDoc() {
399                 public void run() {
400                     
401                     // Set focus to the list
402
lst.grabFocus();
403                     
404                     // Highlight the selection if there is one
405
if (popup.getSelectedIndex() != -1)
406                         lst.setSelectedIndex(popup.getSelectedIndex());
407                     
408                     // If the selection is offscreen - jump to it
409
((org.eclipse.swt.widgets.Table) lst.getPeer()).showSelection();
410                     
411                     // Fire events to say the popup was shown
412
popup.processPopupMenuEvent(JLookupPopup.VISIBLE);
413                 }
414             }, 100);
415             
416         }
417         
418         protected void btnOkPressed() {
419             popup.processItemEvent(new ItemEvent(popup, ItemEvent.DESELECTED, popup.getSelectedItem(), 0));
420             popup.setSelectedIndex(lst.getSelectedIndex());
421             dispose();
422             popup.processItemEvent(new ItemEvent(popup, ItemEvent.SELECTED, popup.getSelectedItem(), 0));
423             popup.processPopupMenuEvent(JLookupPopup.INVISIBLE);
424         }
425         protected void btnCancelPressed() {
426             popup.processPopupMenuEvent(JLookupPopup.CANCELED);
427             dispose();
428             popup.processPopupMenuEvent(JLookupPopup.INVISIBLE);
429         }
430         
431     }
432     
433 }
434
Popular Tags