1 /* 2 * Copyright (c) 2016, 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 @bug 8147841 27 @key headful 28 @summary Updating Tray Icon popup menu does not update menu items on Mac OS X 29 @run main/manual UpdatePopupMenu 30 */ 31 32 import java.awt.SystemTray; 33 import java.awt.TrayIcon; 34 import java.awt.PopupMenu; 35 import java.awt.MenuItem; 36 import java.awt.Image; 37 import java.awt.Graphics2D; 38 import java.awt.Color; 39 import java.awt.image.BufferedImage; 40 import java.awt.RenderingHints; 41 import java.awt.AWTException; 42 import java.awt.Button; 43 import java.awt.Frame; 44 import java.awt.GridBagConstraints; 45 import java.awt.GridBagLayout; 46 import java.awt.Panel; 47 import java.awt.TextArea; 48 import java.awt.event.ActionEvent; 49 import java.awt.event.ActionListener; 50 51 public class UpdatePopupMenu implements ActionListener { 52 53 private static final int imageSize = 32; 54 private static final int imageInset = 4; 55 private static GridBagLayout layout; 56 private static Panel mainControlPanel; 57 private static Panel resultButtonPanel; 58 private static TextArea instructionTextArea; 59 private static Button passButton; 60 private static Button failButton; 61 private static Frame mainFrame; 62 private static Thread mainThread = null; 63 private static boolean testPassed = false; 64 private static boolean isInterrupted = false; 65 private static final int testTimeOut = 300000; 66 createSystemTrayIconImage()67 private Image createSystemTrayIconImage() { 68 final BufferedImage trayImage = new BufferedImage( 69 imageSize, 70 imageSize, 71 BufferedImage.TYPE_INT_ARGB); 72 73 final Graphics2D imageGraphics = (Graphics2D) trayImage.getGraphics(); 74 75 imageGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 76 RenderingHints.VALUE_ANTIALIAS_ON); 77 78 imageGraphics.setColor(new Color(255, 255, 255, 0)); 79 imageGraphics.fillRect(0, 0, trayImage.getWidth(), 80 trayImage.getHeight()); 81 82 imageGraphics.setColor(Color.green); 83 84 int imageWidth = trayImage.getWidth() - 2 * imageInset; 85 int imageHeight = trayImage.getHeight() - 2 * imageInset; 86 87 imageGraphics.fillOval(imageInset, imageInset, imageWidth, imageHeight); 88 imageGraphics.setColor(Color.darkGray); 89 imageGraphics.drawOval(imageInset, imageInset, imageWidth, imageHeight); 90 91 return trayImage; 92 } 93 createPopupMenu(final TrayIcon trayIcon, final int menuCount)94 private PopupMenu createPopupMenu(final TrayIcon trayIcon, 95 final int menuCount) { 96 97 final PopupMenu trayIconPopupMenu = new PopupMenu(); 98 99 for (int i = 1; i <= menuCount; ++i) { 100 final MenuItem popupMenuItem = new MenuItem("MenuItem_" + i); 101 102 popupMenuItem.addActionListener(new ActionListener() { 103 @Override 104 public void actionPerformed(final ActionEvent ae) { 105 trayIcon.setPopupMenu(createPopupMenu(trayIcon, 106 menuCount + 1)); 107 } 108 }); 109 110 trayIconPopupMenu.add(popupMenuItem); 111 } 112 113 return trayIconPopupMenu; 114 } 115 createSystemTrayIcons()116 private void createSystemTrayIcons() { 117 118 final TrayIcon trayIcon = new TrayIcon(createSystemTrayIconImage()); 119 trayIcon.setImageAutoSize(true); 120 trayIcon.setToolTip("Update Popup Menu items"); 121 122 try { 123 trayIcon.setPopupMenu(createPopupMenu(trayIcon, 2)); 124 SystemTray.getSystemTray().add(trayIcon); 125 126 } catch (AWTException ex) { 127 throw new RuntimeException("System Tray cration failed"); 128 } 129 } 130 createInstructionUI()131 private void createInstructionUI() { 132 mainFrame = new Frame("Updating TrayIcon Popup Menu Item Test"); 133 layout = new GridBagLayout(); 134 mainControlPanel = new Panel(layout); 135 resultButtonPanel = new Panel(layout); 136 137 GridBagConstraints gbc = new GridBagConstraints(); 138 String instructions 139 = "INSTRUCTIONS:" 140 + "\n 1. Click on the System Tray Icon" 141 + "\n 2. Click on any of the displayed Menu items" 142 + "\n 3. Repeat step 1 and count the number of items in the " 143 + "Menu" 144 + "\n 4. The number of items in the Menu should increase by 1" 145 + "\n 5. Repeating steps 1, 2 and 3 should not break 4th step" 146 + "\n 6. Click Fail if the 4th step is broken, Otherwise " 147 + "click Pass "; 148 149 instructionTextArea = new TextArea(); 150 instructionTextArea.setText(instructions); 151 instructionTextArea.setEnabled(false); 152 instructionTextArea.setBackground(Color.white); 153 154 gbc.gridx = 0; 155 gbc.gridy = 0; 156 gbc.fill = GridBagConstraints.HORIZONTAL; 157 mainControlPanel.add(instructionTextArea, gbc); 158 159 passButton = new Button("Pass"); 160 passButton.setName("Pass"); 161 passButton.addActionListener(this); 162 163 failButton = new Button("Fail"); 164 failButton.setName("Fail"); 165 failButton.addActionListener(this); 166 167 gbc.gridx = 0; 168 gbc.gridy = 0; 169 resultButtonPanel.add(passButton, gbc); 170 gbc.gridx = 1; 171 gbc.gridy = 0; 172 resultButtonPanel.add(failButton, gbc); 173 gbc.gridx = 0; 174 gbc.gridy = 1; 175 mainControlPanel.add(resultButtonPanel, gbc); 176 177 mainFrame.add(mainControlPanel); 178 mainFrame.pack(); 179 mainFrame.setVisible(true); 180 } 181 182 @Override actionPerformed(ActionEvent ae)183 public void actionPerformed(ActionEvent ae) { 184 if (ae.getSource() instanceof Button) { 185 Button btn = (Button) ae.getSource(); 186 switch (btn.getName()) { 187 case "Pass": 188 testPassed = true; 189 isInterrupted = true; 190 mainThread.interrupt(); 191 break; 192 193 case "Fail": 194 testPassed = false; 195 isInterrupted = true; 196 mainThread.interrupt(); 197 break; 198 } 199 } 200 } 201 cleanUp()202 private static void cleanUp() { 203 mainFrame.dispose(); 204 } 205 main(final String[] args)206 public static void main(final String[] args) throws Exception { 207 if (SystemTray.isSupported()) { 208 209 UpdatePopupMenu updatePopupMenu = new UpdatePopupMenu(); 210 updatePopupMenu.createInstructionUI(); 211 updatePopupMenu.createSystemTrayIcons(); 212 213 mainThread = Thread.currentThread(); 214 try { 215 mainThread.sleep(testTimeOut); 216 } catch (InterruptedException ex) { 217 if (!testPassed) { 218 throw new RuntimeException("Updating TrayIcon popup menu" 219 + " items FAILED"); 220 } 221 } finally { 222 cleanUp(); 223 } 224 225 if (!isInterrupted) { 226 throw new RuntimeException("Test Timed out after " 227 + testTimeOut / 1000 + " seconds"); 228 } 229 230 } else { 231 System.out.println("System Tray is not supported on this platform"); 232 } 233 } 234 } 235