1 /* 2 * Copyright (c) 2011, 2012, 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.beans.*; 30 31 import javax.swing.*; 32 import javax.swing.plaf.*; 33 import javax.swing.plaf.basic.BasicMenuItemUI; 34 35 import apple.laf.JRSUIConstants.Size; 36 37 // TODO: no screen menu bar for now 38 public class AquaMenuItemUI extends BasicMenuItemUI implements AquaMenuPainter.Client/*, ScreenMenuItemUI*/ { 39 static final int kPlain = 0, kCheckBox = 1, kRadioButton = 2; 40 static final String sPropertyPrefixes[] = { "MenuItem", "CheckBoxMenuItem", "RadioButtonMenuItem" }; 41 42 boolean fIsScreenMenuItem = false; 43 boolean fIsIndeterminate = false; 44 int fType; 45 AquaMenuItemUI(final int type)46 AquaMenuItemUI(final int type) { 47 super(); 48 fType = type; 49 } 50 createUI(final JComponent c)51 public static ComponentUI createUI(final JComponent c) { 52 int type = kPlain; 53 if (c instanceof JCheckBoxMenuItem) type = kCheckBox; 54 if (c instanceof JRadioButtonMenuItem) type = kRadioButton; 55 return new AquaMenuItemUI(type); 56 } 57 58 // The only real difference between the three is which property prefix it returns 59 // and therefore which icons! getPropertyPrefix()60 protected String getPropertyPrefix() { 61 return sPropertyPrefixes[fType]; 62 } 63 64 @Override installListeners()65 protected void installListeners() { 66 super.installListeners(); 67 IndeterminateListener.install(menuItem); 68 } 69 70 @Override uninstallListeners()71 protected void uninstallListeners() { 72 IndeterminateListener.uninstall(menuItem); 73 super.uninstallListeners(); 74 } 75 updateListenersForScreenMenuItem()76 public void updateListenersForScreenMenuItem() { 77 setIsScreenMenu(true); 78 } 79 80 // Users can dynamically change the kind of menu we're on by calling JPopupMenu.setInvoker 81 // so we need to be prepared to put the listeners back on setIsScreenMenu(final boolean isScreenMenuItem)82 protected void setIsScreenMenu(final boolean isScreenMenuItem) { 83 if (fIsScreenMenuItem != isScreenMenuItem) { 84 fIsScreenMenuItem = isScreenMenuItem; 85 if (fIsScreenMenuItem) removeListeners(); 86 else addListeners(); 87 } 88 } 89 removeListeners()90 protected void removeListeners() { 91 menuItem.removeMouseListener(mouseInputListener); 92 menuItem.removeMouseMotionListener(mouseInputListener); 93 menuItem.removeMenuDragMouseListener(menuDragMouseListener); 94 } 95 addListeners()96 protected void addListeners() { 97 menuItem.addMouseListener(mouseInputListener); 98 menuItem.addMouseMotionListener(mouseInputListener); 99 menuItem.addMenuDragMouseListener(menuDragMouseListener); 100 } 101 paintMenuItem(final Graphics g, final JComponent c, final Icon localCheckIcon, final Icon localArrowIcon, final Color background, final Color foreground, final int localDefaultTextIconGap)102 protected void paintMenuItem(final Graphics g, final JComponent c, final Icon localCheckIcon, final Icon localArrowIcon, final Color background, final Color foreground, final int localDefaultTextIconGap) { 103 AquaMenuPainter.instance().paintMenuItem(this, g, c, localCheckIcon, localArrowIcon, background, foreground, disabledForeground, selectionForeground, localDefaultTextIconGap, acceleratorFont); 104 } 105 getPreferredMenuItemSize(final JComponent c, final Icon localCheckIcon, final Icon localArrowIcon, final int localDefaultTextIconGap)106 protected Dimension getPreferredMenuItemSize(final JComponent c, final Icon localCheckIcon, final Icon localArrowIcon, final int localDefaultTextIconGap) { 107 return AquaMenuPainter.instance().getPreferredMenuItemSize(c, localCheckIcon, localArrowIcon, localDefaultTextIconGap, acceleratorFont); 108 } 109 update(final Graphics g, final JComponent c)110 public void update(final Graphics g, final JComponent c) { 111 if (c.isOpaque()) { 112 // sja fix ((PenGraphics)g).alphaClearRect(0,0,c.getWidth(),c.getHeight()); 113 final Color oldColor = g.getColor(); 114 g.setColor(c.getBackground()); 115 g.fillRect(0, 0, c.getWidth(), c.getHeight()); 116 g.setColor(oldColor); 117 } 118 119 paint(g, c); 120 } 121 paintBackground(final Graphics g, final JComponent c, final int menuWidth, final int menuHeight)122 public void paintBackground(final Graphics g, final JComponent c, final int menuWidth, final int menuHeight) { 123 if ((c.getParent() instanceof JMenuBar)) return; 124 final Color oldColor = g.getColor(); 125 126 g.setColor(c.getBackground()); 127 g.fillRect(0, 0, menuWidth, menuHeight); 128 if (((JMenuItem)c).isBorderPainted()) { 129 if (((JMenuItem)c).getModel().isArmed()) { 130 AquaMenuPainter.instance().paintSelectedMenuItemBackground(g, menuWidth, menuHeight); 131 } 132 //getTheme().drawMenuItem(c, g, 0, 0, menuWidth, menuHeight); 133 } else { 134 // If selected, use black (see AquaLookAndFeel "Menu.selectionBackground") 135 if (((JMenuItem)c).getModel().isArmed()) { 136 final Color holdc = g.getColor(); 137 g.setColor(Color.black); 138 g.fillRect(0, 0, menuWidth, menuHeight); 139 g.setColor(holdc); 140 } else { 141 g.setColor(Color.green); 142 g.fillRect(0, 0, menuWidth, menuHeight); 143 //super.paintBackground(g,c,menuWidth, menuHeight); //getTheme().drawMenuBackground((Component)c, g, (short)1, 0, 0, menuWidth, menuHeight); 144 } 145 } 146 g.setColor(oldColor); 147 } 148 doClick(final MenuSelectionManager msm)149 protected void doClick(final MenuSelectionManager msm) { 150 final Dimension size = menuItem.getSize(); 151 AquaUtils.blinkMenu(new AquaUtils.Selectable() { 152 public void paintSelected(final boolean selected) { 153 menuItem.setArmed(selected); 154 menuItem.paintImmediately(0, 0, size.width, size.height); 155 } 156 }); 157 super.doClick(msm); 158 } 159 160 static final IndeterminateListener INDETERMINATE_LISTENER = new IndeterminateListener(); 161 static class IndeterminateListener implements PropertyChangeListener { 162 static final String CLIENT_PROPERTY_KEY = "JMenuItem.selectedState"; 163 install(final JMenuItem menuItem)164 static void install(final JMenuItem menuItem) { 165 menuItem.addPropertyChangeListener(CLIENT_PROPERTY_KEY, INDETERMINATE_LISTENER); 166 apply(menuItem, menuItem.getClientProperty(CLIENT_PROPERTY_KEY)); 167 } 168 uninstall(final JMenuItem menuItem)169 static void uninstall(final JMenuItem menuItem) { 170 menuItem.removePropertyChangeListener(CLIENT_PROPERTY_KEY, INDETERMINATE_LISTENER); 171 } 172 propertyChange(final PropertyChangeEvent evt)173 public void propertyChange(final PropertyChangeEvent evt) { 174 final String key = evt.getPropertyName(); 175 if (!CLIENT_PROPERTY_KEY.equalsIgnoreCase(key)) return; 176 177 final Object source = evt.getSource(); 178 if (!(source instanceof JMenuItem)) return; 179 180 final JMenuItem c = (JMenuItem)source; 181 apply(c, evt.getNewValue()); 182 } 183 apply(final JMenuItem menuItem, final Object value)184 static void apply(final JMenuItem menuItem, final Object value) { 185 final ButtonUI ui = menuItem.getUI(); 186 if (!(ui instanceof AquaMenuItemUI)) return; 187 188 final AquaMenuItemUI aquaUI = (AquaMenuItemUI)ui; 189 190 if (aquaUI.fIsIndeterminate = "indeterminate".equals(value)) { 191 aquaUI.checkIcon = UIManager.getIcon(aquaUI.getPropertyPrefix() + ".dashIcon"); 192 } else { 193 aquaUI.checkIcon = UIManager.getIcon(aquaUI.getPropertyPrefix() + ".checkIcon"); 194 } 195 } 196 isIndeterminate(final JMenuItem menuItem)197 public static boolean isIndeterminate(final JMenuItem menuItem) { 198 return "indeterminate".equals(menuItem.getClientProperty(CLIENT_PROPERTY_KEY)); 199 } 200 } 201 } 202