--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java Thu May 14 02:05:02 2015 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java Thu May 14 18:23:39 2015 +0300
@@ -150,6 +150,8 @@
*/
protected KeyListener popupKeyListener;
+ private MouseWheelListener mouseWheelListener;
+
// This is used for knowing when to cache the minimum preferred size.
// If the data in the list changes, the cached value get marked for recalc.
// Added to the current JComboBox model
@@ -413,6 +415,10 @@
comboBox.getModel().addListDataListener( listDataListener );
}
}
+
+ if ((mouseWheelListener = createMouseWheelListener()) != null) {
+ comboBox.addMouseWheelListener(mouseWheelListener);
+ }
}
/**
@@ -459,6 +465,9 @@
comboBox.getModel().removeListDataListener( listDataListener );
}
}
+ if (mouseWheelListener != null) {
+ comboBox.removeMouseWheelListener(mouseWheelListener);
+ }
}
/**
@@ -572,6 +581,10 @@
return handler;
}
+ private MouseWheelListener createMouseWheelListener() {
+ return getHandler();
+ }
+
//
// end UI Initialization
//======================
@@ -1723,7 +1736,8 @@
//
private class Handler implements ActionListener, FocusListener,
KeyListener, LayoutManager,
- ListDataListener, PropertyChangeListener {
+ ListDataListener, PropertyChangeListener,
+ MouseWheelListener {
//
// PropertyChangeListener
//
@@ -1997,21 +2011,25 @@
public void actionPerformed(ActionEvent evt) {
Object item = comboBox.getEditor().getItem();
if (item != null) {
- if(!comboBox.isPopupVisible() && !item.equals(comboBox.getSelectedItem())) {
- comboBox.setSelectedItem(comboBox.getEditor().getItem());
- }
- ActionMap am = comboBox.getActionMap();
- if (am != null) {
- Action action = am.get("enterPressed");
- if (action != null) {
- action.actionPerformed(new ActionEvent(comboBox, evt.getID(),
- evt.getActionCommand(),
- evt.getModifiers()));
+ if (!comboBox.isPopupVisible() && !item.equals(comboBox.getSelectedItem())) {
+ comboBox.setSelectedItem(comboBox.getEditor().getItem());
+ }
+ ActionMap am = comboBox.getActionMap();
+ if (am != null) {
+ Action action = am.get("enterPressed");
+ if (action != null) {
+ action.actionPerformed(new ActionEvent(comboBox, evt.getID(),
+ evt.getActionCommand(),
+ evt.getModifiers()));
+ }
}
}
- }
+ }
+
+ public void mouseWheelMoved(MouseWheelEvent e) {
+ e.consume();
+ }
}
- }
class DefaultKeySelectionManager implements JComboBox.KeySelectionManager, UIResource {
private String prefix = "";
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java Thu May 14 02:05:02 2015 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java Thu May 14 18:23:39 2015 +0300
@@ -184,6 +184,8 @@
*/
protected ItemListener itemListener;
+ private MouseWheelListener scrollerMouseWheelListener;
+
/**
* This protected field is implementation specific. Do not access directly
* or override.
@@ -311,6 +313,7 @@
uninstallComboBoxModelListeners(comboBox.getModel());
uninstallKeyboardActions();
uninstallListListeners();
+ uninstallScrollerListeners();
// We do this, otherwise the listener the ui installs on
// the model (the combobox model in this case) will keep a
// reference to the list, causing the list (and us) to never get gced.
@@ -608,6 +611,7 @@
scroller.setFocusable( false );
scroller.getVerticalScrollBar().setFocusable( false );
scroller.setBorder( null );
+ installScrollerListeners();
}
/**
@@ -624,6 +628,20 @@
setFocusable( false );
}
+ private void installScrollerListeners() {
+ scrollerMouseWheelListener = getHandler();
+ if (scrollerMouseWheelListener != null) {
+ scroller.addMouseWheelListener(scrollerMouseWheelListener);
+ }
+ }
+
+ private void uninstallScrollerListeners() {
+ if (scrollerMouseWheelListener != null) {
+ scroller.removeMouseWheelListener(scrollerMouseWheelListener);
+ scrollerMouseWheelListener = null;
+ }
+ }
+
/**
* This method adds the necessary listeners to the JComboBox.
*/
@@ -835,8 +853,8 @@
private class Handler implements ItemListener, MouseListener,
- MouseMotionListener, PropertyChangeListener,
- Serializable {
+ MouseMotionListener, MouseWheelListener,
+ PropertyChangeListener, Serializable {
//
// MouseListener
// NOTE: this is added to both the JList and JComboBox
@@ -1024,6 +1042,13 @@
setListSelection(comboBox.getSelectedIndex());
}
}
+
+ //
+ // MouseWheelListener
+ //
+ public void mouseWheelMoved(MouseWheelEvent e) {
+ e.consume();
+ }
}
//
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java Thu May 14 02:05:02 2015 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java Thu May 14 18:23:39 2015 +0300
@@ -914,7 +914,9 @@
processMouseEvent(me);
break;
case MouseEvent.MOUSE_WHEEL:
- if (isInPopup(src)) {
+ if (isInPopup(src)
+ || ((src instanceof JComboBox) && ((JComboBox) src).isPopupVisible())) {
+
return;
}
cancelPopupMenu();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JComboBox/8033069/bug8033069NoScrollBar.java Thu May 14 18:23:39 2015 +0300
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.AWTException;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import javax.swing.JComboBox;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UIManager.LookAndFeelInfo;
+import javax.swing.UnsupportedLookAndFeelException;
+
+/* @test
+ * @bug 8033069
+ * @summary Checks that JComboBox popup does not close when mouse wheel is
+ * rotated over combo box and over its popup. The case where popup
+ * has no scroll bar.
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main bug8033069NoScrollBar
+ * @author Alexey Ivanov
+ */
+public class bug8033069NoScrollBar implements Runnable {
+
+ private static final String[] NO_SCROLL_ITEMS = new String[] {
+ "A", "B", "C", "D", "E", "F"
+ };
+
+ private final Robot robot;
+
+ private final String[] items;
+
+ private JFrame frame;
+ private JComboBox cb1;
+ private JComboBox cb2;
+
+ public static void main(String[] args) throws Exception {
+ iterateLookAndFeels(new bug8033069NoScrollBar(NO_SCROLL_ITEMS));
+ }
+
+ protected static void iterateLookAndFeels(final bug8033069NoScrollBar test) throws Exception {
+ LookAndFeelInfo[] lafInfo = UIManager.getInstalledLookAndFeels();
+ for (LookAndFeelInfo info : lafInfo) {
+ try {
+ UIManager.setLookAndFeel(info.getClassName());
+ System.out.println("Look and Feel: " + info.getClassName());
+ test.runTest();
+ } catch (UnsupportedLookAndFeelException e) {
+ System.out.println("Skipping unsupported LaF: " + info);
+ }
+ }
+ }
+
+ public bug8033069NoScrollBar(String[] items) throws AWTException {
+ this.items = items;
+
+ robot = new Robot();
+ robot.setAutoDelay(200);
+ }
+
+ private void setupUI() {
+ frame = new JFrame();
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ cb1 = new JComboBox<>(items);
+ cb2 = new JComboBox<>(items);
+ JPanel panel = new JPanel(new GridLayout(1, 2));
+ panel.add(cb1);
+ panel.add(cb2);
+
+ frame.add(panel);
+
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+ public void runTest() throws Exception {
+ try {
+ SwingUtilities.invokeAndWait(this);
+
+ robot.waitForIdle();
+ assertFalse("cb1 popup is visible",
+ Util.invokeOnEDT(cb1::isPopupVisible));
+
+ // Move mouse pointer to the center of the fist combo box
+ Point p = cb1.getLocationOnScreen();
+ Dimension d = cb1.getSize();
+ robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2);
+ // Click it to open popup
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+
+ robot.waitForIdle();
+ assertTrue("cb1 popup is not visible",
+ Util.invokeOnEDT(cb1::isPopupVisible));
+
+ robot.mouseWheel(1);
+ robot.waitForIdle();
+ assertTrue("cb1 popup is not visible after mouse wheel up on combo box",
+ Util.invokeOnEDT(cb1::isPopupVisible));
+
+ robot.mouseWheel(-1);
+ robot.waitForIdle();
+ assertTrue("cb1 popup is not visible after mouse wheel down on combo box",
+ Util.invokeOnEDT(cb1::isPopupVisible));
+
+ // Move mouse down on the popup
+ robot.mouseMove(p.x + d.width / 2, p.y + d.height * 3);
+
+ robot.mouseWheel(1);
+ robot.waitForIdle();
+ assertTrue("cb1 popup is not visible after mouse wheel up on popup",
+ Util.invokeOnEDT(cb1::isPopupVisible));
+
+ robot.mouseWheel(-1);
+ robot.waitForIdle();
+ assertTrue("cb1 popup is not visible after mouse wheel down on popup",
+ Util.invokeOnEDT(cb1::isPopupVisible));
+
+
+ // Move mouse pointer to the center of the second combo box
+ p = cb2.getLocationOnScreen();
+ d = cb2.getSize();
+ robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2);
+
+ robot.mouseWheel(1);
+ robot.waitForIdle();
+ assertFalse("cb1 popup is visible after mouse wheel up on cb2",
+ Util.invokeOnEDT(cb1::isPopupVisible));
+ } finally {
+ if (frame != null) {
+ frame.dispose();
+ }
+ }
+
+ System.out.println("Test passed");
+ }
+
+ @Override
+ public void run() {
+ setupUI();
+ }
+
+ private static void assertTrue(String message, boolean value) {
+ assertEquals(message, true, value);
+ }
+
+ private static void assertFalse(String message, boolean value) {
+ assertEquals(message, false, value);
+ }
+
+ private static void assertEquals(String message, boolean expected, boolean actual) {
+ if (expected != actual) {
+ throw new RuntimeException(message);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JComboBox/8033069/bug8033069ScrollBar.java Thu May 14 18:23:39 2015 +0300
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.AWTException;
+
+/* @test
+ * @bug 8033069
+ * @summary Checks that JComboBox popup does not close when mouse wheel is
+ * rotated over combo box and over its popup. The case where
+ * popup has scroll bar.
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main bug8033069ScrollBar
+ * @author Alexey Ivanov
+ */
+public class bug8033069ScrollBar extends bug8033069NoScrollBar {
+
+ private static final String[] SCROLL_ITEMS = new String[] {
+ "A", "B", "C", "D", "E", "F",
+ "G", "H", "I", "J", "K", "L",
+ "M", "N", "O", "P", "Q", "R"
+ };
+
+ public static void main(String[] args) throws Exception {
+ iterateLookAndFeels(new bug8033069ScrollBar(SCROLL_ITEMS));
+ }
+
+ public bug8033069ScrollBar(String[] items) throws AWTException {
+ super(items);
+ }
+
+}