KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > ui > KeyedComboBoxModel


1 /* ========================================================================
2  * JCommon : a free general purpose class library for the Java(tm) platform
3  * ========================================================================
4  *
5  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jcommon/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * ------------------
28  * KeyedComboBoxModel.java
29  * ------------------
30  * (C) Copyright 2004, by Thomas Morgner and Contributors.
31  *
32  * Original Author: Thomas Morgner;
33  * Contributor(s): David Gilbert (for Object Refinery Limited);
34  *
35  * $Id: KeyedComboBoxModel.java,v 1.6 2006/12/03 15:33:33 taqua Exp $
36  *
37  * Changes
38  * -------
39  * 07-Jun-2004 : Added JCommon header (DG);
40  *
41  */

42 package org.jfree.ui;
43
44 import java.util.ArrayList JavaDoc;
45 import javax.swing.ComboBoxModel JavaDoc;
46 import javax.swing.event.ListDataEvent JavaDoc;
47 import javax.swing.event.ListDataListener JavaDoc;
48
49 /**
50  * The KeyedComboBox model allows to define an internal key (the data element)
51  * for every entry in the model.
52  * <p/>
53  * This class is usefull in all cases, where the public text differs from the
54  * internal view on the data. A separation between presentation data and
55  * processing data is a prequesite for localizing combobox entries. This model
56  * does not allow selected elements, which are not in the list of valid
57  * elements.
58  *
59  * @author Thomas Morgner
60  */

61 public class KeyedComboBoxModel implements ComboBoxModel JavaDoc
62 {
63
64   /**
65    * The internal data carrier to map keys to values and vice versa.
66    */

67   private static class ComboBoxItemPair
68   {
69     /**
70      * The key.
71      */

72     private Object JavaDoc key;
73     /**
74      * The value for the key.
75      */

76     private Object JavaDoc value;
77
78     /**
79      * Creates a new item pair for the given key and value. The value can be
80      * changed later, if needed.
81      *
82      * @param key the key
83      * @param value the value
84      */

85     public ComboBoxItemPair(final Object JavaDoc key, final Object JavaDoc value)
86     {
87       this.key = key;
88       this.value = value;
89     }
90
91     /**
92      * Returns the key.
93      *
94      * @return the key.
95      */

96     public Object JavaDoc getKey()
97     {
98       return key;
99     }
100
101     /**
102      * Returns the value.
103      *
104      * @return the value for this key.
105      */

106     public Object JavaDoc getValue()
107     {
108       return value;
109     }
110
111     /**
112      * Redefines the value stored for that key.
113      *
114      * @param value the new value.
115      */

116     public void setValue(final Object JavaDoc value)
117     {
118       this.value = value;
119     }
120   }
121
122   /**
123    * The index of the selected item.
124    */

125   private int selectedItemIndex;
126   private Object JavaDoc selectedItemValue;
127   /**
128    * The data (contains ComboBoxItemPairs).
129    */

130   private ArrayList JavaDoc data;
131   /**
132    * The listeners.
133    */

134   private ArrayList JavaDoc listdatalistener;
135   /**
136    * The cached listeners as array.
137    */

138   private transient ListDataListener JavaDoc[] tempListeners;
139   private boolean allowOtherValue;
140
141   /**
142    * Creates a new keyed combobox model.
143    */

144   public KeyedComboBoxModel()
145   {
146     data = new ArrayList JavaDoc();
147     listdatalistener = new ArrayList JavaDoc();
148   }
149
150   /**
151    * Creates a new keyed combobox model for the given keys and values. Keys
152    * and values must have the same number of items.
153    *
154    * @param keys the keys
155    * @param values the values
156    */

157   public KeyedComboBoxModel(final Object JavaDoc[] keys, final Object JavaDoc[] values)
158   {
159     this();
160     setData(keys, values);
161   }
162
163   /**
164    * Replaces the data in this combobox model. The number of keys must be
165    * equals to the number of values.
166    *
167    * @param keys the keys
168    * @param values the values
169    */

170   public void setData(final Object JavaDoc[] keys, final Object JavaDoc[] values)
171   {
172     if (values.length != keys.length)
173     {
174       throw new IllegalArgumentException JavaDoc("Values and text must have the same length.");
175     }
176
177     data.clear();
178     data.ensureCapacity(keys.length);
179
180     for (int i = 0; i < values.length; i++)
181     {
182       add(keys[i], values[i]);
183     }
184
185     selectedItemIndex = -1;
186     final ListDataEvent JavaDoc evt = new ListDataEvent JavaDoc
187         (this, ListDataEvent.CONTENTS_CHANGED, 0, data.size() - 1);
188     fireListDataEvent(evt);
189   }
190
191   /**
192    * Notifies all registered list data listener of the given event.
193    *
194    * @param evt the event.
195    */

196   protected synchronized void fireListDataEvent(final ListDataEvent JavaDoc evt)
197   {
198     if (tempListeners == null)
199     {
200       tempListeners = (ListDataListener JavaDoc[]) listdatalistener.toArray
201           (new ListDataListener JavaDoc[listdatalistener.size()]);
202     }
203     for (int i = 0; i < tempListeners.length; i++)
204     {
205       final ListDataListener JavaDoc l = tempListeners[i];
206       l.contentsChanged(evt);
207     }
208   }
209
210   /**
211    * Returns the selected item.
212    *
213    * @return The selected item or <code>null</code> if there is no selection
214    */

215   public Object JavaDoc getSelectedItem()
216   {
217     return selectedItemValue;
218   }
219
220   /**
221    * Defines the selected key. If the object is not in the list of values, no
222    * item gets selected.
223    *
224    * @param anItem the new selected item.
225    */

226   public void setSelectedKey(final Object JavaDoc anItem)
227   {
228     if (anItem == null)
229     {
230       selectedItemIndex = -1;
231       selectedItemValue = null;
232     }
233     else
234     {
235       final int newSelectedItem = findDataElementIndex(anItem);
236       if (newSelectedItem == -1)
237       {
238         selectedItemIndex = -1;
239         selectedItemValue = null;
240       }
241       else
242       {
243         selectedItemIndex = newSelectedItem;
244         selectedItemValue = getElementAt(selectedItemIndex);
245       }
246     }
247     fireListDataEvent(new ListDataEvent JavaDoc(this, ListDataEvent.CONTENTS_CHANGED, -1, -1));
248   }
249
250   /**
251    * Set the selected item. The implementation of this method should notify
252    * all registered <code>ListDataListener</code>s that the contents have
253    * changed.
254    *
255    * @param anItem the list object to select or <code>null</code> to clear the
256    * selection
257    */

258   public void setSelectedItem(final Object JavaDoc anItem)
259   {
260     if (anItem == null)
261     {
262       selectedItemIndex = -1;
263       selectedItemValue = null;
264     }
265     else
266     {
267       final int newSelectedItem = findElementIndex(anItem);
268       if (newSelectedItem == -1)
269       {
270         if (isAllowOtherValue())
271         {
272           selectedItemIndex = -1;
273           selectedItemValue = anItem;
274         }
275         else
276         {
277           selectedItemIndex = -1;
278           selectedItemValue = null;
279         }
280       }
281       else
282       {
283         selectedItemIndex = newSelectedItem;
284         selectedItemValue = getElementAt(selectedItemIndex);
285       }
286     }
287     fireListDataEvent(new ListDataEvent JavaDoc(this, ListDataEvent.CONTENTS_CHANGED, -1, -1));
288   }
289
290   private boolean isAllowOtherValue()
291   {
292     return allowOtherValue;
293   }
294
295   public void setAllowOtherValue(final boolean allowOtherValue)
296   {
297     this.allowOtherValue = allowOtherValue;
298   }
299
300   /**
301    * Adds a listener to the list that's notified each time a change to the data
302    * model occurs.
303    *
304    * @param l the <code>ListDataListener</code> to be added
305    */

306   public synchronized void addListDataListener(final ListDataListener JavaDoc l)
307   {
308     listdatalistener.add(l);
309     tempListeners = null;
310   }
311
312   /**
313    * Returns the value at the specified index.
314    *
315    * @param index the requested index
316    * @return the value at <code>index</code>
317    */

318   public Object JavaDoc getElementAt(final int index)
319   {
320     if (index >= data.size())
321     {
322       return null;
323     }
324
325     final ComboBoxItemPair datacon = (ComboBoxItemPair) data.get(index);
326     if (datacon == null)
327     {
328       return null;
329     }
330     return datacon.getValue();
331   }
332
333   /**
334    * Returns the key from the given index.
335    *
336    * @param index the index of the key.
337    * @return the the key at the specified index.
338    */

339   public Object JavaDoc getKeyAt(final int index)
340   {
341     if (index >= data.size())
342     {
343       return null;
344     }
345
346     if (index < 0)
347     {
348       return null;
349     }
350
351     final ComboBoxItemPair datacon = (ComboBoxItemPair) data.get(index);
352     if (datacon == null)
353     {
354       return null;
355     }
356     return datacon.getKey();
357   }
358
359   /**
360    * Returns the selected data element or null if none is set.
361    *
362    * @return the selected data element.
363    */

364   public Object JavaDoc getSelectedKey()
365   {
366     return getKeyAt(selectedItemIndex);
367   }
368
369   /**
370    * Returns the length of the list.
371    *
372    * @return the length of the list
373    */

374   public int getSize()
375   {
376     return data.size();
377   }
378
379   /**
380    * Removes a listener from the list that's notified each time a change to
381    * the data model occurs.
382    *
383    * @param l the <code>ListDataListener</code> to be removed
384    */

385   public void removeListDataListener(final ListDataListener JavaDoc l)
386   {
387     listdatalistener.remove(l);
388     tempListeners = null;
389   }
390
391   /**
392    * Searches an element by its data value. This method is called by the
393    * setSelectedItem method and returns the first occurence of the element.
394    *
395    * @param anItem the item
396    * @return the index of the item or -1 if not found.
397    */

398   private int findDataElementIndex(final Object JavaDoc anItem)
399   {
400     if (anItem == null)
401     {
402       throw new NullPointerException JavaDoc("Item to find must not be null");
403     }
404
405     for (int i = 0; i < data.size(); i++)
406     {
407       final ComboBoxItemPair datacon = (ComboBoxItemPair) data.get(i);
408       if (anItem.equals(datacon.getKey()))
409       {
410         return i;
411       }
412     }
413     return -1;
414   }
415
416   /**
417    * Tries to find the index of element with the given key. The key must not
418    * be null.
419    *
420    * @param key the key for the element to be searched.
421    * @return the index of the key, or -1 if not found.
422    */

423   public int findElementIndex(final Object JavaDoc key)
424   {
425     if (key == null)
426     {
427       throw new NullPointerException JavaDoc("Item to find must not be null");
428     }
429
430     for (int i = 0; i < data.size(); i++)
431     {
432       final ComboBoxItemPair datacon = (ComboBoxItemPair) data.get(i);
433       if (key.equals(datacon.getValue()))
434       {
435         return i;
436       }
437     }
438     return -1;
439   }
440
441   /**
442    * Removes an entry from the model.
443    *
444    * @param key the key
445    */

446   public void removeDataElement(final Object JavaDoc key)
447   {
448     final int idx = findDataElementIndex(key);
449     if (idx == -1)
450     {
451       return;
452     }
453
454     data.remove(idx);
455     final ListDataEvent JavaDoc evt = new ListDataEvent JavaDoc
456         (this, ListDataEvent.INTERVAL_REMOVED, idx, idx);
457     fireListDataEvent(evt);
458   }
459
460   /**
461    * Adds a new entry to the model.
462    *
463    * @param key the key
464    * @param cbitem the display value.
465    */

466   public void add(final Object JavaDoc key, final Object JavaDoc cbitem)
467   {
468     final ComboBoxItemPair con = new ComboBoxItemPair(key, cbitem);
469     data.add(con);
470     final ListDataEvent JavaDoc evt = new ListDataEvent JavaDoc
471         (this, ListDataEvent.INTERVAL_ADDED, data.size() - 2, data.size() - 2);
472     fireListDataEvent(evt);
473   }
474
475   /**
476    * Removes all entries from the model.
477    */

478   public void clear()
479   {
480     final int size = getSize();
481     data.clear();
482     final ListDataEvent JavaDoc evt = new ListDataEvent JavaDoc(this, ListDataEvent.INTERVAL_REMOVED, 0, size - 1);
483     fireListDataEvent(evt);
484   }
485
486 }
487
Popular Tags