Path: blob/master/src/java.desktop/macosx/classes/sun/lwawt/LWChoicePeer.java
41153 views
/*1* Copyright (c) 2011, 2018, 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*/2425package sun.lwawt;2627import java.awt.Point;28import java.awt.Choice;2930import java.awt.event.ItemEvent;31import java.awt.event.ItemListener;32import java.awt.peer.ChoicePeer;3334import javax.accessibility.Accessible;35import javax.swing.JComboBox;36import javax.swing.SwingUtilities;37import javax.swing.JPopupMenu;3839/**40* Lightweight implementation of {@link ChoicePeer}. Delegates most of the work41* to the {@link JComboBox}.42*/43final class LWChoicePeer extends LWComponentPeer<Choice, JComboBox<String>>44implements ChoicePeer, ItemListener {4546/**47* According to Choice specification item events are sent in response to48* user input, but not in response to calls to select(). But JComboBox are49* sent item events in both cases. Should be used under delegateLock.50*/51private boolean skipPostMessage;5253LWChoicePeer(final Choice target,54final PlatformComponent platformComponent) {55super(target, platformComponent);56}5758@Override59JComboBox<String> createDelegate() {60return new JComboBoxDelegate();61}6263@Override64void initializeImpl() {65super.initializeImpl();66final Choice choice = getTarget();67final JComboBox<String> combo = getDelegate();68synchronized (getDelegateLock()) {69final int count = choice.getItemCount();70for (int i = 0; i < count; ++i) {71combo.addItem(choice.getItem(i));72}73select(choice.getSelectedIndex());7475// NOTE: the listener must be added at the very end, otherwise it76// fires events upon initialization of the combo box.77combo.addItemListener(this);78}79}8081@Override82public void itemStateChanged(final ItemEvent e) {83// AWT Choice sends SELECTED event only whereas JComboBox84// sends both SELECTED and DESELECTED.85if (e.getStateChange() == ItemEvent.SELECTED) {86synchronized (getDelegateLock()) {87if (skipPostMessage) {88return;89}90getTarget().select(getDelegate().getSelectedIndex());91}92postEvent(new ItemEvent(getTarget(), ItemEvent.ITEM_STATE_CHANGED,93e.getItem(), ItemEvent.SELECTED));94}95}9697@Override98public void add(final String item, final int index) {99synchronized (getDelegateLock()) {100getDelegate().insertItemAt(item, index);101}102}103104@Override105public void remove(final int index) {106synchronized (getDelegateLock()) {107// We shouldn't post event, if selected item was removed.108skipPostMessage = true;109getDelegate().removeItemAt(index);110skipPostMessage = false;111}112}113114@Override115public void removeAll() {116synchronized (getDelegateLock()) {117getDelegate().removeAllItems();118}119}120121@Override122public void select(final int index) {123synchronized (getDelegateLock()) {124if (index != getDelegate().getSelectedIndex()) {125skipPostMessage = true;126getDelegate().setSelectedIndex(index);127skipPostMessage = false;128}129}130}131132@Override133public boolean isFocusable() {134return true;135}136137@SuppressWarnings("serial")// Safe: outer class is non-serializable.138private final class JComboBoxDelegate extends JComboBox<String> {139140@Override141public boolean hasFocus() {142return getTarget().hasFocus();143}144145//Needed for proper popup menu location146@Override147public Point getLocationOnScreen() {148return LWChoicePeer.this.getLocationOnScreen();149}150151@Override152public void firePopupMenuWillBecomeVisible() {153super.firePopupMenuWillBecomeVisible();154SwingUtilities.invokeLater(() -> {155JPopupMenu popupMenu = getPopupMenu();156// Need to override the invoker for proper grab handling157if (popupMenu != null158&& popupMenu.isShowing()159&& popupMenu.getInvoker() != getTarget()) {160// The popup is now visible with correct location161// Save it and restore after toggling visibility and changing invoker162Point loc = popupMenu.getLocationOnScreen();163SwingUtilities.convertPointFromScreen(loc, this);164popupMenu.setVisible(false);165popupMenu.show(getTarget(), loc.x, loc.y);166}167});168}169170private JPopupMenu getPopupMenu() {171for (int i = 0; i < getAccessibleContext().getAccessibleChildrenCount(); i++) {172Accessible child = getAccessibleContext().getAccessibleChild(i);173if (child instanceof JPopupMenu) {174return (JPopupMenu) child;175}176}177return null;178}179}180}181182183