1 /* 2 * Copyright (c) 2011, 2014, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.apple.laf; 27 28 import java.awt.*; 29 import java.awt.event.*; 30 import java.awt.peer.MenuComponentPeer; 31 import java.util.Hashtable; 32 33 import javax.swing.*; 34 35 import sun.awt.SunToolkit; 36 import sun.lwawt.LWToolkit; 37 import sun.lwawt.macosx.*; 38 39 @SuppressWarnings("serial") // JDK implementation class 40 final class ScreenMenu extends Menu 41 implements ContainerListener, ComponentListener, 42 ScreenMenuPropertyHandler { 43 44 static { 45 java.security.AccessController.doPrivileged( 46 new java.security.PrivilegedAction<Void>() { 47 public Void run() { 48 System.loadLibrary("awt"); 49 return null; 50 } 51 }); 52 } 53 54 // screen menu stuff 195 SunToolkit.executeOnEventHandlerThread(fInvoker, new Runnable() { 196 @Override 197 public void run() { 198 Component target = null; 199 Rectangle targetRect = null; 200 for (int i = 0; i < fItemBounds.length; i++) { 201 final Rectangle testRect = fItemBounds[i]; 202 if (testRect != null) { 203 if (testRect.contains(x, y)) { 204 target = fInvoker.getMenuComponent(i); 205 targetRect = testRect; 206 break; 207 } 208 } 209 } 210 if (target == null && fLastMouseEventTarget == null) return; 211 212 // Send a mouseExited to the previously hilited item, if it wasn't 0. 213 if (target != fLastMouseEventTarget) { 214 if (fLastMouseEventTarget != null) { 215 LWToolkit.postEvent(new MouseEvent(fLastMouseEventTarget, MouseEvent.MOUSE_EXITED, when, modifiers, x - fLastTargetRect.x, y - fLastTargetRect.y, 0, false)); 216 } 217 // Send a mouseEntered to the current hilited item, if it wasn't 0. 218 if (target != null) { 219 LWToolkit.postEvent(new MouseEvent(target, MouseEvent.MOUSE_ENTERED, when, modifiers, x - targetRect.x, y - targetRect.y, 0, false)); 220 } 221 fLastMouseEventTarget = target; 222 fLastTargetRect = targetRect; 223 } 224 // Post a mouse event to the current item. 225 if (target == null) return; 226 LWToolkit.postEvent(new MouseEvent(target, kind, when, modifiers, x - targetRect.x, y - targetRect.y, 0, false)); 227 } 228 }); 229 } 230 231 @Override 232 @SuppressWarnings("deprecation") 233 public void addNotify() { 234 synchronized (getTreeLock()) { 235 super.addNotify(); 236 if (fModelPtr == 0) { 237 fInvoker.addContainerListener(this); 238 fInvoker.addComponentListener(this); 239 fPropertyListener = new ScreenMenuPropertyListener(this); 240 fInvoker.addPropertyChangeListener(fPropertyListener); 241 242 final Icon icon = fInvoker.getIcon(); 243 if (icon != null) { 244 setIcon(icon); 245 } 246 247 final String tooltipText = fInvoker.getToolTipText(); 248 if (tooltipText != null) { 249 setToolTipText(tooltipText); 250 } 251 final MenuComponentPeer peer = getPeer(); 252 if (peer instanceof CMenu) { 253 final CMenu menu = (CMenu) peer; 254 final long nativeMenu = menu.getNativeMenu(); 255 fModelPtr = addMenuListeners(this, nativeMenu); 256 } 257 } 258 } 259 } 260 261 @Override 262 public void removeNotify() { 263 synchronized (getTreeLock()) { 264 // Call super so that the NSMenu has been removed, before we release 265 // the delegate in removeMenuListeners 266 super.removeNotify(); 267 fItems.clear(); 268 if (fModelPtr != 0) { 269 removeMenuListeners(fModelPtr); 270 fModelPtr = 0; 271 fInvoker.removeContainerListener(this); 338 final ScreenMenu sm = (ScreenMenu)parent; 339 sm.setChildVisible(fInvoker, b); 340 } 341 } 342 } 343 344 @Override 345 public void setChildVisible(final JMenuItem child, final boolean b) { 346 fItems.remove(child); 347 updateItems(); 348 } 349 350 @Override 351 public void setAccelerator(final KeyStroke ks) {} 352 353 // only check and radio items can be indeterminate 354 @Override 355 public void setIndeterminate(boolean indeterminate) { } 356 357 @Override 358 @SuppressWarnings("deprecation") 359 public void setToolTipText(final String text) { 360 final MenuComponentPeer peer = getPeer(); 361 if (!(peer instanceof CMenuItem)) return; 362 363 final CMenuItem cmi = (CMenuItem)peer; 364 cmi.setToolTipText(text); 365 } 366 367 @Override 368 @SuppressWarnings("deprecation") 369 public void setIcon(final Icon i) { 370 final MenuComponentPeer peer = getPeer(); 371 if (!(peer instanceof CMenuItem)) return; 372 373 final CMenuItem cmi = (CMenuItem)peer; 374 Image img = null; 375 376 if (i != null) { 377 if (i.getIconWidth() > 0 && i.getIconHeight() > 0) { 378 img = AquaIcon.getImageForIcon(i); 379 } 380 } 381 cmi.setImage(img); 382 } 383 384 385 /** 386 * Gets a hashCode for a JMenu or JMenuItem or subclass so that we can compare for 387 * changes in the Menu. 388 */ 389 private static int getHashCode(final Component m) { 390 int hashCode = m.hashCode(); | 1 /* 2 * Copyright (c) 2011, 2015, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.apple.laf; 27 28 import java.awt.*; 29 import java.awt.event.*; 30 import java.util.Hashtable; 31 32 import javax.swing.*; 33 34 import sun.awt.AWTAccessor; 35 import sun.awt.SunToolkit; 36 import sun.lwawt.LWToolkit; 37 import sun.lwawt.macosx.*; 38 39 @SuppressWarnings("serial") // JDK implementation class 40 final class ScreenMenu extends Menu 41 implements ContainerListener, ComponentListener, 42 ScreenMenuPropertyHandler { 43 44 static { 45 java.security.AccessController.doPrivileged( 46 new java.security.PrivilegedAction<Void>() { 47 public Void run() { 48 System.loadLibrary("awt"); 49 return null; 50 } 51 }); 52 } 53 54 // screen menu stuff 195 SunToolkit.executeOnEventHandlerThread(fInvoker, new Runnable() { 196 @Override 197 public void run() { 198 Component target = null; 199 Rectangle targetRect = null; 200 for (int i = 0; i < fItemBounds.length; i++) { 201 final Rectangle testRect = fItemBounds[i]; 202 if (testRect != null) { 203 if (testRect.contains(x, y)) { 204 target = fInvoker.getMenuComponent(i); 205 targetRect = testRect; 206 break; 207 } 208 } 209 } 210 if (target == null && fLastMouseEventTarget == null) return; 211 212 // Send a mouseExited to the previously hilited item, if it wasn't 0. 213 if (target != fLastMouseEventTarget) { 214 if (fLastMouseEventTarget != null) { 215 LWToolkit.postEvent( 216 new MouseEvent(fLastMouseEventTarget, 217 MouseEvent.MOUSE_EXITED, when, 218 modifiers, x - fLastTargetRect.x, 219 y - fLastTargetRect.y, 0, 220 false)); 221 } 222 // Send a mouseEntered to the current hilited item, if it 223 // wasn't 0. 224 if (target != null) { 225 LWToolkit.postEvent( 226 new MouseEvent(target, MouseEvent.MOUSE_ENTERED, 227 when, modifiers, 228 x - targetRect.x, 229 y - targetRect.y, 0, false)); 230 } 231 fLastMouseEventTarget = target; 232 fLastTargetRect = targetRect; 233 } 234 // Post a mouse event to the current item. 235 if (target == null) return; 236 LWToolkit.postEvent( 237 new MouseEvent(target, kind, when, modifiers, 238 x - targetRect.x, y - targetRect.y, 0, 239 false)); 240 } 241 }); 242 } 243 244 @Override 245 public void addNotify() { 246 synchronized (getTreeLock()) { 247 super.addNotify(); 248 if (fModelPtr == 0) { 249 fInvoker.addContainerListener(this); 250 fInvoker.addComponentListener(this); 251 fPropertyListener = new ScreenMenuPropertyListener(this); 252 fInvoker.addPropertyChangeListener(fPropertyListener); 253 254 final Icon icon = fInvoker.getIcon(); 255 if (icon != null) { 256 setIcon(icon); 257 } 258 259 final String tooltipText = fInvoker.getToolTipText(); 260 if (tooltipText != null) { 261 setToolTipText(tooltipText); 262 } 263 final Object peer = AWTAccessor.getMenuComponentAccessor() 264 .getPeer(this); 265 if (peer instanceof CMenu) { 266 final CMenu menu = (CMenu) peer; 267 final long nativeMenu = menu.getNativeMenu(); 268 fModelPtr = addMenuListeners(this, nativeMenu); 269 } 270 } 271 } 272 } 273 274 @Override 275 public void removeNotify() { 276 synchronized (getTreeLock()) { 277 // Call super so that the NSMenu has been removed, before we release 278 // the delegate in removeMenuListeners 279 super.removeNotify(); 280 fItems.clear(); 281 if (fModelPtr != 0) { 282 removeMenuListeners(fModelPtr); 283 fModelPtr = 0; 284 fInvoker.removeContainerListener(this); 351 final ScreenMenu sm = (ScreenMenu)parent; 352 sm.setChildVisible(fInvoker, b); 353 } 354 } 355 } 356 357 @Override 358 public void setChildVisible(final JMenuItem child, final boolean b) { 359 fItems.remove(child); 360 updateItems(); 361 } 362 363 @Override 364 public void setAccelerator(final KeyStroke ks) {} 365 366 // only check and radio items can be indeterminate 367 @Override 368 public void setIndeterminate(boolean indeterminate) { } 369 370 @Override 371 public void setToolTipText(final String text) { 372 Object peer = AWTAccessor.getMenuComponentAccessor().getPeer(this); 373 if (!(peer instanceof CMenuItem)) return; 374 375 final CMenuItem cmi = (CMenuItem)peer; 376 cmi.setToolTipText(text); 377 } 378 379 @Override 380 public void setIcon(final Icon i) { 381 Object peer = AWTAccessor.getMenuComponentAccessor().getPeer(this); 382 if (!(peer instanceof CMenuItem)) return; 383 384 final CMenuItem cmi = (CMenuItem)peer; 385 Image img = null; 386 387 if (i != null) { 388 if (i.getIconWidth() > 0 && i.getIconHeight() > 0) { 389 img = AquaIcon.getImageForIcon(i); 390 } 391 } 392 cmi.setImage(img); 393 } 394 395 396 /** 397 * Gets a hashCode for a JMenu or JMenuItem or subclass so that we can compare for 398 * changes in the Menu. 399 */ 400 private static int getHashCode(final Component m) { 401 int hashCode = m.hashCode(); |