Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/classes/sun/lwawt/LWChoicePeer.java
38827 views
/*1* Copyright (c) 2011, 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*/242526package sun.lwawt;2728import java.awt.*;29import java.awt.event.ItemEvent;30import java.awt.event.ItemListener;31import java.awt.peer.ChoicePeer;3233import javax.accessibility.Accessible;34import javax.swing.*;3536/**37* Lightweight implementation of {@link ChoicePeer}. Delegates most of the work38* to the {@link JComboBox}.39*/40final class LWChoicePeer extends LWComponentPeer<Choice, JComboBox<String>>41implements ChoicePeer, ItemListener {4243/**44* According to Choice specification item events are sent in response to45* user input, but not in response to calls to select(). But JComboBox are46* sent item events in both cases. Should be used under delegateLock.47*/48private boolean skipPostMessage;4950LWChoicePeer(final Choice target,51final PlatformComponent platformComponent) {52super(target, platformComponent);53}5455@Override56JComboBox<String> createDelegate() {57return new JComboBoxDelegate();58}5960@Override61void initializeImpl() {62super.initializeImpl();63final Choice choice = getTarget();64final JComboBox<String> combo = getDelegate();65synchronized (getDelegateLock()) {66final int count = choice.getItemCount();67for (int i = 0; i < count; ++i) {68combo.addItem(choice.getItem(i));69}70select(choice.getSelectedIndex());7172// NOTE: the listener must be added at the very end, otherwise it73// fires events upon initialization of the combo box.74combo.addItemListener(this);75}76}7778@Override79public void itemStateChanged(final ItemEvent e) {80// AWT Choice sends SELECTED event only whereas JComboBox81// sends both SELECTED and DESELECTED.82if (e.getStateChange() == ItemEvent.SELECTED) {83synchronized (getDelegateLock()) {84if (skipPostMessage) {85return;86}87getTarget().select(getDelegate().getSelectedIndex());88}89postEvent(new ItemEvent(getTarget(), ItemEvent.ITEM_STATE_CHANGED,90e.getItem(), ItemEvent.SELECTED));91}92}9394@Override95public void add(final String item, final int index) {96synchronized (getDelegateLock()) {97getDelegate().insertItemAt(item, index);98}99}100101@Override102public void remove(final int index) {103synchronized (getDelegateLock()) {104// We shouldn't post event, if selected item was removed.105skipPostMessage = true;106getDelegate().removeItemAt(index);107skipPostMessage = false;108}109}110111@Override112public void removeAll() {113synchronized (getDelegateLock()) {114getDelegate().removeAllItems();115}116}117118@Override119public void select(final int index) {120synchronized (getDelegateLock()) {121if (index != getDelegate().getSelectedIndex()) {122skipPostMessage = true;123getDelegate().setSelectedIndex(index);124skipPostMessage = false;125}126}127}128129@Override130public boolean isFocusable() {131return true;132}133134@SuppressWarnings("serial")// Safe: outer class is non-serializable.135private final class JComboBoxDelegate extends JComboBox<String> {136137// Empty non private constructor was added because access to this138// class shouldn't be emulated by a synthetic accessor method.139JComboBoxDelegate() {140super();141}142143@Override144public boolean hasFocus() {145return getTarget().hasFocus();146}147148//Needed for proper popup menu location149@Override150public Point getLocationOnScreen() {151return LWChoicePeer.this.getLocationOnScreen();152}153154/**155* We should post ITEM_STATE_CHANGED event when the same element is156* reselected.157*/158@Override159public void setSelectedItem(final Object anObject) {160final Object oldSelection = selectedItemReminder;161if (oldSelection != null && oldSelection.equals(anObject)) {162selectedItemChanged();163}164super.setSelectedItem(anObject);165}166167@Override168public void firePopupMenuWillBecomeVisible() {169super.firePopupMenuWillBecomeVisible();170SwingUtilities.invokeLater(() -> {171JPopupMenu popupMenu = getPopupMenu();172// Need to override the invoker for proper grab handling173if (popupMenu != null174&& popupMenu.isShowing()175&& popupMenu.getInvoker() != getTarget()) {176// The popup is now visible with correct location177// Save it and restore after toggling visibility and changing invoker178Point loc = popupMenu.getLocationOnScreen();179SwingUtilities.convertPointFromScreen(loc, this);180popupMenu.setVisible(false);181popupMenu.show(getTarget(), loc.x, loc.y);182}183});184}185186private JPopupMenu getPopupMenu() {187for (int i = 0; i < getAccessibleContext().getAccessibleChildrenCount(); i++) {188Accessible child = getAccessibleContext().getAccessibleChild(i);189if (child instanceof JPopupMenu) {190return (JPopupMenu) child;191}192}193return null;194}195}196}197198199