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 import java.awt.Point;
25 import java.awt.Rectangle;
26 import java.awt.Robot;
27 import java.awt.event.InputEvent;
28 import javax.swing.JCheckBoxMenuItem;
29 import javax.swing.JComponent;
30 import javax.swing.JFrame;
31 import javax.swing.JMenu;
32 import javax.swing.JMenuBar;
33 import javax.swing.JMenuItem;
34 import javax.swing.JRadioButtonMenuItem;
35 import javax.swing.SwingUtilities;
36 import javax.swing.UIManager;
37 
38 /**
39  * @test
40  * @key headful
41  * @bug 8158566 8160879 8160977 8158566
42  * @summary Provide a Swing property which modifies MenuItemUI behaviour
43  */
44 
45 public class CloseOnMouseClickPropertyTest {
46 
47     private static final String CHECK_BOX_PROP = "CheckBoxMenuItem."
48             + "doNotCloseOnMouseClick";
49     private static final String RADIO_BUTTON_PROP = "RadioButtonMenuItem"
50             + ".doNotCloseOnMouseClick";
51 
52     private static JFrame frame;
53     private static JMenu menu;
54 
55     private static TestItem[] TEST_ITEMS = {
56         new TestItem(TestType.CHECK_BOX_MENU_ITEM, true, true),
57         new TestItem(TestType.CHECK_BOX_MENU_ITEM, true, false),
58         new TestItem(TestType.CHECK_BOX_MENU_ITEM, false, true),
59         new TestItem(TestType.CHECK_BOX_MENU_ITEM, false, false),
60 
61         new TestItem(TestType.CHECK_BOX_MENU_ITEM, null, true),
62         new TestItem(TestType.CHECK_BOX_MENU_ITEM, null, false),
63         new TestItem(TestType.CHECK_BOX_MENU_ITEM, true, null),
64         new TestItem(TestType.CHECK_BOX_MENU_ITEM, false, null),
65 
66 
67         new TestItem(TestType.RADIO_BUTTON_MENU_ITEM, true, true),
68         new TestItem(TestType.RADIO_BUTTON_MENU_ITEM, true, false),
69         new TestItem(TestType.RADIO_BUTTON_MENU_ITEM, false, true),
70         new TestItem(TestType.RADIO_BUTTON_MENU_ITEM, false, false),
71 
72         new TestItem(TestType.RADIO_BUTTON_MENU_ITEM, true, null),
73         new TestItem(TestType.RADIO_BUTTON_MENU_ITEM, false, null),
74         new TestItem(TestType.RADIO_BUTTON_MENU_ITEM, null, true),
75         new TestItem(TestType.RADIO_BUTTON_MENU_ITEM, null, false),
76 
77         new TestItem(TestType.MENU_ITEM, true, true),
78         new TestItem(TestType.MENU_ITEM, true, false),
79         new TestItem(TestType.MENU_ITEM, false, true),
80         new TestItem(TestType.MENU_ITEM, false, false),
81 
82         new TestItem(TestType.MENU_ITEM, true, null),
83         new TestItem(TestType.MENU_ITEM, false, null),
84         new TestItem(TestType.MENU_ITEM, null, true),
85         new TestItem(TestType.MENU_ITEM, null, false),
86     };
87 
main(String[] args)88     public static void main(String[] args) throws Exception {
89 
90         for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
91             UIManager.setLookAndFeel(info.getClassName());
92             for (TestItem testItem : TEST_ITEMS) {
93                 test(testItem);
94             }
95         }
96     }
97 
test(TestItem item)98     private static void test(TestItem item) throws Exception {
99 
100         Robot robot = new Robot();
101         robot.setAutoDelay(50);
102         SwingUtilities.invokeAndWait(() -> createAndShowGUI(item));
103         robot.waitForIdle();
104 
105         Point point = getClickPoint(true);
106         robot.mouseMove(point.x, point.y);
107         robot.mousePress(InputEvent.BUTTON1_MASK);
108         robot.mouseRelease(InputEvent.BUTTON1_MASK);
109         robot.waitForIdle();
110 
111         point = getClickPoint(false);
112         robot.mouseMove(point.x, point.y);
113         robot.mousePress(InputEvent.BUTTON1_MASK);
114         robot.mouseRelease(InputEvent.BUTTON1_MASK);
115         robot.waitForIdle();
116 
117         SwingUtilities.invokeAndWait(() -> {
118             JMenuItem menuItem = menu.getItem(0);
119             boolean isShowing = menuItem.isShowing();
120             frame.dispose();
121             if (isShowing ^ item.doNotCloseOnMouseClick()) {
122                 throw new RuntimeException("Property is not taken into account!");
123             }
124         });
125     }
126 
createAndShowGUI(TestItem testItem)127     private static void createAndShowGUI(TestItem testItem) {
128 
129         frame = new JFrame();
130         frame.setSize(300, 300);
131         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
132 
133         JMenuBar menuBar = new JMenuBar();
134         menu = new JMenu("Menu");
135         JMenuItem menuItem = testItem.getMenuItem();
136         testItem.setProperties(menuItem);
137         menu.add(menuItem);
138         menuBar.add(menu);
139 
140         frame.setJMenuBar(menuBar);
141         frame.setVisible(true);
142     }
143 
getClickPoint(boolean parent)144     private static Point getClickPoint(boolean parent) throws Exception {
145         Point points[] = new Point[1];
146 
147         SwingUtilities.invokeAndWait(() -> {
148 
149             JComponent comp = parent ? menu : menu.getItem(0);
150 
151             Point point = comp.getLocationOnScreen();
152             Rectangle bounds = comp.getBounds();
153             point.x += bounds.getWidth() / 2;
154             point.y += bounds.getHeight() / 2;
155 
156             points[0] = point;
157         });
158 
159         return points[0];
160     }
161 
162     enum TestType {
163 
164         MENU_ITEM,
165         CHECK_BOX_MENU_ITEM,
166         RADIO_BUTTON_MENU_ITEM
167     }
168 
169     static class TestItem {
170 
171         TestType type;
172         Boolean compDoNotCloseOnMouseClick;
173         Boolean lafDoNotCloseOnMouseClick;
174 
TestItem(TestType type, Boolean compDoNotCloseOnMouseClick, Boolean lafDoNotCloseOnMouseClick)175         public TestItem(TestType type,
176                         Boolean compDoNotCloseOnMouseClick,
177                         Boolean lafDoNotCloseOnMouseClick)
178         {
179             this.type = type;
180             this.compDoNotCloseOnMouseClick = compDoNotCloseOnMouseClick;
181             this.lafDoNotCloseOnMouseClick = lafDoNotCloseOnMouseClick;
182         }
183 
doNotCloseOnMouseClick()184         boolean doNotCloseOnMouseClick() {
185             switch (type) {
186                 case MENU_ITEM:
187                     return false;
188                 default:
189                     return compDoNotCloseOnMouseClick != null
190                             ? compDoNotCloseOnMouseClick
191                             : lafDoNotCloseOnMouseClick;
192             }
193         }
194 
setProperties(JMenuItem menuItem)195         void setProperties(JMenuItem menuItem) {
196             switch (type) {
197                 case CHECK_BOX_MENU_ITEM:
198                     menuItem.putClientProperty(CHECK_BOX_PROP, compDoNotCloseOnMouseClick);
199                     UIManager.put(CHECK_BOX_PROP, lafDoNotCloseOnMouseClick);
200                     break;
201                 case RADIO_BUTTON_MENU_ITEM:
202                     menuItem.putClientProperty(RADIO_BUTTON_PROP, compDoNotCloseOnMouseClick);
203                     UIManager.put(RADIO_BUTTON_PROP, lafDoNotCloseOnMouseClick);
204                     break;
205                 default:
206                     menuItem.putClientProperty(CHECK_BOX_PROP, compDoNotCloseOnMouseClick);
207                     menuItem.putClientProperty(RADIO_BUTTON_PROP, compDoNotCloseOnMouseClick);
208                     UIManager.put(CHECK_BOX_PROP, lafDoNotCloseOnMouseClick);
209                     UIManager.put(RADIO_BUTTON_PROP, lafDoNotCloseOnMouseClick);
210             }
211         }
212 
getMenuItem()213         JMenuItem getMenuItem() {
214             switch (type) {
215                 case CHECK_BOX_MENU_ITEM:
216                     return new JCheckBoxMenuItem("Check Box");
217                 case RADIO_BUTTON_MENU_ITEM:
218                     return new JRadioButtonMenuItem("Radio Button");
219                 default:
220                     return new JMenuItem("Menu Item");
221             }
222         }
223     }
224 }
225 
226