1 /* List.java -- A listbox widget
2    Copyright (C) 1999, 2002, 2004, 2006,  Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package java.awt;
40 
41 import java.awt.event.ActionEvent;
42 import java.awt.event.ActionListener;
43 import java.awt.event.ItemEvent;
44 import java.awt.event.ItemListener;
45 import java.awt.peer.ListPeer;
46 import java.util.EventListener;
47 import java.util.Vector;
48 
49 import javax.accessibility.Accessible;
50 import javax.accessibility.AccessibleContext;
51 import javax.accessibility.AccessibleRole;
52 import javax.accessibility.AccessibleSelection;
53 import javax.accessibility.AccessibleState;
54 import javax.accessibility.AccessibleStateSet;
55 
56 /**
57  * Class that implements a listbox widget
58  *
59  * @author Aaron M. Renn (arenn@urbanophile.com)
60  */
61 public class List extends Component
62   implements ItemSelectable, Accessible
63 {
64 
65   /**
66    * The number used to generate the name returned by getName.
67    */
68   private static transient long next_list_number;
69 
70   // Serialization constant
71   private static final long serialVersionUID = -3304312411574666869L;
72 
73   // FIXME: Need read/writeObject
74 
75   /**
76     * @serial The items in the list.
77     */
78   private Vector items = new Vector();
79 
80   /**
81    * @serial Indicates whether or not multiple items can be selected
82    * simultaneously.
83    */
84   private boolean multipleMode;
85 
86   /**
87    * @serial The number of rows in the list.  This is set on creation
88    * only and cannot be modified.
89    */
90   private int rows;
91 
92   /**
93    * @serial An array of the item indices that are selected.
94    */
95   private int[] selected;
96 
97   /**
98    * @serial An index value used by <code>makeVisible()</code> and
99    * <code>getVisibleIndex</code>.
100    */
101   private int visibleIndex = -1;
102 
103   // The list of ItemListeners for this object.
104   private ItemListener item_listeners;
105 
106   // The list of ActionListeners for this object.
107   private ActionListener action_listeners;
108 
109   /**
110    * Initializes a new instance of <code>List</code> with no visible lines
111    * and multi-select disabled.
112    *
113    * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
114    * @since 1.1
115    */
List()116   public List()
117   {
118     this(4, false);
119   }
120 
121   /**
122    * Initializes a new instance of <code>List</code> with the specified
123    * number of visible lines and multi-select disabled.
124    *
125    * @param rows The number of visible rows in the list.
126    *
127    * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
128    */
List(int rows)129   public List(int rows)
130   {
131     this(rows, false);
132   }
133 
134   /**
135    * Initializes a new instance of <code>List</code> with the specified
136    * number of lines and the specified multi-select setting.
137    *
138    * @param rows The number of visible rows in the list.
139    * @param multipleMode <code>true</code> if multiple lines can be selected
140    * simultaneously, <code>false</code> otherwise.
141    *
142    * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
143    */
List(int rows, boolean multipleMode)144   public List(int rows, boolean multipleMode)
145   {
146     if (rows == 0)
147       this.rows = 4;
148     else
149       this.rows = rows;
150 
151     this.multipleMode = multipleMode;
152     selected = new int[0];
153 
154     if (GraphicsEnvironment.isHeadless())
155       throw new HeadlessException();
156 
157   }
158 
159   /**
160    * Returns the number of items in this list.
161    *
162    * @return The number of items in this list.
163    *
164    * @since 1.1
165    */
getItemCount()166   public int getItemCount()
167   {
168     return countItems();
169   }
170 
171   /**
172    * Returns the number of items in this list.
173    *
174    * @return The number of items in this list.
175    *
176    * @deprecated This method is deprecated in favor of
177    * <code>getItemCount()</code>
178    */
countItems()179   public int countItems()
180   {
181     return items.size();
182   }
183 
184   /**
185    * Returns the complete list of items.
186    *
187    * @return The complete list of items in the list.
188    *
189    * @since 1.1
190    */
getItems()191   public synchronized String[] getItems()
192   {
193     String[] l_items = new String[getItemCount()];
194 
195     items.copyInto(l_items);
196     return(l_items);
197   }
198 
199   /**
200    * Returns the item at the specified index.
201    *
202    * @param index The index of the item to retrieve.
203    *
204    * @exception IndexOutOfBoundsException If the index value is not valid.
205    */
getItem(int index)206   public String getItem(int index)
207   {
208     return((String) items.elementAt(index));
209   }
210 
211   /**
212    * Returns the number of visible rows in the list.
213    *
214    * @return The number of visible rows in the list.
215    */
getRows()216   public int getRows()
217   {
218     return(rows);
219   }
220 
221   /**
222    * Tests whether or not multi-select mode is enabled.
223    *
224    * @return <code>true</code> if multi-select mode is enabled,
225    * <code>false</code> otherwise.
226    *
227    * @since 1.1
228    */
isMultipleMode()229   public boolean isMultipleMode()
230   {
231     return allowsMultipleSelections ();
232   }
233 
234   /**
235    * Tests whether or not multi-select mode is enabled.
236    *
237    * @return <code>true</code> if multi-select mode is enabled,
238    * <code>false</code> otherwise.
239    *
240    * @deprecated This method is deprecated in favor of
241    * <code>isMultipleMode()</code>.
242    */
allowsMultipleSelections()243   public boolean allowsMultipleSelections()
244   {
245     return multipleMode;
246   }
247 
248   /**
249    * This method enables or disables multiple selection mode for this
250    * list.
251    *
252    * @param multipleMode <code>true</code> to enable multiple mode,
253    * <code>false</code> otherwise.
254    *
255    * @since 1.1
256    */
setMultipleMode(boolean multipleMode)257   public void setMultipleMode(boolean multipleMode)
258   {
259     setMultipleSelections (multipleMode);
260   }
261 
262   /**
263    * This method enables or disables multiple selection mode for this
264    * list.
265    *
266    * @param multipleMode <code>true</code> to enable multiple mode,
267    * <code>false</code> otherwise.
268    *
269    * @deprecated
270    */
setMultipleSelections(boolean multipleMode)271   public void setMultipleSelections(boolean multipleMode)
272   {
273     this.multipleMode = multipleMode;
274 
275     ListPeer peer = (ListPeer) getPeer();
276     if (peer != null)
277       peer.setMultipleMode(multipleMode);
278 
279   }
280 
281   /**
282    * Returns the minimum size of this component.
283    *
284    * @return The minimum size of this component.
285    *
286    * @since 1.1
287    */
getMinimumSize()288   public Dimension getMinimumSize()
289   {
290     return getMinimumSize(getRows());
291   }
292 
293   /**
294    * Returns the minimum size of this component.
295    *
296    * @return The minimum size of this component.
297    *
298    * @deprecated This method is deprecated in favor of
299    * <code>getMinimumSize</code>.
300    */
minimumSize()301   public Dimension minimumSize()
302   {
303     return minimumSize(getRows());
304   }
305 
306   /**
307    * Returns the minimum size of this component assuming it had the specified
308    * number of rows.
309    *
310    * @param rows The number of rows to size for.
311    *
312    * @return The minimum size of this component.
313    *
314    * @since 1.1
315    */
getMinimumSize(int rows)316   public Dimension getMinimumSize(int rows)
317   {
318     return minimumSize(rows);
319   }
320 
321   /**
322    * Returns the minimum size of this component assuming it had the specified
323    * number of rows.
324    *
325    * @param rows The number of rows to size for.
326    *
327    * @return The minimum size of this component.
328    *
329    * @deprecated This method is deprecated in favor of
330    * <code>getMinimumSize(int)</code>>
331    */
minimumSize(int rows)332   public Dimension minimumSize(int rows)
333   {
334     ListPeer peer = (ListPeer) getPeer();
335     if (peer != null)
336       return peer.minimumSize(rows);
337     else
338       return new Dimension(0, 0);
339   }
340 
341   /**
342    * Returns the preferred size of this component.
343    *
344    * @return The preferred size of this component.
345    *
346    * @since 1.1
347    */
getPreferredSize()348   public Dimension getPreferredSize()
349   {
350     return getPreferredSize(getRows());
351   }
352 
353   /**
354    * Returns the preferred size of this component.
355    *
356    * @return The preferred size of this component.
357    *
358    * @deprecated This method is deprecated in favor of
359    * <code>getPreferredSize</code>.
360    */
preferredSize()361   public Dimension preferredSize()
362   {
363     return preferredSize(getRows());
364   }
365 
366   /**
367    * Returns the preferred size of this component assuming it had the specified
368    * number of rows.
369    *
370    * @param rows The number of rows to size for.
371    *
372    * @return The preferred size of this component.
373    *
374    * @since 1.1
375    */
getPreferredSize(int rows)376   public Dimension getPreferredSize(int rows)
377   {
378     return preferredSize(rows);
379   }
380 
381   /**
382    * Returns the preferred size of this component assuming it had the specified
383    * number of rows.
384    *
385    * @param rows The number of rows to size for.
386    *
387    * @return The preferred size of this component.
388    *
389    * @deprecated This method is deprecated in favor of
390    * <code>getPreferredSize(int)</code>>
391    */
preferredSize(int rows)392   public Dimension preferredSize(int rows)
393   {
394     ListPeer peer = (ListPeer)getPeer();
395     if (peer != null)
396       return peer.preferredSize(rows);
397     else
398       return getSize();
399   }
400 
401   /**
402    * This method adds the specified item to the end of the list.
403    *
404    * @param item The item to add to the list.
405    *
406    * @since 1.1
407    */
add(String item)408   public void add(String item)
409   {
410     add (item, -1);
411   }
412 
413   /**
414    * This method adds the specified item to the end of the list.
415    *
416    * @param item The item to add to the list.
417    *
418    * @deprecated Use add() instead.
419    */
addItem(String item)420   public void addItem(String item)
421   {
422     addItem(item, -1);
423   }
424 
425   /**
426    * Adds the specified item to the specified location in the list.
427    * If the desired index is -1 or greater than the number of rows
428    * in the list, then the item is added to the end.
429    *
430    * @param item The item to add to the list.
431    * @param index The location in the list to add the item, or -1 to add
432    * to the end.
433    *
434    * @since 1.1
435    */
add(String item, int index)436   public void add(String item, int index)
437   {
438     addItem(item, index);
439   }
440 
441   /**
442    * Adds the specified item to the specified location in the list.
443    * If the desired index is -1 or greater than the number of rows
444    * in the list, then the item is added to the end.
445    *
446    * @param item The item to add to the list.
447    * @param index The location in the list to add the item, or -1 to add
448    * to the end.
449    *
450    * @deprecated Use add() instead.
451    */
addItem(String item, int index)452   public void addItem(String item, int index)
453   {
454     if (item == null)
455       item = "";
456 
457     if (index < -1)
458       index = -1;
459 
460     if ((index == -1) || (index >= items.size ()))
461       items.addElement (item);
462     else
463       items.insertElementAt(item, index);
464 
465     ListPeer peer = (ListPeer) getPeer();
466     if (peer != null)
467       peer.add (item, index);
468   }
469 
470   /**
471    * Deletes the item at the specified index.
472    *
473    * @param index The index of the item to delete.
474    *
475    * @exception IllegalArgumentException If the index is not valid
476    *
477    * @deprecated
478    */
delItem(int index)479   public void delItem(int index) throws IllegalArgumentException
480   {
481     boolean selected = false;
482     if (isSelected(index))
483       {
484         selected = true;
485         deselect(index);
486       }
487 
488     items.removeElementAt (index);
489 
490     if (selected)
491       select(index);
492 
493     ListPeer peer = (ListPeer) getPeer();
494     if (peer != null)
495       peer.delItems (index, index);
496   }
497 
498   /**
499    * Deletes the item at the specified index.
500    *
501    * @param index The index of the item to delete.
502    *
503    * @exception IllegalArgumentException If the index is not valid
504    *
505    * @since 1.1
506    */
remove(int index)507   public void remove(int index) throws IllegalArgumentException
508   {
509     delItem(index);
510   }
511 
512   /**
513    * Deletes all items in the specified index range.
514    *
515    * @param start The beginning index of the range to delete.
516    * @param end The ending index of the range to delete.
517    *
518    * @exception IllegalArgumentException If the indexes are not valid
519    *
520    * @deprecated This method is deprecated for some unknown reason.
521    */
delItems(int start, int end)522   public synchronized void delItems(int start, int end)
523     throws IllegalArgumentException
524   {
525     // We must run the loop in reverse direction.
526     for (int i = end; i >= start; --i)
527       items.removeElementAt (i);
528     if (peer != null)
529       {
530         ListPeer l = (ListPeer) peer;
531         l.delItems (start, end);
532       }
533   }
534 
535   /**
536    * Deletes the first occurrence of the specified item from the list.
537    *
538    * @param item The item to delete.
539    *
540    * @exception IllegalArgumentException If the specified item does not exist.
541    *
542    * @since 1.1
543    */
remove(String item)544   public synchronized void remove(String item) throws IllegalArgumentException
545   {
546     int index = items.indexOf(item);
547     if (index == -1)
548       throw new IllegalArgumentException("List element to delete not found");
549 
550     remove(index);
551   }
552 
553   /**
554    * Deletes all of the items from the list.
555    *
556    * @since 1.1
557    */
removeAll()558   public synchronized void removeAll()
559   {
560     clear();
561   }
562 
563   /**
564    * Deletes all of the items from the list.
565    *
566    * @deprecated This method is deprecated in favor of <code>removeAll()</code>.
567    */
clear()568   public void clear()
569   {
570     items.clear();
571 
572     ListPeer peer = (ListPeer) getPeer();
573     if (peer != null)
574       peer.removeAll();
575 
576     selected = new int[0];
577   }
578 
579   /**
580    * Replaces the item at the specified index with the specified item.
581    *
582    * @param item The new item value.
583    * @param index The index of the item to replace.
584    *
585    * @exception ArrayIndexOutOfBoundsException If the index is not valid.
586    */
replaceItem(String item, int index)587   public synchronized void replaceItem(String item, int index)
588     throws ArrayIndexOutOfBoundsException
589   {
590     if ((index < 0) || (index >= items.size()))
591       throw new ArrayIndexOutOfBoundsException("Bad list index: " + index);
592 
593     items.insertElementAt(item, index + 1);
594     items.removeElementAt (index);
595 
596     if (peer != null)
597       {
598         ListPeer l = (ListPeer) peer;
599 
600         /* We add first and then remove so that the selected
601            item remains the same */
602         l.add (item, index + 1);
603         l.delItems (index, index);
604       }
605   }
606 
607   /**
608    * Returns the index of the currently selected item.  -1 will be returned
609    * if there are no selected rows or if there are multiple selected rows.
610    *
611    * @return The index of the selected row.
612    */
getSelectedIndex()613   public synchronized int getSelectedIndex()
614   {
615     if (peer != null)
616       {
617         ListPeer l = (ListPeer) peer;
618         selected = l.getSelectedIndexes ();
619       }
620 
621     if (selected == null || selected.length != 1)
622       return -1;
623 
624     return selected[0];
625   }
626 
627   /**
628    * Returns an array containing the indexes of the rows that are
629    * currently selected.
630    *
631    * @return A list of indexes of selected rows.
632    */
getSelectedIndexes()633   public synchronized int[] getSelectedIndexes()
634   {
635     if (peer != null)
636       {
637         ListPeer l = (ListPeer) peer;
638         selected = l.getSelectedIndexes();
639       }
640 
641     return selected;
642   }
643 
644   /**
645    * Returns the item that is currently selected, or <code>null</code> if there
646    * is no item selected.  FIXME: What happens if multiple items selected?
647    *
648    * @return The selected item, or <code>null</code> if there is no
649    * selected item.
650    */
getSelectedItem()651   public synchronized String getSelectedItem()
652   {
653     int index = getSelectedIndex();
654     if (index == -1)
655       return(null);
656 
657     return((String) items.elementAt(index));
658   }
659 
660   /**
661    * Returns the list of items that are currently selected in this list.
662    *
663    * @return The list of currently selected items.
664    */
getSelectedItems()665   public synchronized String[] getSelectedItems()
666   {
667     int[] indexes = getSelectedIndexes();
668     if (indexes == null)
669       return(new String[0]);
670 
671     String[] retvals = new String[indexes.length];
672     if (retvals.length > 0)
673       for (int i = 0 ; i < retvals.length; i++)
674          retvals[i] = (String)items.elementAt(indexes[i]);
675 
676     return(retvals);
677   }
678 
679   /**
680    * Returns the list of items that are currently selected in this list as
681    * an array of type <code>Object[]</code> instead of <code>String[]</code>.
682    *
683    * @return The list of currently selected items.
684    */
getSelectedObjects()685   public synchronized Object[] getSelectedObjects()
686   {
687     int[] indexes = getSelectedIndexes();
688     if (indexes == null)
689       return(new Object[0]);
690 
691     Object[] retvals = new Object[indexes.length];
692     if (retvals.length > 0)
693       for (int i = 0 ; i < retvals.length; i++)
694          retvals[i] = items.elementAt(indexes[i]);
695 
696     return(retvals);
697   }
698 
699   /**
700    * Tests whether or not the specified index is selected.
701    *
702    * @param index The index to test.
703    *
704    * @return <code>true</code> if the index is selected, <code>false</code>
705    * otherwise.
706    *
707    * @since 1.1
708    */
isIndexSelected(int index)709   public boolean isIndexSelected(int index)
710   {
711     return isSelected(index);
712   }
713 
714   /**
715    * Tests whether or not the specified index is selected.
716    *
717    * @param index The index to test.
718    *
719    * @return <code>true</code> if the index is selected, <code>false</code>
720    * otherwise.
721    *
722    * @deprecated This method is deprecated in favor of
723    * <code>isIndexSelected(int)</code>.
724    */
isSelected(int index)725   public boolean isSelected(int index)
726   {
727     int[] indexes = getSelectedIndexes();
728 
729     for (int i = 0; i < indexes.length; i++)
730       if (indexes[i] == index)
731         return true;
732 
733     return false;
734   }
735 
736   /**
737    * This method ensures that the item at the specified index is visible.
738    *
739    * @param index The index of the item to be made visible.
740    */
makeVisible(int index)741   public synchronized void makeVisible(int index)
742     throws IllegalArgumentException
743   {
744     visibleIndex = index;
745     if (peer != null)
746       {
747         ListPeer l = (ListPeer) peer;
748         l.makeVisible (index);
749       }
750   }
751 
752   /**
753    * Returns the index of the last item that was made visible via the
754    * <code>makeVisible()</code> method.
755    *
756    * @return The index of the last item made visible via the
757    * <code>makeVisible()</code> method.
758    */
getVisibleIndex()759   public int getVisibleIndex()
760   {
761     return visibleIndex;
762   }
763 
764   /**
765    * Makes the item at the specified index selected.
766    *
767    * @param index The index of the item to select.
768    */
select(int index)769   public synchronized void select(int index)
770   {
771     ListPeer lp = (ListPeer) getPeer();
772     if (lp != null)
773       lp.select(index);
774 
775    if (selected != null)
776      {
777        boolean found = false;
778        for (int i = 0; i < selected.length; i++)
779          {
780            if (selected[i] == index)
781            found = true;
782          }
783        if (! found)
784          {
785            if (! isMultipleMode())
786              {
787                selected = new int[] { index };
788                return;
789              }
790            int[] temp = new int[selected.length + 1];
791            System.arraycopy(selected, 0, temp, 0, selected.length);
792            temp[selected.length] = index;
793            selected = temp;
794          }
795      }
796    else
797      {
798        selected = new int[1];
799        selected[0] = index;
800      }
801   }
802 
803   /**
804    * Makes the item at the specified index not selected.
805    *
806    * @param index The index of the item to unselect.
807    */
deselect(int index)808   public synchronized void deselect(int index)
809   {
810     if (isSelected(index))
811       {
812         ListPeer lp = (ListPeer)getPeer();
813         if (lp != null)
814           lp.deselect(index);
815 
816         int[] temp = new int[selected.length - 1];
817         for (int i = 0; i < temp.length; i++)
818           {
819             if (selected[i] != index)
820               temp[i] = selected[i];
821             else
822               {
823                 System.arraycopy(selected, i + 1, temp, i,
824                                  selected.length - i - 1);
825                 break;
826               }
827           }
828         selected = temp;
829       }
830   }
831 
832   /**
833    * Notifies this object to create its native peer.
834    */
addNotify()835   public void addNotify()
836   {
837     if (peer == null)
838       peer = getToolkit ().createList(this);
839     super.addNotify ();
840   }
841 
842   /**
843    * Notifies this object to destroy its native peer.
844    */
removeNotify()845   public void removeNotify()
846   {
847     super.removeNotify();
848   }
849 
850   /**
851    * Adds the specified <code>ActionListener</code> to the list of
852    * registered listeners for this object.
853    *
854    * @param listener The listener to add.
855    *
856    * @since 1.1
857    */
addActionListener(ActionListener listener)858   public synchronized void addActionListener(ActionListener listener)
859   {
860     action_listeners = AWTEventMulticaster.add(action_listeners, listener);
861   }
862 
863   /**
864    * Removes the specified <code>ActionListener</code> from the list of
865    * registers listeners for this object.
866    *
867    * @param listener The listener to remove.
868    *
869    * @since 1.1
870    */
removeActionListener(ActionListener listener)871   public synchronized void removeActionListener(ActionListener listener)
872   {
873     action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
874   }
875 
876   /**
877    * Adds the specified <code>ItemListener</code> to the list of
878    * registered listeners for this object.
879    *
880    * @param listener The listener to add.
881    *
882    * @since 1.1
883    */
addItemListener(ItemListener listener)884   public synchronized void addItemListener(ItemListener listener)
885   {
886     item_listeners = AWTEventMulticaster.add(item_listeners, listener);
887   }
888 
889   /**
890    * Removes the specified <code>ItemListener</code> from the list of
891    * registers listeners for this object.
892    *
893    * @param listener The listener to remove.
894    *
895    * @since 1.1
896    */
removeItemListener(ItemListener listener)897   public synchronized void removeItemListener(ItemListener listener)
898   {
899     item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
900   }
901 
902   /**
903    * Processes the specified event for this object.  If the event is an
904    * instance of <code>ActionEvent</code> then the
905    * <code>processActionEvent()</code> method is called.  Similarly, if the
906    * even is an instance of <code>ItemEvent</code> then the
907    * <code>processItemEvent()</code> method is called.  Otherwise the
908    * superclass method is called to process this event.
909    *
910    * @param event The event to process.
911    *
912    * @since 1.1
913    */
processEvent(AWTEvent event)914   protected void processEvent(AWTEvent event)
915   {
916     if (event instanceof ActionEvent)
917       processActionEvent((ActionEvent)event);
918     else if (event instanceof ItemEvent)
919       processItemEvent((ItemEvent)event);
920     else
921       super.processEvent(event);
922   }
923 
924   /**
925    * This method processes the specified event by dispatching it to any
926    * registered listeners.  Note that this method will only get called if
927    * action events are enabled.  This will happen automatically if any
928    * listeners are added, or it can be done "manually" by calling
929    * the <code>enableEvents()</code> method.
930    *
931    * @param event The event to process.
932    *
933    * @since 1.1
934    */
processActionEvent(ActionEvent event)935   protected void processActionEvent(ActionEvent event)
936   {
937     if (action_listeners != null)
938       action_listeners.actionPerformed(event);
939   }
940 
941   /**
942    * This method processes the specified event by dispatching it to any
943    * registered listeners.  Note that this method will only get called if
944    * item events are enabled.  This will happen automatically if any
945    * listeners are added, or it can be done "manually" by calling
946    * the <code>enableEvents()</code> method.
947    *
948    * @param event The event to process.
949    *
950    * @since 1.1
951    */
processItemEvent(ItemEvent event)952   protected void processItemEvent(ItemEvent event)
953   {
954     if (item_listeners != null)
955       item_listeners.itemStateChanged(event);
956   }
957 
dispatchEventImpl(AWTEvent e)958   void dispatchEventImpl(AWTEvent e)
959   {
960     if (e.id <= ItemEvent.ITEM_LAST
961         && e.id >= ItemEvent.ITEM_FIRST
962         && (item_listeners != null
963         || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0))
964       processEvent(e);
965     else if (e.id <= ActionEvent.ACTION_LAST
966            && e.id >= ActionEvent.ACTION_FIRST
967            && (action_listeners != null
968            || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
969       processEvent(e);
970     else
971       super.dispatchEventImpl(e);
972   }
973 
974   /**
975    * Returns a debugging string for this object.
976    *
977    * @return A debugging string for this object.
978    */
paramString()979   protected String paramString()
980   {
981     return "multiple=" + multipleMode + ",rows=" + rows + super.paramString();
982   }
983 
984   /**
985    * Returns an array of all the objects currently registered as FooListeners
986    * upon this <code>List</code>. FooListeners are registered using the
987    * addFooListener method.
988    *
989    * @exception ClassCastException If listenerType doesn't specify a class or
990    * interface that implements java.util.EventListener.
991    *
992    * @since 1.3
993    */
getListeners(Class<T> listenerType)994   public <T extends EventListener> T[] getListeners (Class<T> listenerType)
995   {
996     if (listenerType == ActionListener.class)
997       return AWTEventMulticaster.getListeners (action_listeners, listenerType);
998 
999     if (listenerType == ItemListener.class)
1000       return AWTEventMulticaster.getListeners (item_listeners, listenerType);
1001 
1002     return super.getListeners (listenerType);
1003   }
1004 
1005   /**
1006    * Returns all action listeners registered to this object.
1007    *
1008    * @since 1.4
1009    */
getActionListeners()1010   public ActionListener[] getActionListeners ()
1011   {
1012     return (ActionListener[]) getListeners (ActionListener.class);
1013   }
1014 
1015   /**
1016    * Returns all action listeners registered to this object.
1017    *
1018    * @since 1.4
1019    */
getItemListeners()1020   public ItemListener[] getItemListeners ()
1021   {
1022     return (ItemListener[]) getListeners (ItemListener.class);
1023   }
1024 
1025   // Accessibility internal class
1026   protected class AccessibleAWTList extends AccessibleAWTComponent
1027     implements AccessibleSelection, ItemListener, ActionListener
1028   {
1029     private static final long serialVersionUID = 7924617370136012829L;
1030 
1031     protected class AccessibleAWTListChild extends AccessibleAWTComponent
1032       implements Accessible
1033     {
1034       private static final long serialVersionUID = 4412022926028300317L;
1035 
1036       // Field names are fixed by serialization spec.
1037       private List parent;
1038       private int indexInParent;
1039 
AccessibleAWTListChild(List parent, int indexInParent)1040       public AccessibleAWTListChild(List parent, int indexInParent)
1041       {
1042         this.parent = parent;
1043         this.indexInParent = indexInParent;
1044         if (parent == null)
1045           this.indexInParent = -1;
1046       }
1047 
1048       /* (non-Javadoc)
1049        * @see javax.accessibility.Accessible#getAccessibleContext()
1050        */
getAccessibleContext()1051       public AccessibleContext getAccessibleContext()
1052       {
1053         return this;
1054       }
1055 
getAccessibleRole()1056       public AccessibleRole getAccessibleRole()
1057       {
1058         return AccessibleRole.LIST_ITEM;
1059       }
1060 
getAccessibleStateSet()1061       public AccessibleStateSet getAccessibleStateSet()
1062       {
1063         AccessibleStateSet states = super.getAccessibleStateSet();
1064         if (parent.isIndexSelected(indexInParent))
1065           states.add(AccessibleState.SELECTED);
1066         return states;
1067       }
1068 
getAccessibleIndexInParent()1069       public int getAccessibleIndexInParent()
1070       {
1071         return indexInParent;
1072       }
1073 
1074     }
1075 
AccessibleAWTList()1076     public AccessibleAWTList()
1077     {
1078       addItemListener(this);
1079       addActionListener(this);
1080     }
1081 
getAccessibleRole()1082     public AccessibleRole getAccessibleRole()
1083     {
1084       return AccessibleRole.LIST;
1085     }
1086 
getAccessibleStateSet()1087     public AccessibleStateSet getAccessibleStateSet()
1088     {
1089       AccessibleStateSet states = super.getAccessibleStateSet();
1090       states.add(AccessibleState.SELECTABLE);
1091       if (isMultipleMode())
1092         states.add(AccessibleState.MULTISELECTABLE);
1093       return states;
1094     }
1095 
getAccessibleChildrenCount()1096     public int getAccessibleChildrenCount()
1097     {
1098       return getItemCount();
1099     }
1100 
getAccessibleChild(int i)1101     public Accessible getAccessibleChild(int i)
1102     {
1103       if (i >= getItemCount())
1104         return null;
1105       return new AccessibleAWTListChild(List.this, i);
1106     }
1107 
1108     /* (non-Javadoc)
1109      * @see javax.accessibility.AccessibleSelection#getAccessibleSelectionCount()
1110      */
getAccessibleSelectionCount()1111     public int getAccessibleSelectionCount()
1112     {
1113       return getSelectedIndexes().length;
1114     }
1115 
1116     /* (non-Javadoc)
1117      * @see javax.accessibility.AccessibleSelection#getAccessibleSelection()
1118      */
getAccessibleSelection()1119     public AccessibleSelection getAccessibleSelection()
1120     {
1121       return this;
1122     }
1123 
1124     /* (non-Javadoc)
1125      * @see javax.accessibility.AccessibleSelection#getAccessibleSelection(int)
1126      */
getAccessibleSelection(int i)1127     public Accessible getAccessibleSelection(int i)
1128     {
1129       int[] items = getSelectedIndexes();
1130       if (i >= items.length)
1131         return null;
1132       return new AccessibleAWTListChild(List.this, items[i]);
1133     }
1134 
1135     /* (non-Javadoc)
1136      * @see javax.accessibility.AccessibleSelection#isAccessibleChildSelected(int)
1137      */
isAccessibleChildSelected(int i)1138     public boolean isAccessibleChildSelected(int i)
1139     {
1140       return isIndexSelected(i);
1141     }
1142 
1143     /* (non-Javadoc)
1144      * @see javax.accessibility.AccessibleSelection#addAccessibleSelection(int)
1145      */
addAccessibleSelection(int i)1146     public void addAccessibleSelection(int i)
1147     {
1148       select(i);
1149     }
1150 
1151     /* (non-Javadoc)
1152      * @see javax.accessibility.AccessibleSelection#removeAccessibleSelection(int)
1153      */
removeAccessibleSelection(int i)1154     public void removeAccessibleSelection(int i)
1155     {
1156       deselect(i);
1157     }
1158 
1159     /* (non-Javadoc)
1160      * @see javax.accessibility.AccessibleSelection#clearAccessibleSelection()
1161      */
clearAccessibleSelection()1162     public void clearAccessibleSelection()
1163     {
1164       for (int i = 0; i < getItemCount(); i++)
1165         deselect(i);
1166     }
1167 
1168     /* (non-Javadoc)
1169      * @see javax.accessibility.AccessibleSelection#selectAllAccessibleSelection()
1170      */
selectAllAccessibleSelection()1171     public void selectAllAccessibleSelection()
1172     {
1173       if (isMultipleMode())
1174         for (int i = 0; i < getItemCount(); i++)
1175           select(i);
1176     }
1177 
1178     /* (non-Javadoc)
1179      * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
1180      */
itemStateChanged(ItemEvent event)1181     public void itemStateChanged(ItemEvent event)
1182     {
1183     }
1184 
1185     /* (non-Javadoc)
1186      * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
1187      */
actionPerformed(ActionEvent event)1188     public void actionPerformed(ActionEvent event)
1189     {
1190     }
1191 
1192   }
1193 
1194   /**
1195    * Gets the AccessibleContext associated with this <code>List</code>.
1196    * The context is created, if necessary.
1197    *
1198    * @return the associated context
1199    */
getAccessibleContext()1200   public AccessibleContext getAccessibleContext()
1201   {
1202     /* Create the context if this is the first request */
1203     if (accessibleContext == null)
1204       accessibleContext = new AccessibleAWTList();
1205     return accessibleContext;
1206   }
1207 
1208   /**
1209    * Generate a unique name for this <code>List</code>.
1210    *
1211    * @return A unique name for this <code>List</code>.
1212    */
generateName()1213   String generateName()
1214   {
1215     return "list" + getUniqueLong();
1216   }
1217 
getUniqueLong()1218   private static synchronized long getUniqueLong()
1219   {
1220     return next_list_number++;
1221   }
1222 } // class List
1223