4632N/A/*
4632N/A * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
4632N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4632N/A *
4632N/A * This code is free software; you can redistribute it and/or modify it
4632N/A * under the terms of the GNU General Public License version 2 only, as
4632N/A * published by the Free Software Foundation. Oracle designates this
4632N/A * particular file as subject to the "Classpath" exception as provided
4632N/A * by Oracle in the LICENSE file that accompanied this code.
4632N/A *
4632N/A * This code is distributed in the hope that it will be useful, but WITHOUT
4632N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4632N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4632N/A * version 2 for more details (a copy is included in the LICENSE file that
4632N/A * accompanied this code).
4632N/A *
4632N/A * You should have received a copy of the GNU General Public License version
4632N/A * 2 along with this work; if not, write to the Free Software Foundation,
4632N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4632N/A *
4632N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4632N/A * or visit www.oracle.com if you need additional information or have any
4632N/A * questions.
4632N/A */
4632N/A
4632N/Apackage com.apple.laf;
4632N/A
4632N/Aimport java.awt.*;
4632N/Aimport java.awt.event.*;
4632N/A
4632N/Aimport javax.swing.*;
4632N/Aimport javax.swing.border.Border;
4632N/Aimport javax.swing.plaf.basic.BasicHTML;
4632N/Aimport javax.swing.text.View;
4632N/A
4632N/Aimport sun.swing.SwingUtilities2;
4632N/A
4632N/Aimport apple.laf.JRSUIConstants.*;
4632N/A
4632N/Aimport com.apple.laf.AquaIcon.InvertableIcon;
4632N/Aimport com.apple.laf.AquaUtils.RecyclableSingleton;
4632N/Aimport com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
4632N/A
4632N/A/**
4632N/A * AquaMenuPainter, implements paintMenuItem to avoid code duplication
4632N/A *
4632N/A * BasicMenuItemUI didn't factor out the various parts of the Menu, and
4632N/A * we subclass it and its subclasses BasicMenuUI
4632N/A * Our classes need an implementation of paintMenuItem
4632N/A * that allows them to paint their own backgrounds
4632N/A */
4632N/A
4632N/Apublic class AquaMenuPainter {
4632N/A // Glyph statics:
4632N/A // ASCII character codes
4632N/A static final byte
4632N/A kShiftGlyph = 0x05,
4632N/A kOptionGlyph = 0x07,
4632N/A kControlGlyph = 0x06,
4632N/A kPencilGlyph = 0x0F,
4632N/A kCommandMark = 0x11;
4632N/A
4632N/A // Unicode character codes
4632N/A static final char
4632N/A kUBlackDiamond = 0x25C6,
4632N/A kUCheckMark = 0x2713,
4632N/A kUControlGlyph = 0x2303,
4632N/A kUOptionGlyph = 0x2325,
4632N/A kUEnterGlyph = 0x2324,
4632N/A kUCommandGlyph = 0x2318,
4632N/A kULeftDeleteGlyph = 0x232B,
4632N/A kURightDeleteGlyph = 0x2326,
4632N/A kUShiftGlyph = 0x21E7,
4632N/A kUCapsLockGlyph = 0x21EA;
4632N/A
4632N/A static final int ALT_GRAPH_MASK = 1 << 5; // New to Java2
4632N/A static final int sUnsupportedModifiersMask = ~(InputEvent.CTRL_MASK | InputEvent.ALT_MASK | InputEvent.SHIFT_MASK | InputEvent.META_MASK | ALT_GRAPH_MASK);
4632N/A
4632N/A interface Client {
4632N/A public void paintBackground(Graphics g, JComponent c, int menuWidth, int menuHeight);
4632N/A }
4632N/A
4632N/A // Return a string with the proper modifier glyphs
4632N/A static String getKeyModifiersText(final int modifiers, final boolean isLeftToRight) {
4632N/A return getKeyModifiersUnicode(modifiers, isLeftToRight);
4632N/A }
4632N/A
4632N/A // Return a string with the proper modifier glyphs
4632N/A private static String getKeyModifiersUnicode(final int modifiers, final boolean isLeftToRight) {
4632N/A final StringBuilder buf = new StringBuilder(2);
4632N/A // Order (from StandardMenuDef.c): control, option(alt), shift, cmd
4632N/A // reverse for right-to-left
4632N/A //$ check for substitute key glyphs for localization
4632N/A if (isLeftToRight) {
4632N/A if ((modifiers & InputEvent.CTRL_MASK) != 0) {
4632N/A buf.append(kUControlGlyph);
4632N/A }
4632N/A if ((modifiers & (InputEvent.ALT_MASK | ALT_GRAPH_MASK)) != 0) {
4632N/A buf.append(kUOptionGlyph);
4632N/A }
4632N/A if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
4632N/A buf.append(kUShiftGlyph);
4632N/A }
4632N/A if ((modifiers & InputEvent.META_MASK) != 0) {
4632N/A buf.append(kUCommandGlyph);
4632N/A }
4632N/A } else {
4632N/A if ((modifiers & InputEvent.META_MASK) != 0) {
4632N/A buf.append(kUCommandGlyph);
4632N/A }
4632N/A if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
4632N/A buf.append(kUShiftGlyph);
4632N/A }
4632N/A if ((modifiers & (InputEvent.ALT_MASK | ALT_GRAPH_MASK)) != 0) {
4632N/A buf.append(kUOptionGlyph);
4632N/A }
4632N/A if ((modifiers & InputEvent.CTRL_MASK) != 0) {
4632N/A buf.append(kUControlGlyph);
4632N/A }
4632N/A }
4632N/A return buf.toString();
4632N/A }
4632N/A
4632N/A static final RecyclableSingleton<AquaMenuPainter> sPainter = new RecyclableSingletonFromDefaultConstructor<AquaMenuPainter>(AquaMenuPainter.class);
4632N/A static AquaMenuPainter instance() {
4632N/A return sPainter.get();
4632N/A }
4632N/A
4632N/A static final int defaultMenuItemGap = 2;
4632N/A static final int kAcceleratorArrowSpace = 16; // Accel space doesn't overlap arrow space, even though items can't have both
4632N/A
4632N/A static class RecyclableBorder extends RecyclableSingleton<Border> {
4632N/A final String borderName;
4632N/A RecyclableBorder(final String borderName) { this.borderName = borderName; }
4632N/A protected Border getInstance() { return UIManager.getBorder(borderName); }
4632N/A }
4632N/A
4632N/A protected final RecyclableBorder menuBarPainter = new RecyclableBorder("MenuBar.backgroundPainter");
4632N/A protected final RecyclableBorder selectedMenuBarItemPainter = new RecyclableBorder("MenuBar.selectedBackgroundPainter");
4632N/A protected final RecyclableBorder selectedMenuItemPainter = new RecyclableBorder("MenuItem.selectedBackgroundPainter");
4632N/A
4632N/A public void paintMenuBarBackground(final Graphics g, final int width, final int height, final JComponent c) {
4632N/A g.setColor(c == null ? Color.white : c.getBackground());
4632N/A g.fillRect(0, 0, width, height);
4632N/A menuBarPainter.get().paintBorder(null, g, 0, 0, width, height);
4632N/A }
4632N/A
4632N/A public void paintSelectedMenuTitleBackground(final Graphics g, final int width, final int height) {
4632N/A selectedMenuBarItemPainter.get().paintBorder(null, g, -1, 0, width + 2, height);
4632N/A }
4632N/A
4632N/A public void paintSelectedMenuItemBackground(final Graphics g, final int width, final int height) {
4632N/A selectedMenuItemPainter.get().paintBorder(null, g, 0, 0, width, height);
4632N/A }
4632N/A
4632N/A protected void paintMenuItem(final Client client, final Graphics g, final JComponent c, final Icon checkIcon, final Icon arrowIcon, final Color background, final Color foreground, final Color disabledForeground, final Color selectionForeground, final int defaultTextIconGap, final Font acceleratorFont) {
4632N/A final JMenuItem b = (JMenuItem)c;
4632N/A final ButtonModel model = b.getModel();
4632N/A
4632N/A// Dimension size = b.getSize();
4632N/A final int menuWidth = b.getWidth();
4632N/A final int menuHeight = b.getHeight();
4632N/A final Insets i = c.getInsets();
4632N/A
4632N/A Rectangle viewRect = new Rectangle(0, 0, menuWidth, menuHeight);
4632N/A
4632N/A viewRect.x += i.left;
4632N/A viewRect.y += i.top;
4632N/A viewRect.width -= (i.right + viewRect.x);
4632N/A viewRect.height -= (i.bottom + viewRect.y);
4632N/A
4632N/A final Font holdf = g.getFont();
4632N/A final Color holdc = g.getColor();
4632N/A final Font f = c.getFont();
4632N/A g.setFont(f);
4632N/A final FontMetrics fm = g.getFontMetrics(f);
4632N/A
4632N/A final FontMetrics fmAccel = g.getFontMetrics(acceleratorFont);
4632N/A
4632N/A // Paint background (doesn't touch the Graphics object's color)
4632N/A if (c.isOpaque()) {
4632N/A client.paintBackground(g, c, menuWidth, menuHeight);
4632N/A }
4632N/A
4632N/A // get Accelerator text
4632N/A final KeyStroke accelerator = b.getAccelerator();
4632N/A String modifiersString = "", keyString = "";
4632N/A final boolean leftToRight = AquaUtils.isLeftToRight(c);
4632N/A if (accelerator != null) {
4632N/A final int modifiers = accelerator.getModifiers();
4632N/A if (modifiers > 0) {
4632N/A modifiersString = getKeyModifiersText(modifiers, leftToRight);
4632N/A }
4632N/A final int keyCode = accelerator.getKeyCode();
4632N/A if (keyCode != 0) {
4632N/A keyString = KeyEvent.getKeyText(keyCode);
4632N/A } else {
4632N/A keyString += accelerator.getKeyChar();
4632N/A }
4632N/A }
4632N/A
4632N/A Rectangle iconRect = new Rectangle();
4632N/A Rectangle textRect = new Rectangle();
4632N/A Rectangle acceleratorRect = new Rectangle();
4632N/A Rectangle checkIconRect = new Rectangle();
4632N/A Rectangle arrowIconRect = new Rectangle();
4632N/A
4632N/A // layout the text and icon
4632N/A final String text = layoutMenuItem(b, fm, b.getText(), fmAccel, keyString, modifiersString, b.getIcon(), checkIcon, arrowIcon, b.getVerticalAlignment(), b.getHorizontalAlignment(), b.getVerticalTextPosition(), b.getHorizontalTextPosition(), viewRect, iconRect, textRect, acceleratorRect, checkIconRect, arrowIconRect, b.getText() == null ? 0 : defaultTextIconGap, defaultTextIconGap);
4632N/A
4632N/A // if this is in a AquaScreenMenuBar that's attached to a DialogPeer
4632N/A // the native menu will be disabled, though the awt Menu won't know about it
4632N/A // so the JPopupMenu will not have visibility set and the items should draw disabled
4632N/A // If it's not on a JPopupMenu then it should just use the model's enable state
4632N/A final Container parent = b.getParent();
4632N/A final boolean parentIsMenuBar = parent instanceof JMenuBar;
4632N/A
4632N/A Container ancestor = parent;
4632N/A while (ancestor != null && !(ancestor instanceof JPopupMenu)) ancestor = ancestor.getParent();
4632N/A
4632N/A boolean isEnabled = model.isEnabled() && (ancestor == null || ancestor.isVisible());
4632N/A
4632N/A // Set the accel/normal text color
4632N/A boolean isSelected = false;
4632N/A if (!isEnabled) {
4632N/A // *** paint the text disabled
4632N/A g.setColor(disabledForeground);
4632N/A } else {
4632N/A // *** paint the text normally
4632N/A if (model.isArmed() || (c instanceof JMenu && model.isSelected())) {
4632N/A g.setColor(selectionForeground);
4632N/A isSelected = true;
4632N/A } else {
4632N/A g.setColor(parentIsMenuBar ? parent.getForeground() : b.getForeground()); // Which is either MenuItem.foreground or the user's choice
4632N/A }
4632N/A }
4632N/A
4632N/A // We want to paint the icon after the text color is set since some icon painting depends on the correct
4632N/A // graphics color being set
4632N/A // See <rdar://problem/3792383> Menu icons missing in Java2D's Lines.Joins demo
4632N/A // Paint the Icon
4632N/A if (b.getIcon() != null) {
4632N/A paintIcon(g, b, iconRect, isEnabled);
4632N/A }
4632N/A
4632N/A // Paint the Check using the current text color
4632N/A if (checkIcon != null) {
4632N/A paintCheck(g, b, checkIcon, checkIconRect);
4632N/A }
4632N/A
4632N/A // Draw the accelerator first in case the HTML renderer changes the color
4632N/A if (keyString != null && !keyString.equals("")) {
4632N/A final int yAccel = acceleratorRect.y + fm.getAscent();
4632N/A if (modifiersString.equals("")) {
4632N/A // just draw the keyString
4632N/A SwingUtilities2.drawString(c, g, keyString, acceleratorRect.x, yAccel);
4632N/A } else {
4632N/A final int modifiers = accelerator.getModifiers();
4632N/A int underlinedChar = 0;
4632N/A if ((modifiers & ALT_GRAPH_MASK) > 0) underlinedChar = kUOptionGlyph; // This is a Java2 thing, we won't be getting kOptionGlyph
4632N/A // The keyStrings should all line up, so always adjust the width by the same amount
4632N/A // (if they're multi-char, they won't line up but at least they won't be cut off)
4632N/A final int emWidth = Math.max(fm.charWidth('M'), SwingUtilities.computeStringWidth(fm, keyString));
4632N/A
4632N/A if (leftToRight) {
4632N/A g.setFont(acceleratorFont);
4632N/A drawString(g, c, modifiersString, underlinedChar, acceleratorRect.x, yAccel, isEnabled, isSelected);
4632N/A g.setFont(f);
4632N/A SwingUtilities2.drawString(c, g, keyString, acceleratorRect.x + acceleratorRect.width - emWidth, yAccel);
4632N/A } else {
4632N/A final int xAccel = acceleratorRect.x + emWidth;
4632N/A g.setFont(acceleratorFont);
4632N/A drawString(g, c, modifiersString, underlinedChar, xAccel, yAccel, isEnabled, isSelected);
4632N/A g.setFont(f);
4632N/A SwingUtilities2.drawString(c, g, keyString, xAccel - fm.stringWidth(keyString), yAccel);
4632N/A }
4632N/A }
4632N/A }
4632N/A
4632N/A // Draw the Text
4632N/A if (text != null && !text.equals("")) {
4632N/A final View v = (View)c.getClientProperty(BasicHTML.propertyKey);
4632N/A if (v != null) {
4632N/A v.paint(g, textRect);
4632N/A } else {
4632N/A final int mnemonic = (AquaMnemonicHandler.isMnemonicHidden() ? -1 : model.getMnemonic());
4632N/A drawString(g, c, text, mnemonic, textRect.x, textRect.y + fm.getAscent(), isEnabled, isSelected);
4632N/A }
4632N/A }
4632N/A
4632N/A // Paint the Arrow
4632N/A if (arrowIcon != null) {
4632N/A paintArrow(g, b, model, arrowIcon, arrowIconRect);
4632N/A }
4632N/A
4632N/A g.setColor(holdc);
4632N/A g.setFont(holdf);
4632N/A }
4632N/A
4632N/A // All this had to be copied from BasicMenuItemUI, just to get the right keyModifiersText fn
4632N/A // and a few Mac tweaks
4632N/A protected Dimension getPreferredMenuItemSize(final JComponent c, final Icon checkIcon, final Icon arrowIcon, final int defaultTextIconGap, final Font acceleratorFont) {
4632N/A final JMenuItem b = (JMenuItem)c;
4632N/A final Icon icon = b.getIcon();
4632N/A final String text = b.getText();
4632N/A final KeyStroke accelerator = b.getAccelerator();
4632N/A String keyString = "", modifiersString = "";
4632N/A
4632N/A if (accelerator != null) {
4632N/A final int modifiers = accelerator.getModifiers();
4632N/A if (modifiers > 0) {
4632N/A modifiersString = getKeyModifiersText(modifiers, true); // doesn't matter, this is just for metrics
4632N/A }
4632N/A final int keyCode = accelerator.getKeyCode();
4632N/A if (keyCode != 0) {
4632N/A keyString = KeyEvent.getKeyText(keyCode);
4632N/A } else {
4632N/A keyString += accelerator.getKeyChar();
4632N/A }
4632N/A }
4632N/A
4632N/A final Font font = b.getFont();
4632N/A final FontMetrics fm = b.getFontMetrics(font);
4632N/A final FontMetrics fmAccel = b.getFontMetrics(acceleratorFont);
4632N/A
4632N/A Rectangle iconRect = new Rectangle();
4632N/A Rectangle textRect = new Rectangle();
4632N/A Rectangle acceleratorRect = new Rectangle();
4632N/A Rectangle checkIconRect = new Rectangle();
4632N/A Rectangle arrowIconRect = new Rectangle();
4632N/A Rectangle viewRect = new Rectangle(Short.MAX_VALUE, Short.MAX_VALUE);
4632N/A
4632N/A layoutMenuItem(b, fm, text, fmAccel, keyString, modifiersString, icon, checkIcon, arrowIcon, b.getVerticalAlignment(), b.getHorizontalAlignment(), b.getVerticalTextPosition(), b.getHorizontalTextPosition(), viewRect, iconRect, textRect, acceleratorRect, checkIconRect, arrowIconRect, text == null ? 0 : defaultTextIconGap, defaultTextIconGap);
4632N/A // find the union of the icon and text rects
4632N/A Rectangle r = new Rectangle();
4632N/A r.setBounds(textRect);
4632N/A r = SwingUtilities.computeUnion(iconRect.x, iconRect.y, iconRect.width, iconRect.height, r);
4632N/A // r = iconRect.union(textRect);
4632N/A
4632N/A // Add in the accelerator
4632N/A boolean acceleratorTextIsEmpty = (keyString == null) || keyString.equals("");
4632N/A
4632N/A if (!acceleratorTextIsEmpty) {
4632N/A r.width += acceleratorRect.width;
4632N/A }
4632N/A
4632N/A if (!isTopLevelMenu(b)) {
4632N/A // Add in the checkIcon
4632N/A r.width += checkIconRect.width;
4632N/A r.width += defaultTextIconGap;
4632N/A
4632N/A // Add in the arrowIcon space
4632N/A r.width += defaultTextIconGap;
4632N/A r.width += arrowIconRect.width;
4632N/A }
4632N/A
4632N/A final Insets insets = b.getInsets();
4632N/A if (insets != null) {
4632N/A r.width += insets.left + insets.right;
4632N/A r.height += insets.top + insets.bottom;
4632N/A }
4632N/A
4632N/A // Tweak for Mac
4632N/A r.width += 4 + defaultTextIconGap;
4632N/A r.height = Math.max(r.height, 18);
4632N/A
4632N/A return r.getSize();
4632N/A }
4632N/A
4632N/A protected void paintCheck(final Graphics g, final JMenuItem item, Icon checkIcon, Rectangle checkIconRect) {
4632N/A if (isTopLevelMenu(item) || !item.isSelected()) return;
4632N/A
4632N/A if (item.isArmed() && checkIcon instanceof InvertableIcon) {
4632N/A ((InvertableIcon)checkIcon).getInvertedIcon().paintIcon(item, g, checkIconRect.x, checkIconRect.y);
4632N/A } else {
4632N/A checkIcon.paintIcon(item, g, checkIconRect.x, checkIconRect.y);
4632N/A }
4632N/A }
4632N/A
4632N/A protected void paintIcon(final Graphics g, final JMenuItem c, final Rectangle localIconRect, boolean isEnabled) {
4632N/A final ButtonModel model = c.getModel();
4632N/A Icon icon;
4632N/A if (!isEnabled) {
4632N/A icon = c.getDisabledIcon();
4632N/A } else if (model.isPressed() && model.isArmed()) {
4632N/A icon = c.getPressedIcon();
4632N/A if (icon == null) {
4632N/A // Use default icon
4632N/A icon = c.getIcon();
4632N/A }
4632N/A } else {
4632N/A icon = c.getIcon();
4632N/A }
4632N/A
4632N/A if (icon != null) icon.paintIcon(c, g, localIconRect.x, localIconRect.y);
4632N/A }
4632N/A
4632N/A protected void paintArrow(Graphics g, JMenuItem c, ButtonModel model, Icon arrowIcon, Rectangle arrowIconRect) {
4632N/A if (isTopLevelMenu(c)) return;
4632N/A
4632N/A if (c instanceof JMenu && (model.isArmed() || model.isSelected()) && arrowIcon instanceof InvertableIcon) {
4632N/A ((InvertableIcon)arrowIcon).getInvertedIcon().paintIcon(c, g, arrowIconRect.x, arrowIconRect.y);
4632N/A } else {
4632N/A arrowIcon.paintIcon(c, g, arrowIconRect.x, arrowIconRect.y);
4632N/A }
4632N/A }
4632N/A
4632N/A /** Draw a string with the graphics g at location (x,y) just like g.drawString() would.
4632N/A * The first occurence of underlineChar in text will be underlined. The matching is
4632N/A * not case sensitive.
4632N/A */
4632N/A public void drawString(final Graphics g, final JComponent c, final String text, final int underlinedChar, final int x, final int y, final boolean isEnabled, final boolean isSelected) {
4632N/A char lc, uc;
4632N/A int index = -1, lci, uci;
4632N/A
4632N/A if (underlinedChar != '\0') {
4632N/A uc = Character.toUpperCase((char)underlinedChar);
4632N/A lc = Character.toLowerCase((char)underlinedChar);
4632N/A
4632N/A uci = text.indexOf(uc);
4632N/A lci = text.indexOf(lc);
4632N/A
4632N/A if (uci == -1) index = lci;
4632N/A else if (lci == -1) index = uci;
4632N/A else index = (lci < uci) ? lci : uci;
4632N/A }
4632N/A
4632N/A SwingUtilities2.drawStringUnderlineCharAt(c, g, text, index, x, y);
4632N/A }
4632N/A
4632N/A /*
4632N/A * Returns false if the component is a JMenu and it is a top
4632N/A * level menu (on the menubar).
4632N/A */
4632N/A private static boolean isTopLevelMenu(final JMenuItem menuItem) {
4632N/A return (menuItem instanceof JMenu) && (((JMenu)menuItem).isTopLevelMenu());
4632N/A }
4632N/A
4632N/A private String layoutMenuItem(final JMenuItem menuItem, final FontMetrics fm, final String text, final FontMetrics fmAccel, String keyString, final String modifiersString, final Icon icon, final Icon checkIcon, final Icon arrowIcon, final int verticalAlignment, final int horizontalAlignment, final int verticalTextPosition, final int horizontalTextPosition, final Rectangle viewR, final Rectangle iconR, final Rectangle textR, final Rectangle acceleratorR, final Rectangle checkIconR, final Rectangle arrowIconR, final int textIconGap, final int menuItemGap) {
4632N/A // Force it to do "LEFT", then flip the rects if we're right-to-left
4632N/A SwingUtilities.layoutCompoundLabel(menuItem, fm, text, icon, verticalAlignment, SwingConstants.LEFT, verticalTextPosition, horizontalTextPosition, viewR, iconR, textR, textIconGap);
4632N/A
4632N/A final boolean acceleratorTextIsEmpty = (keyString == null) || keyString.equals("");
4632N/A
4632N/A if (acceleratorTextIsEmpty) {
4632N/A acceleratorR.width = acceleratorR.height = 0;
4632N/A keyString = "";
4632N/A } else {
4632N/A // Accel space doesn't overlap arrow space, even though items can't have both
4632N/A acceleratorR.width = SwingUtilities.computeStringWidth(fmAccel, modifiersString);
4632N/A // The keyStrings should all line up, so always adjust the width by the same amount
4632N/A // (if they're multi-char, they won't line up but at least they won't be cut off)
4632N/A acceleratorR.width += Math.max(fm.charWidth('M'), SwingUtilities.computeStringWidth(fm, keyString));
4632N/A acceleratorR.height = fmAccel.getHeight();
4632N/A }
4632N/A
4632N/A /* Initialize the checkIcon bounds rectangle checkIconR.
4632N/A */
4632N/A
4632N/A final boolean isTopLevelMenu = isTopLevelMenu(menuItem);
4632N/A if (!isTopLevelMenu) {
4632N/A if (checkIcon != null) {
4632N/A checkIconR.width = checkIcon.getIconWidth();
4632N/A checkIconR.height = checkIcon.getIconHeight();
4632N/A } else {
4632N/A checkIconR.width = checkIconR.height = 16;
4632N/A }
4632N/A
4632N/A /* Initialize the arrowIcon bounds rectangle arrowIconR.
4632N/A */
4632N/A
4632N/A if (arrowIcon != null) {
4632N/A arrowIconR.width = arrowIcon.getIconWidth();
4632N/A arrowIconR.height = arrowIcon.getIconHeight();
4632N/A } else {
4632N/A arrowIconR.width = arrowIconR.height = 16;
4632N/A }
4632N/A
4632N/A textR.x += 12;
4632N/A iconR.x += 12;
4632N/A }
4632N/A
4632N/A final Rectangle labelR = iconR.union(textR);
4632N/A
4632N/A // Position the Accelerator text rect
4632N/A // Menu shortcut text *ought* to have the letters left-justified - look at a menu with an "M" in it
4632N/A acceleratorR.x += (viewR.width - arrowIconR.width - acceleratorR.width);
4632N/A acceleratorR.y = viewR.y + (viewR.height / 2) - (acceleratorR.height / 2);
4632N/A
4632N/A if (!isTopLevelMenu) {
4632N/A // if ( GetSysDirection() < 0 ) hierRect.right = hierRect.left + w + 4;
4632N/A // else hierRect.left = hierRect.right - w - 4;
4632N/A arrowIconR.x = (viewR.width - arrowIconR.width) + 1;
4632N/A arrowIconR.y = viewR.y + (labelR.height / 2) - (arrowIconR.height / 2) + 1;
4632N/A
4632N/A checkIconR.y = viewR.y + (labelR.height / 2) - (checkIconR.height / 2);
4632N/A checkIconR.x = 5;
4632N/A
4632N/A textR.width += 8;
4632N/A }
4632N/A
4632N/A /*System.out.println("Layout: " +horizontalAlignment+ " v=" +viewR+" c="+checkIconR+" i="+
4632N/A iconR+" t="+textR+" acc="+acceleratorR+" a="+arrowIconR);*/
4632N/A
4632N/A if (!AquaUtils.isLeftToRight(menuItem)) {
4632N/A // Flip the rectangles so that instead of [check][icon][text][accel/arrow] it's [accel/arrow][text][icon][check]
4632N/A final int w = viewR.width;
4632N/A checkIconR.x = w - (checkIconR.x + checkIconR.width);
4632N/A iconR.x = w - (iconR.x + iconR.width);
4632N/A textR.x = w - (textR.x + textR.width);
4632N/A acceleratorR.x = w - (acceleratorR.x + acceleratorR.width);
4632N/A arrowIconR.x = w - (arrowIconR.x + arrowIconR.width);
4632N/A }
4632N/A textR.x += menuItemGap;
4632N/A iconR.x += menuItemGap;
4632N/A
4632N/A return text;
4632N/A }
4632N/A
4632N/A public static Border getMenuBarPainter() {
4632N/A final AquaBorder border = new AquaBorder.Default();
4632N/A border.painter.state.set(Widget.MENU_BAR);
4632N/A return border;
4632N/A }
4632N/A
4632N/A public static Border getSelectedMenuBarItemPainter() {
4632N/A final AquaBorder border = new AquaBorder.Default();
4632N/A border.painter.state.set(Widget.MENU_TITLE);
4632N/A border.painter.state.set(State.PRESSED);
4632N/A return border;
4632N/A }
4632N/A
4632N/A public static Border getSelectedMenuItemPainter() {
4632N/A final AquaBorder border = new AquaBorder.Default();
4632N/A border.painter.state.set(Widget.MENU_ITEM);
4632N/A border.painter.state.set(State.PRESSED);
4632N/A return border;
4632N/A }
4632N/A}