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