Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/awt/Choice.java
38829 views
/*1* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package java.awt;2526import java.util.*;27import java.awt.peer.ChoicePeer;28import java.awt.event.*;29import java.util.EventListener;30import java.io.ObjectOutputStream;31import java.io.ObjectInputStream;32import java.io.IOException;3334import javax.accessibility.*;353637/**38* The <code>Choice</code> class presents a pop-up menu of choices.39* The current choice is displayed as the title of the menu.40* <p>41* The following code example produces a pop-up menu:42*43* <hr><blockquote><pre>44* Choice ColorChooser = new Choice();45* ColorChooser.add("Green");46* ColorChooser.add("Red");47* ColorChooser.add("Blue");48* </pre></blockquote><hr>49* <p>50* After this choice menu has been added to a panel,51* it appears as follows in its normal state:52* <p>53* <img src="doc-files/Choice-1.gif" alt="The following text describes the graphic"54* style="float:center; margin: 7px 10px;">55* <p>56* In the picture, <code>"Green"</code> is the current choice.57* Pushing the mouse button down on the object causes a menu to58* appear with the current choice highlighted.59* <p>60* Some native platforms do not support arbitrary resizing of61* <code>Choice</code> components and the behavior of62* <code>setSize()/getSize()</code> is bound by63* such limitations.64* Native GUI <code>Choice</code> components' size are often bound by such65* attributes as font size and length of items contained within66* the <code>Choice</code>.67* <p>68* @author Sami Shaio69* @author Arthur van Hoff70* @since JDK1.071*/72public class Choice extends Component implements ItemSelectable, Accessible {73/**74* The items for the <code>Choice</code>.75* This can be a <code>null</code> value.76* @serial77* @see #add(String)78* @see #addItem(String)79* @see #getItem(int)80* @see #getItemCount()81* @see #insert(String, int)82* @see #remove(String)83*/84Vector<String> pItems;8586/**87* The index of the current choice for this <code>Choice</code>88* or -1 if nothing is selected.89* @serial90* @see #getSelectedItem()91* @see #select(int)92*/93int selectedIndex = -1;9495transient ItemListener itemListener;9697private static final String base = "choice";98private static int nameCounter = 0;99100/*101* JDK 1.1 serialVersionUID102*/103private static final long serialVersionUID = -4075310674757313071L;104105static {106/* ensure that the necessary native libraries are loaded */107Toolkit.loadLibraries();108/* initialize JNI field and method ids */109if (!GraphicsEnvironment.isHeadless()) {110initIDs();111}112}113114/**115* Creates a new choice menu. The menu initially has no items in it.116* <p>117* By default, the first item added to the choice menu becomes the118* selected item, until a different selection is made by the user119* by calling one of the <code>select</code> methods.120* @exception HeadlessException if GraphicsEnvironment.isHeadless()121* returns true122* @see java.awt.GraphicsEnvironment#isHeadless123* @see #select(int)124* @see #select(java.lang.String)125*/126public Choice() throws HeadlessException {127GraphicsEnvironment.checkHeadless();128pItems = new Vector<>();129}130131/**132* Constructs a name for this component. Called by133* <code>getName</code> when the name is <code>null</code>.134*/135String constructComponentName() {136synchronized (Choice.class) {137return base + nameCounter++;138}139}140141/**142* Creates the <code>Choice</code>'s peer. This peer allows us143* to change the look144* of the <code>Choice</code> without changing its functionality.145* @see java.awt.Toolkit#createChoice(java.awt.Choice)146* @see java.awt.Component#getToolkit()147*/148public void addNotify() {149synchronized (getTreeLock()) {150if (peer == null)151peer = getToolkit().createChoice(this);152super.addNotify();153}154}155156/**157* Returns the number of items in this <code>Choice</code> menu.158* @return the number of items in this <code>Choice</code> menu159* @see #getItem160* @since JDK1.1161*/162public int getItemCount() {163return countItems();164}165166/**167* @deprecated As of JDK version 1.1,168* replaced by <code>getItemCount()</code>.169*/170@Deprecated171public int countItems() {172return pItems.size();173}174175/**176* Gets the string at the specified index in this177* <code>Choice</code> menu.178* @param index the index at which to begin179* @see #getItemCount180*/181public String getItem(int index) {182return getItemImpl(index);183}184185/*186* This is called by the native code, so client code can't187* be called on the toolkit thread.188*/189final String getItemImpl(int index) {190return pItems.elementAt(index);191}192193/**194* Adds an item to this <code>Choice</code> menu.195* @param item the item to be added196* @exception NullPointerException if the item's value is197* <code>null</code>198* @since JDK1.1199*/200public void add(String item) {201addItem(item);202}203204/**205* Obsolete as of Java 2 platform v1.1. Please use the206* <code>add</code> method instead.207* <p>208* Adds an item to this <code>Choice</code> menu.209* @param item the item to be added210* @exception NullPointerException if the item's value is equal to211* <code>null</code>212*/213public void addItem(String item) {214synchronized (this) {215insertNoInvalidate(item, pItems.size());216}217218// This could change the preferred size of the Component.219invalidateIfValid();220}221222/**223* Inserts an item to this <code>Choice</code>,224* but does not invalidate the <code>Choice</code>.225* Client methods must provide their own synchronization before226* invoking this method.227* @param item the item to be added228* @param index the new item position229* @exception NullPointerException if the item's value is equal to230* <code>null</code>231*/232private void insertNoInvalidate(String item, int index) {233if (item == null) {234throw new235NullPointerException("cannot add null item to Choice");236}237pItems.insertElementAt(item, index);238ChoicePeer peer = (ChoicePeer)this.peer;239if (peer != null) {240peer.add(item, index);241}242// no selection or selection shifted up243if (selectedIndex < 0 || selectedIndex >= index) {244select(0);245}246}247248249/**250* Inserts the item into this choice at the specified position.251* Existing items at an index greater than or equal to252* <code>index</code> are shifted up by one to accommodate253* the new item. If <code>index</code> is greater than or254* equal to the number of items in this choice,255* <code>item</code> is added to the end of this choice.256* <p>257* If the item is the first one being added to the choice,258* then the item becomes selected. Otherwise, if the259* selected item was one of the items shifted, the first260* item in the choice becomes the selected item. If the261* selected item was no among those shifted, it remains262* the selected item.263* @param item the non-<code>null</code> item to be inserted264* @param index the position at which the item should be inserted265* @exception IllegalArgumentException if index is less than 0266*/267public void insert(String item, int index) {268synchronized (this) {269if (index < 0) {270throw new IllegalArgumentException("index less than zero.");271}272/* if the index greater than item count, add item to the end */273index = Math.min(index, pItems.size());274275insertNoInvalidate(item, index);276}277278// This could change the preferred size of the Component.279invalidateIfValid();280}281282/**283* Removes the first occurrence of <code>item</code>284* from the <code>Choice</code> menu. If the item285* being removed is the currently selected item,286* then the first item in the choice becomes the287* selected item. Otherwise, the currently selected288* item remains selected (and the selected index is289* updated accordingly).290* @param item the item to remove from this <code>Choice</code> menu291* @exception IllegalArgumentException if the item doesn't292* exist in the choice menu293* @since JDK1.1294*/295public void remove(String item) {296synchronized (this) {297int index = pItems.indexOf(item);298if (index < 0) {299throw new IllegalArgumentException("item " + item +300" not found in choice");301} else {302removeNoInvalidate(index);303}304}305306// This could change the preferred size of the Component.307invalidateIfValid();308}309310/**311* Removes an item from the choice menu312* at the specified position. If the item313* being removed is the currently selected item,314* then the first item in the choice becomes the315* selected item. Otherwise, the currently selected316* item remains selected (and the selected index is317* updated accordingly).318* @param position the position of the item319* @throws IndexOutOfBoundsException if the specified320* position is out of bounds321* @since JDK1.1322*/323public void remove(int position) {324synchronized (this) {325removeNoInvalidate(position);326}327328// This could change the preferred size of the Component.329invalidateIfValid();330}331332/**333* Removes an item from the <code>Choice</code> at the334* specified position, but does not invalidate the <code>Choice</code>.335* Client methods must provide their336* own synchronization before invoking this method.337* @param position the position of the item338*/339private void removeNoInvalidate(int position) {340pItems.removeElementAt(position);341ChoicePeer peer = (ChoicePeer)this.peer;342if (peer != null) {343peer.remove(position);344}345/* Adjust selectedIndex if selected item was removed. */346if (pItems.size() == 0) {347selectedIndex = -1;348} else if (selectedIndex == position) {349select(0);350} else if (selectedIndex > position) {351select(selectedIndex-1);352}353}354355356/**357* Removes all items from the choice menu.358* @see #remove359* @since JDK1.1360*/361public void removeAll() {362synchronized (this) {363if (peer != null) {364((ChoicePeer)peer).removeAll();365}366pItems.removeAllElements();367selectedIndex = -1;368}369370// This could change the preferred size of the Component.371invalidateIfValid();372}373374/**375* Gets a representation of the current choice as a string.376* @return a string representation of the currently377* selected item in this choice menu378* @see #getSelectedIndex379*/380public synchronized String getSelectedItem() {381return (selectedIndex >= 0) ? getItem(selectedIndex) : null;382}383384/**385* Returns an array (length 1) containing the currently selected386* item. If this choice has no items, returns <code>null</code>.387* @see ItemSelectable388*/389public synchronized Object[] getSelectedObjects() {390if (selectedIndex >= 0) {391Object[] items = new Object[1];392items[0] = getItem(selectedIndex);393return items;394}395return null;396}397398/**399* Returns the index of the currently selected item.400* If nothing is selected, returns -1.401*402* @return the index of the currently selected item, or -1 if nothing403* is currently selected404* @see #getSelectedItem405*/406public int getSelectedIndex() {407return selectedIndex;408}409410/**411* Sets the selected item in this <code>Choice</code> menu to be the412* item at the specified position.413*414* <p>Note that this method should be primarily used to415* initially select an item in this component.416* Programmatically calling this method will <i>not</i> trigger417* an <code>ItemEvent</code>. The only way to trigger an418* <code>ItemEvent</code> is by user interaction.419*420* @param pos the position of the selected item421* @exception IllegalArgumentException if the specified422* position is greater than the423* number of items or less than zero424* @see #getSelectedItem425* @see #getSelectedIndex426*/427public synchronized void select(int pos) {428if ((pos >= pItems.size()) || (pos < 0)) {429throw new IllegalArgumentException("illegal Choice item position: " + pos);430}431if (pItems.size() > 0) {432selectedIndex = pos;433ChoicePeer peer = (ChoicePeer)this.peer;434if (peer != null) {435peer.select(pos);436}437}438}439440/**441* Sets the selected item in this <code>Choice</code> menu442* to be the item whose name is equal to the specified string.443* If more than one item matches (is equal to) the specified string,444* the one with the smallest index is selected.445*446* <p>Note that this method should be primarily used to447* initially select an item in this component.448* Programmatically calling this method will <i>not</i> trigger449* an <code>ItemEvent</code>. The only way to trigger an450* <code>ItemEvent</code> is by user interaction.451*452* @param str the specified string453* @see #getSelectedItem454* @see #getSelectedIndex455*/456public synchronized void select(String str) {457int index = pItems.indexOf(str);458if (index >= 0) {459select(index);460}461}462463/**464* Adds the specified item listener to receive item events from465* this <code>Choice</code> menu. Item events are sent in response466* to user input, but not in response to calls to <code>select</code>.467* If l is <code>null</code>, no exception is thrown and no action468* is performed.469* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"470* >AWT Threading Issues</a> for details on AWT's threading model.471* @param l the item listener472* @see #removeItemListener473* @see #getItemListeners474* @see #select475* @see java.awt.event.ItemEvent476* @see java.awt.event.ItemListener477* @since JDK1.1478*/479public synchronized void addItemListener(ItemListener l) {480if (l == null) {481return;482}483itemListener = AWTEventMulticaster.add(itemListener, l);484newEventsOnly = true;485}486487/**488* Removes the specified item listener so that it no longer receives489* item events from this <code>Choice</code> menu.490* If l is <code>null</code>, no exception is thrown and no491* action is performed.492* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"493* >AWT Threading Issues</a> for details on AWT's threading model.494* @param l the item listener495* @see #addItemListener496* @see #getItemListeners497* @see java.awt.event.ItemEvent498* @see java.awt.event.ItemListener499* @since JDK1.1500*/501public synchronized void removeItemListener(ItemListener l) {502if (l == null) {503return;504}505itemListener = AWTEventMulticaster.remove(itemListener, l);506}507508/**509* Returns an array of all the item listeners510* registered on this choice.511*512* @return all of this choice's <code>ItemListener</code>s513* or an empty array if no item514* listeners are currently registered515*516* @see #addItemListener517* @see #removeItemListener518* @see java.awt.event.ItemEvent519* @see java.awt.event.ItemListener520* @since 1.4521*/522public synchronized ItemListener[] getItemListeners() {523return getListeners(ItemListener.class);524}525526/**527* Returns an array of all the objects currently registered528* as <code><em>Foo</em>Listener</code>s529* upon this <code>Choice</code>.530* <code><em>Foo</em>Listener</code>s are registered using the531* <code>add<em>Foo</em>Listener</code> method.532*533* <p>534* You can specify the <code>listenerType</code> argument535* with a class literal, such as536* <code><em>Foo</em>Listener.class</code>.537* For example, you can query a538* <code>Choice</code> <code>c</code>539* for its item listeners with the following code:540*541* <pre>ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));</pre>542*543* If no such listeners exist, this method returns an empty array.544*545* @param listenerType the type of listeners requested; this parameter546* should specify an interface that descends from547* <code>java.util.EventListener</code>548* @return an array of all objects registered as549* <code><em>Foo</em>Listener</code>s on this choice,550* or an empty array if no such551* listeners have been added552* @exception ClassCastException if <code>listenerType</code>553* doesn't specify a class or interface that implements554* <code>java.util.EventListener</code>555*556* @see #getItemListeners557* @since 1.3558*/559public <T extends EventListener> T[] getListeners(Class<T> listenerType) {560EventListener l = null;561if (listenerType == ItemListener.class) {562l = itemListener;563} else {564return super.getListeners(listenerType);565}566return AWTEventMulticaster.getListeners(l, listenerType);567}568569// REMIND: remove when filtering is done at lower level570boolean eventEnabled(AWTEvent e) {571if (e.id == ItemEvent.ITEM_STATE_CHANGED) {572if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0 ||573itemListener != null) {574return true;575}576return false;577}578return super.eventEnabled(e);579}580581/**582* Processes events on this choice. If the event is an583* instance of <code>ItemEvent</code>, it invokes the584* <code>processItemEvent</code> method. Otherwise, it calls its585* superclass's <code>processEvent</code> method.586* <p>Note that if the event parameter is <code>null</code>587* the behavior is unspecified and may result in an588* exception.589*590* @param e the event591* @see java.awt.event.ItemEvent592* @see #processItemEvent593* @since JDK1.1594*/595protected void processEvent(AWTEvent e) {596if (e instanceof ItemEvent) {597processItemEvent((ItemEvent)e);598return;599}600super.processEvent(e);601}602603/**604* Processes item events occurring on this <code>Choice</code>605* menu by dispatching them to any registered606* <code>ItemListener</code> objects.607* <p>608* This method is not called unless item events are609* enabled for this component. Item events are enabled610* when one of the following occurs:611* <ul>612* <li>An <code>ItemListener</code> object is registered613* via <code>addItemListener</code>.614* <li>Item events are enabled via <code>enableEvents</code>.615* </ul>616* <p>Note that if the event parameter is <code>null</code>617* the behavior is unspecified and may result in an618* exception.619*620* @param e the item event621* @see java.awt.event.ItemEvent622* @see java.awt.event.ItemListener623* @see #addItemListener(ItemListener)624* @see java.awt.Component#enableEvents625* @since JDK1.1626*/627protected void processItemEvent(ItemEvent e) {628ItemListener listener = itemListener;629if (listener != null) {630listener.itemStateChanged(e);631}632}633634/**635* Returns a string representing the state of this <code>Choice</code>636* menu. This method is intended to be used only for debugging purposes,637* and the content and format of the returned string may vary between638* implementations. The returned string may be empty but may not be639* <code>null</code>.640*641* @return the parameter string of this <code>Choice</code> menu642*/643protected String paramString() {644return super.paramString() + ",current=" + getSelectedItem();645}646647648/* Serialization support.649*/650651/*652* Choice Serial Data Version.653* @serial654*/655private int choiceSerializedDataVersion = 1;656657/**658* Writes default serializable fields to stream. Writes659* a list of serializable <code>ItemListeners</code>660* as optional data. The non-serializable661* <code>ItemListeners</code> are detected and662* no attempt is made to serialize them.663*664* @param s the <code>ObjectOutputStream</code> to write665* @serialData <code>null</code> terminated sequence of 0666* or more pairs; the pair consists of a <code>String</code>667* and an <code>Object</code>; the <code>String</code> indicates668* the type of object and is one of the following:669* <code>itemListenerK</code> indicating an670* <code>ItemListener</code> object671*672* @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)673* @see java.awt.Component#itemListenerK674* @see #readObject(ObjectInputStream)675*/676private void writeObject(ObjectOutputStream s)677throws java.io.IOException678{679s.defaultWriteObject();680681AWTEventMulticaster.save(s, itemListenerK, itemListener);682s.writeObject(null);683}684685/**686* Reads the <code>ObjectInputStream</code> and if it687* isn't <code>null</code> adds a listener to receive688* item events fired by the <code>Choice</code> item.689* Unrecognized keys or values will be ignored.690*691* @param s the <code>ObjectInputStream</code> to read692* @exception HeadlessException if693* <code>GraphicsEnvironment.isHeadless</code> returns694* <code>true</code>695* @serial696* @see #removeItemListener(ItemListener)697* @see #addItemListener(ItemListener)698* @see java.awt.GraphicsEnvironment#isHeadless699* @see #writeObject(ObjectOutputStream)700*/701private void readObject(ObjectInputStream s)702throws ClassNotFoundException, IOException, HeadlessException703{704GraphicsEnvironment.checkHeadless();705s.defaultReadObject();706707Object keyOrNull;708while(null != (keyOrNull = s.readObject())) {709String key = ((String)keyOrNull).intern();710711if (itemListenerK == key)712addItemListener((ItemListener)(s.readObject()));713714else // skip value for unrecognized key715s.readObject();716}717}718719/**720* Initialize JNI field and method IDs721*/722private static native void initIDs();723724/////////////////725// Accessibility support726////////////////727728729/**730* Gets the <code>AccessibleContext</code> associated with this731* <code>Choice</code>. For <code>Choice</code> components,732* the <code>AccessibleContext</code> takes the form of an733* <code>AccessibleAWTChoice</code>. A new <code>AccessibleAWTChoice</code>734* instance is created if necessary.735*736* @return an <code>AccessibleAWTChoice</code> that serves as the737* <code>AccessibleContext</code> of this <code>Choice</code>738* @since 1.3739*/740public AccessibleContext getAccessibleContext() {741if (accessibleContext == null) {742accessibleContext = new AccessibleAWTChoice();743}744return accessibleContext;745}746747/**748* This class implements accessibility support for the749* <code>Choice</code> class. It provides an implementation of the750* Java Accessibility API appropriate to choice user-interface elements.751* @since 1.3752*/753protected class AccessibleAWTChoice extends AccessibleAWTComponent754implements AccessibleAction755{756/*757* JDK 1.3 serialVersionUID758*/759private static final long serialVersionUID = 7175603582428509322L;760761public AccessibleAWTChoice() {762super();763}764765/**766* Get the AccessibleAction associated with this object. In the767* implementation of the Java Accessibility API for this class,768* return this object, which is responsible for implementing the769* AccessibleAction interface on behalf of itself.770*771* @return this object772* @see AccessibleAction773*/774public AccessibleAction getAccessibleAction() {775return this;776}777778/**779* Get the role of this object.780*781* @return an instance of AccessibleRole describing the role of the782* object783* @see AccessibleRole784*/785public AccessibleRole getAccessibleRole() {786return AccessibleRole.COMBO_BOX;787}788789/**790* Returns the number of accessible actions available in this object791* If there are more than one, the first one is considered the "default"792* action of the object.793*794* @return the zero-based number of Actions in this object795*/796public int getAccessibleActionCount() {797return 0; // To be fully implemented in a future release798}799800/**801* Returns a description of the specified action of the object.802*803* @param i zero-based index of the actions804* @return a String description of the action805* @see #getAccessibleActionCount806*/807public String getAccessibleActionDescription(int i) {808return null; // To be fully implemented in a future release809}810811/**812* Perform the specified Action on the object813*814* @param i zero-based index of actions815* @return true if the action was performed; otherwise false.816* @see #getAccessibleActionCount817*/818public boolean doAccessibleAction(int i) {819return false; // To be fully implemented in a future release820}821822} // inner class AccessibleAWTChoice823824}825826827