1 /* 2 * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @key headful 27 * @bug 8041909 28 * @summary Test to check JComboBox does not lose its ability to invoke 29 * registerd ActionListener in case of exception in ActionListener 30 * @run main ActionListenerExceptionTest 31 */ 32 33 import java.awt.AWTEvent; 34 import java.awt.AWTException; 35 import java.awt.Dimension; 36 import java.awt.EventQueue; 37 import java.awt.Point; 38 import java.awt.Robot; 39 import java.awt.Toolkit; 40 import java.awt.event.ActionEvent; 41 import java.awt.event.ActionListener; 42 import java.awt.event.InputEvent; 43 import java.util.logging.Level; 44 import java.util.logging.Logger; 45 import javax.swing.JComboBox; 46 import javax.swing.JComponent; 47 import javax.swing.JFrame; 48 import javax.swing.JPopupMenu; 49 import javax.swing.JScrollPane; 50 import javax.swing.SwingUtilities; 51 52 public class ActionListenerExceptionTest { 53 54 static final int TOTAL_MENU_ITEMS = 3; 55 private volatile int count = 0; 56 private JFrame frame; 57 private JComboBox combo; 58 59 private int menuItemHeight = 0; 60 private int yPos = 0; 61 private Point cbPos = null; 62 private Dimension cbSize = null; 63 64 65 public static void main(String[] args) throws Exception { 66 67 // See EvenQueueProxy class description below. 68 EventQueue queue = Toolkit.getDefaultToolkit().getSystemEventQueue(); 69 queue.push(new EventQueueProxy()); 70 71 ActionListenerExceptionTest testObject = new ActionListenerExceptionTest(); 72 73 testObject.createGUI(); 74 75 testObject.test(); 76 77 testObject.disposeGUI(); 78 79 if (testObject.getCount() != TOTAL_MENU_ITEMS) { 80 throw new RuntimeException("ActionListener is not invoked expected number of times"); 81 } 82 } 83 84 private void createGUI() throws Exception { 85 SwingUtilities.invokeAndWait(new Runnable() { 86 public void run() { 87 frame = new JFrame(); 88 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 89 90 combo = new JComboBox(new String[]{"One", "Two", "Three"}); 91 combo.addActionListener(new ActionListener() { 92 93 @Override 94 public void actionPerformed(ActionEvent e) { 95 count++; 96 throw new RuntimeException(); 97 } 98 }); 99 combo.setSize(200, 20); 100 frame.add(combo); 101 frame.pack(); 102 frame.setLocationRelativeTo(null); 103 frame.setVisible(true); 104 105 } 106 }); 107 } 108 109 private void disposeGUI() throws Exception { 110 SwingUtilities.invokeAndWait(new Runnable() { 111 public void run() { 112 frame.dispose(); 113 } 114 }); 115 } 116 117 private void test() throws Exception { 118 Robot testRobot = new Robot(); 119 testRobot.delay(200); // delay to make test frame visible on screen 120 121 SwingUtilities.invokeAndWait(new Runnable() { 122 public void run() { 123 cbPos = combo.getLocationOnScreen(); 124 cbSize = combo.getSize(); 125 } 126 }); 127 128 Point center = new Point((cbPos.x + cbSize.width / 2), (cbPos.y + cbSize.height - 5)); 129 testRobot.mouseMove(center.x, center.y); 130 testRobot.delay(100); 131 132 testRobot.mousePress(InputEvent.BUTTON1_DOWN_MASK); 133 testRobot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); 134 testRobot.delay(500); // delay to make popup visible 135 136 SwingUtilities.invokeAndWait(new Runnable() { 137 public void run() { 138 Object comp = combo.getUI().getAccessibleChild(combo, 0); 139 int i = 0; 140 JComponent scrollPane; 141 do { 142 scrollPane = (JComponent) ((JPopupMenu) comp).getComponent(i++); 143 } while (!(scrollPane instanceof JScrollPane)); 144 145 menuItemHeight = scrollPane.getSize().height / TOTAL_MENU_ITEMS; 146 yPos = scrollPane.getLocationOnScreen().y + menuItemHeight / 2; 147 } 148 }); 149 150 for (int i = 0; i < TOTAL_MENU_ITEMS; i++) { 151 152 testRobot.mouseMove(center.x, yPos); 153 154 testRobot.mousePress(InputEvent.BUTTON1_DOWN_MASK); 155 testRobot.delay(100); 156 testRobot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); 157 testRobot.delay(200); 158 159 yPos += menuItemHeight; 160 } 161 162 } 163 164 private int getCount() { 165 return count; 166 } 167 } 168 169 // Proxy class to invoke dispatchEvent and catch exceptions 170 // 171 // This is needed in order to test Exceptions from ActionListener 172 // Without this, jtreg reports test failure at first exception from ActionListener and 173 // we cannot test whether ActionListener is invoked again 174 class EventQueueProxy extends EventQueue { 175 176 protected void dispatchEvent(AWTEvent evt) { 177 try { 178 super.dispatchEvent(evt); 179 } catch (Exception e) { 180 System.out.println("Intentionally consumed Exception from ActionListener"); 181 e.printStackTrace(); 182 } 183 } 184 } 185