KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > wings > SComboBox


1 /*
2  * $Id: SComboBox.java,v 1.11 2005/04/08 15:05:18 blueshift Exp $
3  * Copyright 2000,2005 wingS development team.
4  *
5  * This file is part of wingS (http://www.j-wings.org).
6  *
7  * wingS is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2.1
10  * of the License, or (at your option) any later version.
11  *
12  * Please see COPYING for the complete licence.
13  */

14 package org.wings;
15
16 import org.wings.plaf.ComboBoxCG;
17
18 import javax.swing.*;
19 import javax.swing.event.EventListenerList JavaDoc;
20 import javax.swing.event.ListDataEvent JavaDoc;
21 import javax.swing.event.ListDataListener JavaDoc;
22 import java.awt.*;
23 import java.awt.event.ActionEvent JavaDoc;
24 import java.awt.event.ActionListener JavaDoc;
25 import java.awt.event.ItemEvent JavaDoc;
26 import java.awt.event.ItemListener JavaDoc;
27 import java.util.Vector JavaDoc;
28
29 /**
30  * @author <a HREF="mailto:hengels@mercatis.de">Holger Engels</a>
31  * @version $Revision: 1.11 $
32  * @see javax.swing.ComboBoxModel
33  * @see SListCellRenderer
34  */

35 public class SComboBox
36         extends SComponent
37         implements LowLevelEventListener, ListDataListener JavaDoc, ItemSelectable {
38     /**
39      * The model.
40      *
41      * @see javax.swing.ComboBoxModel
42      */

43     protected ComboBoxModel dataModel;
44
45     /**
46      * The renderer used for cell rendering each cell.
47      *
48      * @see SListCellRenderer
49      */

50     protected SListCellRenderer renderer;
51
52     /**
53      * how many rows are displayed in the popup window
54      */

55     protected int maximumRowCount = 8;
56
57     /**
58      * action command to fire
59      */

60     protected String JavaDoc actionCommand = "comboBoxChanged";
61
62
63     // do not initalize with null!
64
private final SCellRendererPane cellRendererPane = new SCellRendererPane();
65
66     /**
67      * This protected field is implementation specific. Do not access directly
68      * or override.
69      */

70     protected Object JavaDoc selectedItemReminder;
71
72     // Flag to ensure that infinite loops do not occur with ActionEvents.
73
private boolean firingActionEvent = false;
74
75     // Flag to ensure the we don't get multiple ActionEvents on item selection.
76
private boolean selectingItem = false;
77
78     private boolean delayEvent = false;
79     private boolean delayedEvent = false;
80
81     /**
82      * Creates a SComboBox that takes its items from an existing ComboBoxModel.
83      *
84      * @param model the ComboBoxModel that provides the displayed list of items
85      */

86     public SComboBox(ComboBoxModel model) {
87         setModel(model);
88     }
89
90     /**
91      * Creates a SComboBox that contains the elements in the specified array.
92      */

93     public SComboBox(final Object JavaDoc items[]) {
94         setModel(new DefaultComboBoxModel(items));
95     }
96
97     /**
98      * Creates a SComboBox that contains the elements in the specified Vector.
99      */

100     public SComboBox(Vector JavaDoc items) {
101         setModel(new DefaultComboBoxModel(items));
102     }
103
104     /**
105      * Creates a SComboBox with a default data model.
106      * The default data model is an empty list of objects.
107      * Use <code>addItem</code> to add items.
108      */

109     public SComboBox() {
110         setModel(new DefaultComboBoxModel());
111     }
112
113     /**
114      * Sets the data model that the SComboBox uses to obtain the list of items.
115      *
116      * @param model the ComboBoxModel that provides the displayed list of items
117      */

118     public void setModel(ComboBoxModel model) {
119         if (isDifferent(dataModel, model)) {
120             if (dataModel != null)
121                 dataModel.removeListDataListener(this);
122
123             dataModel = model;
124
125             dataModel.addListDataListener(this);
126         
127             // set the current selected item.
128
selectedItemReminder = dataModel.getSelectedItem();
129
130             reload();
131         }
132     }
133
134     /**
135      * Returns the data model currently used by the SComboBox.
136      *
137      * @return the ComboBoxModel that provides the displayed list of items
138      */

139     public final ComboBoxModel getModel() {
140         return dataModel;
141     }
142
143     /**
144      * Sets the maximum number of rows the SComboBox displays.
145      * If shown as a formComponent, this value is used for the <em>size</em>-attribute.
146      *
147      * @param count <em>size</em>-attribute
148      */

149     public void setMaximumRowCount(int count) {
150         if (maximumRowCount != count) {
151             maximumRowCount = count;
152
153             reload();
154         }
155     }
156
157     /**
158      * Returns the <em>size</em>-attribute
159      *
160      * @return the value used for the <em>size</em>-attribute
161      */

162     public int getMaximumRowCount() {
163         return maximumRowCount;
164     }
165
166     /**
167      * @param newRenderer the SListCellRenderer that displays the selected item.
168      */

169     public void setRenderer(SListCellRenderer newRenderer) {
170         if (isDifferent(renderer, newRenderer)) {
171             renderer = newRenderer;
172             reload();
173         }
174     }
175
176     /**
177      * @return the ListCellRenderer that displays the selected item.
178      */

179     public SListCellRenderer getRenderer() {
180         return renderer;
181     }
182
183     /**
184      * Sets the selected item in the SComboBox.
185      *
186      * @param object the list object to select
187      */

188     public void setSelectedItem(Object JavaDoc object) {
189         if (isDifferent(object, dataModel.getSelectedItem())) {
190
191             // Must toggle the state of this flag since this method
192
// call may result in ListDataEvents being fired.
193

194             if (!delayEvent) {
195                 selectingItem = true;
196                 dataModel.setSelectedItem(object);
197                 selectingItem = false;
198
199                 // if (isDifferent(selectedItemReminder , dataModel.getSelectedItem())) {
200
// in case a users implementation of ComboBoxModel
201
// doesn't fire a ListDataEvent when the selection
202
// changes.
203
selectedItemChanged();
204                 // }
205

206                 fireActionEvent();
207
208                 delayedEvent = false;
209             } else {
210                 delayedEvent = true;
211                 selectedItemReminder = object;
212             }
213
214             reload();
215         }
216     }
217
218     /**
219      * Returns the currently selected item.
220      *
221      * @return the currently selected list object from the data model
222      */

223     public Object JavaDoc getSelectedItem() {
224         return dataModel.getSelectedItem();
225     }
226
227     /**
228      * Selects the item at index <code>index</code>.
229      *
230      * @param index the item to be selected
231      */

232     public void setSelectedIndex(int index) {
233         int size = dataModel.getSize();
234
235         if (index == -1)
236             setSelectedItem(null);
237         else if (index < -1 || index >= size)
238             throw new IllegalArgumentException JavaDoc("setSelectedIndex: " + index +
239                     " out of bounds");
240         else
241             setSelectedItem(dataModel.getElementAt(index));
242     }
243
244     /**
245      * Returns the index of the currently selected item in the list.
246      *
247      * @return the selected item in the list or -1 if no item is selected or if
248      * the currently selected item (text field) is not in the list
249      */

250     public int getSelectedIndex() {
251         Object JavaDoc selected = dataModel.getSelectedItem();
252
253         if (selected == null) return -1;
254
255         for (int i = 0; i < getItemCount(); i++) {
256             if (selected.equals(getItemAt(i))) {
257                 return i;
258             }
259         }
260         return -1;
261     }
262
263     /**
264      * Adds an item to the item list.
265      *
266      * @param object the Object to add to the list
267      */

268     public void addItem(Object JavaDoc object) {
269         checkMutableComboBoxModel();
270         ((MutableComboBoxModel) dataModel).addElement(object);
271     }
272
273     /**
274      * Inserts an item into the item list at a given index.
275      *
276      * @param object the Object to add to the list
277      * @param index an int specifying the position at which to add the item
278      */

279     public void insertItemAt(Object JavaDoc object, int index) {
280         checkMutableComboBoxModel();
281         ((MutableComboBoxModel) dataModel).insertElementAt(object, index);
282     }
283
284     /**
285      * Removes an item from the item list.
286      * This method works only if the SComboBox uses the default data model.
287      * SComboBox uses the default data model when created with the empty constructor
288      * and no other model has been set.
289      *
290      * @param object the object to remove from the item list
291      */

292     public void removeItem(Object JavaDoc object) {
293         checkMutableComboBoxModel();
294         ((MutableComboBoxModel) dataModel).removeElement(object);
295     }
296
297     /**
298      * Removes the item at <code>index</code>
299      *
300      * @param index an int specifying the idex of the item to remove, where 0
301      * indicates the first item in the list
302      */

303     public void removeItemAt(int index) {
304         checkMutableComboBoxModel();
305         ((MutableComboBoxModel) dataModel).removeElementAt(index);
306     }
307
308     /**
309      * Removes all items from the item list.
310      */

311     public void removeAllItems() {
312         checkMutableComboBoxModel();
313         MutableComboBoxModel model = (MutableComboBoxModel) dataModel;
314         int size = model.getSize();
315
316         if (model instanceof DefaultComboBoxModel) {
317             ((DefaultComboBoxModel) model).removeAllElements();
318         } else {
319             for (int i = 0; i < size; ++i) {
320                 Object JavaDoc element = model.getElementAt(0);
321                 model.removeElement(element);
322             }
323         }
324     }
325
326     void checkMutableComboBoxModel() {
327         if (!(dataModel instanceof MutableComboBoxModel))
328             throw new RuntimeException JavaDoc("Cannot use this method with a non-Mutable data model.");
329     }
330
331
332     /** Selection **/
333
334     /**
335      * Adds an ItemListener. <code>listener</code> will receive an event when
336      * the selected item changes.
337      *
338      * @param listener the ItemListener that is to be notified
339      */

340     public void addItemListener(ItemListener JavaDoc listener) {
341         addEventListener(ItemListener JavaDoc.class, listener);
342     }
343
344     /**
345      * Removes an ItemListener
346      *
347      * @param listener the ItemListener to remove
348      */

349     public void removeItemListener(ItemListener JavaDoc listener) {
350         removeEventListener(ItemListener JavaDoc.class, listener);
351     }
352
353     /**
354      * Returns an array of all the ItemListener added to this SComboBox
355      *
356      * @return all ItemListener added or an empty array if no listeners are there
357      */

358     public ItemListener JavaDoc[] getItemListener() {
359         return (ItemListener JavaDoc[]) getListeners(ItemListener JavaDoc.class);
360     }
361
362     /**
363      * Adds an ActionListener. The listener will receive an action event
364      * when the user changed the selection.
365      *
366      * @param listener the ActionListener that is to be notified
367      */

368     public void addActionListener(ActionListener JavaDoc listener) {
369         addEventListener(ActionListener JavaDoc.class, listener);
370         reload();
371     }
372
373     /**
374      * Removes an ActionListener
375      *
376      * @param listener the ActionListener to remove
377      */

378     public void removeActionListener(ActionListener JavaDoc listener) {
379         removeEventListener(ActionListener JavaDoc.class, listener);
380         reload();
381     }
382
383     /**
384      * Returns an array of all the ActionListener added
385      * to this SComboBox
386      *
387      * @return all ActionListeners added or an empty
388      * array if no listeners are there
389      */

390     public ActionListener JavaDoc[] getActionListeners() {
391         return (ActionListener JavaDoc[]) getListeners(ActionListener JavaDoc.class);
392     }
393
394     /**
395      * Sets the action commnand that should be included in the event
396      * sent to action listeners.
397      *
398      * @param command a string containing the "command" that is sent
399      * to action listeners. The same listener can then
400      * do different things depending on the command it
401      * receives.
402      */

403     public void setActionCommand(String JavaDoc command) {
404         actionCommand = command;
405     }
406
407     /**
408      * Returns the action commnand that is included in the event sent to
409      * action listeners.
410      *
411      * @return the string containing the "command" that is sent
412      * to action listeners.
413      */

414     public String JavaDoc getActionCommand() {
415         return actionCommand;
416     }
417
418     /**
419      * Notify all listeners that have registered as ItemListeners.
420      *
421      * @see EventListenerList
422      */

423     protected void fireItemStateChanged(ItemEvent JavaDoc e) {
424         // Guaranteed to return a non-null array
425
Object JavaDoc[] listeners = getListenerList();
426         // Process the listeners last to first, notifying
427
// those that are interested in this event
428
for (int i = listeners.length - 2; i >= 0; i -= 2) {
429             if (listeners[i] == ItemListener JavaDoc.class) {
430                 ((ItemListener JavaDoc) listeners[i + 1]).itemStateChanged(e);
431             }
432         }
433     }
434
435     /**
436      * Notify all listeners that have registered as ActionListeners if the
437      * selected item has changed
438      *
439      * @see EventListenerList
440      */

441     protected void fireActionEvent() {
442         if (!firingActionEvent) {
443             // Set flag to ensure that an infinite loop is not created
444
firingActionEvent = true;
445
446             ActionEvent JavaDoc e = null;
447
448 // Guaranteed to return a non-null array
449
Object JavaDoc[] listeners = getListenerList();
450 // Process the listeners last to first, notifying
451
// those that are interested in this event
452
for (int i = listeners.length - 2; i >= 0; i -= 2) {
453                 if (listeners[i] == ActionListener JavaDoc.class) {
454                     if (e == null)
455                         e = new ActionEvent JavaDoc(this, ActionEvent.ACTION_PERFORMED,
456                                 getActionCommand());
457                     ((ActionListener JavaDoc) listeners[i + 1]).actionPerformed(e);
458                 }
459             }
460             firingActionEvent = false;
461         }
462     }
463
464     /**
465      * Returns an array containing the selected item.
466      *
467      * @return an array of Objects containing the selected item
468      */

469     public Object JavaDoc[] getSelectedObjects() {
470         Object JavaDoc selectedObject = getSelectedItem();
471         if (selectedObject == null)
472             return new Object JavaDoc[0];
473         else
474             return new Object JavaDoc[]{selectedObject};
475     }
476
477     /**
478      * This method is public as an implementation side effect.
479      * do not call or override.
480      *
481      * @see javax.swing.event.ListDataListener
482      */

483     public void contentsChanged(ListDataEvent JavaDoc e) {
484         if (isDifferent(selectedItemReminder, dataModel.getSelectedItem())) {
485             selectedItemChanged();
486             if (!selectingItem) {
487                 fireActionEvent();
488             }
489             reload();
490         }
491     }
492
493     /**
494      * Invoked when items have been added to the internal data model.
495      * The "interval" includes the first and last values added.
496      *
497      * @see javax.swing.event.ListDataListener
498      */

499     public void intervalAdded(ListDataEvent JavaDoc e) {
500         reload();
501     }
502
503     /**
504      * Invoked when values have been removed from the data model.
505      * The"interval" includes the first and last values removed.
506      *
507      * @see javax.swing.event.ListDataListener
508      */

509     public void intervalRemoved(ListDataEvent JavaDoc e) {
510         reload();
511     }
512
513
514     /* Accessing the model */
515     /**
516      * Returns the number of items in the list.
517      *
518      * @return an int equal to the number of items in the list
519      */

520     public int getItemCount() {
521         return dataModel.getSize();
522     }
523
524     /**
525      * Returns the list item at the specified index.
526      *
527      * @param index an int indicating the list position
528      * @return the Object at that list position
529      */

530     public Object JavaDoc getItemAt(int index) {
531         return dataModel.getElementAt(index);
532     }
533
534     /**
535      * This protected method is implementation specific. Do not access directly
536      * or override.
537      */

538     protected void selectedItemChanged() {
539         if (selectedItemReminder != null) {
540             fireItemStateChanged(new ItemEvent JavaDoc(this, ItemEvent.ITEM_STATE_CHANGED,
541                     selectedItemReminder,
542                     ItemEvent.DESELECTED));
543         }
544
545         // set the new selected item.
546
selectedItemReminder = dataModel.getSelectedItem();
547
548         if (selectedItemReminder != null) {
549             fireItemStateChanged(new ItemEvent JavaDoc(this, ItemEvent.ITEM_STATE_CHANGED,
550                     selectedItemReminder,
551                     ItemEvent.SELECTED));
552         }
553     }
554
555     public void processLowLevelEvent(String JavaDoc action, String JavaDoc[] values) {
556         processKeyEvents(values);
557
558         delayEvent = true;
559
560         int selectedIndex = -1;
561         // last will win!!
562
for (int i = 0; i < values.length; i++) {
563             try {
564                 if (values[i].length() > 0) selectedIndex = Integer.parseInt(values[i]);
565             } catch (Exception JavaDoc ex) {
566                 // ignore, some illegal request.. (maybe log it)
567
}
568         }
569
570         if (selectedIndex >= 0) {
571             setSelectedIndex(selectedIndex);
572
573             SForm.addArmedComponent(this);
574         }
575
576         delayEvent = false;
577     }
578
579
580     public void setParent(SContainer p) {
581         super.setParent(p);
582         if (getCellRendererPane() != null)
583             getCellRendererPane().setParent(p);
584     }
585
586     protected void setParentFrame(SFrame f) {
587         super.setParentFrame(f);
588         if (getCellRendererPane() != null)
589             getCellRendererPane().setParentFrame(f);
590     }
591
592
593     public void fireIntermediateEvents() {
594     }
595
596     public void fireFinalEvents() {
597         super.fireFinalEvents();
598         if (delayedEvent) {
599             if (isDifferent(selectedItemReminder, dataModel.getSelectedItem())) {
600                 // in case a users implementation of ComboBoxModel
601
// doesn't fire a ListDataEvent when the selection
602
// changes.
603
selectingItem = true;
604                 dataModel.setSelectedItem(selectedItemReminder);
605                 selectingItem = false;
606                 selectedItemChanged();
607                 fireActionEvent();
608             }
609
610
611             delayedEvent = false;
612         }
613
614     }
615
616     /** @see LowLevelEventListener#isEpochCheckEnabled() */
617     private boolean epochCheckEnabled = true;
618
619     /** @see LowLevelEventListener#isEpochCheckEnabled() */
620     public boolean isEpochCheckEnabled() {
621         return epochCheckEnabled;
622     }
623
624     /** @see LowLevelEventListener#isEpochCheckEnabled() */
625     public void setEpochCheckEnabled(boolean epochCheckEnabled) {
626         this.epochCheckEnabled = epochCheckEnabled;
627     }
628
629     public final SCellRendererPane getCellRendererPane() {
630         return cellRendererPane;
631     }
632
633     public void setCG(ComboBoxCG cg) {
634         super.setCG(cg);
635     }
636
637     public String JavaDoc getSelectionParameter(int index) {
638         return Integer.toString(index);
639     }
640 }
641
642
643
Popular Tags