6584657: GTK Look and Feel: Bugs in menu item layout

Reviewed-by: peterz, alexp
This commit is contained in:
Mikhail Lapshin 2008-08-08 20:49:26 +04:00
parent 1dce4ceddd
commit f092fd7939
10 changed files with 2002 additions and 1667 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -974,6 +974,7 @@ public class SwingUtilities implements SwingConstants
boolean textIsEmpty = (text == null) || text.equals("");
int lsb = 0;
int rsb = 0;
/* Unless both text and icon are non-null, we effectively ignore
* the value of textIconGap.
*/
@ -1015,7 +1016,7 @@ public class SwingUtilities implements SwingConstants
if (lsb < 0) {
textR.width -= lsb;
}
int rsb = SwingUtilities2.getRightSideBearing(c, fm, text);
rsb = SwingUtilities2.getRightSideBearing(c, fm, text);
if (rsb > 0) {
textR.width += rsb;
}
@ -1118,6 +1119,11 @@ public class SwingUtilities implements SwingConstants
// lsb is negative. Shift the x location so that the text is
// visually drawn at the right location.
textR.x -= lsb;
textR.width += lsb;
}
if (rsb > 0) {
textR.width -= rsb;
}
return text;

View File

@ -1,5 +1,5 @@
/*
* Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,7 +30,6 @@ import javax.swing.plaf.UIResource;
import java.awt.Container;
import java.awt.Dimension;
import static sun.swing.SwingUtilities2.BASICMENUITEMUI_MAX_TEXT_OFFSET;
/**
* The default layout manager for Popup menus and menubars. This
@ -49,18 +48,7 @@ public class DefaultMenuLayout extends BoxLayout implements UIResource {
public Dimension preferredLayoutSize(Container target) {
if (target instanceof JPopupMenu) {
JPopupMenu popupMenu = (JPopupMenu) target;
// Before the calculation of menu preferred size
// clear the previously calculated maximal widths and offsets
// in menu's Client Properties
popupMenu.putClientProperty(BasicMenuItemUI.MAX_ACC_WIDTH, null);
popupMenu.putClientProperty(BasicMenuItemUI.MAX_ARROW_WIDTH, null);
popupMenu.putClientProperty(BasicMenuItemUI.MAX_CHECK_WIDTH, null);
popupMenu.putClientProperty(BasicMenuItemUI.MAX_ICON_WIDTH, null);
popupMenu.putClientProperty(BasicMenuItemUI.MAX_LABEL_WIDTH, null);
popupMenu.putClientProperty(BasicMenuItemUI.MAX_TEXT_WIDTH, null);
popupMenu.putClientProperty(BASICMENUITEMUI_MAX_TEXT_OFFSET, null);
sun.swing.MenuItemLayoutHelper.clearUsedClientProperties(popupMenu);
if (popupMenu.getComponentCount() == 0) {
return new Dimension(0, 0);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -47,19 +47,22 @@ class DefaultMenuLayout extends BoxLayout implements UIResource {
super(target, axis);
}
public void invalidateLayout(Container target) {
if (target instanceof JPopupMenu) {
SynthPopupMenuUI popupUI = (SynthPopupMenuUI)((JPopupMenu)target).
getUI();
popupUI.resetAlignmentHints();
}
super.invalidateLayout(target);
}
public Dimension preferredLayoutSize(Container target) {
if (target instanceof JPopupMenu && target.getComponentCount() == 0) {
return new Dimension(0, 0);
if (target instanceof JPopupMenu) {
JPopupMenu popupMenu = (JPopupMenu) target;
popupMenu.putClientProperty(
SynthMenuItemLayoutHelper.MAX_ACC_OR_ARROW_WIDTH, null);
sun.swing.MenuItemLayoutHelper.clearUsedClientProperties(popupMenu);
if (popupMenu.getComponentCount() == 0) {
return new Dimension(0, 0);
}
}
// Make BoxLayout recalculate cached preferred sizes
super.invalidateLayout(target);
return super.preferredLayoutSize(target);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,8 @@
package javax.swing.plaf.synth;
import sun.swing.SwingUtilities2;
import sun.swing.MenuItemLayoutHelper;
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.basic.BasicHTML;
@ -411,6 +413,198 @@ public class SynthGraphicsUtils {
}
/**
* A quick note about how preferred sizes are calculated... Generally
* speaking, SynthPopupMenuUI will run through the list of its children
* (from top to bottom) and ask each for its preferred size. Each menu
* item will add up the max width of each element (icons, text,
* accelerator spacing, accelerator text or arrow icon) encountered thus
* far, so by the time all menu items have been calculated, we will
* know the maximum (preferred) menu item size for that popup menu.
* Later when it comes time to paint each menu item, we can use those
* same accumulated max element sizes in order to layout the item.
*/
static Dimension getPreferredMenuItemSize(SynthContext context,
SynthContext accContext, JComponent c,
Icon checkIcon, Icon arrowIcon, int defaultTextIconGap,
String acceleratorDelimiter, boolean useCheckAndArrow,
String propertyPrefix) {
JMenuItem mi = (JMenuItem) c;
SynthMenuItemLayoutHelper lh = new SynthMenuItemLayoutHelper(
context, accContext, mi, checkIcon, arrowIcon,
MenuItemLayoutHelper.createMaxRect(), defaultTextIconGap,
acceleratorDelimiter, SynthLookAndFeel.isLeftToRight(mi),
useCheckAndArrow, propertyPrefix);
Dimension result = new Dimension();
// Calculate the result width
int gap = lh.getGap();
result.width = 0;
MenuItemLayoutHelper.addMaxWidth(lh.getCheckSize(), gap, result);
MenuItemLayoutHelper.addMaxWidth(lh.getLabelSize(), gap, result);
MenuItemLayoutHelper.addWidth(lh.getMaxAccOrArrowWidth(), 5 * gap, result);
// The last gap is unnecessary
result.width -= gap;
// Calculate the result height
result.height = MenuItemLayoutHelper.max(lh.getCheckSize().getHeight(),
lh.getLabelSize().getHeight(), lh.getAccSize().getHeight(),
lh.getArrowSize().getHeight());
// Take into account menu item insets
Insets insets = lh.getMenuItem().getInsets();
if (insets != null) {
result.width += insets.left + insets.right;
result.height += insets.top + insets.bottom;
}
// if the width is even, bump it up one. This is critical
// for the focus dash lhne to draw properly
if (result.width % 2 == 0) {
result.width++;
}
// if the height is even, bump it up one. This is critical
// for the text to center properly
if (result.height % 2 == 0) {
result.height++;
}
return result;
}
static void applyInsets(Rectangle rect, Insets insets) {
if (insets != null) {
rect.x += insets.left;
rect.y += insets.top;
rect.width -= (insets.right + rect.x);
rect.height -= (insets.bottom + rect.y);
}
}
static void paint(SynthContext context, SynthContext accContext, Graphics g,
Icon checkIcon, Icon arrowIcon, String acceleratorDelimiter,
int defaultTextIconGap, String propertyPrefix) {
JMenuItem mi = (JMenuItem) context.getComponent();
SynthStyle style = context.getStyle();
g.setFont(style.getFont(context));
Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight());
applyInsets(viewRect, mi.getInsets());
SynthMenuItemLayoutHelper lh = new SynthMenuItemLayoutHelper(
context, accContext, mi, checkIcon,
arrowIcon, viewRect, defaultTextIconGap, acceleratorDelimiter,
SynthLookAndFeel.isLeftToRight(mi),
MenuItemLayoutHelper.useCheckAndArrow(mi), propertyPrefix);
MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem();
paintMenuItem(g, lh, lr);
}
static void paintMenuItem(Graphics g, SynthMenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
// Save original graphics font and color
Font holdf = g.getFont();
Color holdc = g.getColor();
paintBackground(g, lh);
paintCheckIcon(g, lh, lr);
paintIcon(g, lh, lr);
paintText(g, lh, lr);
paintAccText(g, lh, lr);
paintArrowIcon(g, lh, lr);
// Restore original graphics font and color
g.setColor(holdc);
g.setFont(holdf);
}
static void paintBackground(Graphics g, SynthMenuItemLayoutHelper lh) {
paintBackground(lh.getContext(), g, lh.getMenuItem());
}
static void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintMenuItemBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
}
static void paintIcon(Graphics g, SynthMenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
if (lh.getIcon() != null) {
Icon icon;
JMenuItem mi = lh.getMenuItem();
ButtonModel model = mi.getModel();
if (!model.isEnabled()) {
icon = mi.getDisabledIcon();
} else if (model.isPressed() && model.isArmed()) {
icon = mi.getPressedIcon();
if (icon == null) {
// Use default icon
icon = mi.getIcon();
}
} else {
icon = mi.getIcon();
}
if (icon != null) {
Rectangle iconRect = lr.getIconRect();
SynthIcon.paintIcon(icon, lh.getContext(), g, iconRect.x,
iconRect.y, iconRect.width, iconRect.height);
}
}
}
static void paintCheckIcon(Graphics g, SynthMenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
if (lh.getCheckIcon() != null) {
Rectangle checkRect = lr.getCheckRect();
SynthIcon.paintIcon(lh.getCheckIcon(), lh.getContext(), g,
checkRect.x, checkRect.y, checkRect.width, checkRect.height);
}
}
static void paintAccText(Graphics g, SynthMenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
String accText = lh.getAccText();
if (accText != null && !accText.equals("")) {
g.setColor(lh.getAccStyle().getColor(lh.getAccContext(),
ColorType.TEXT_FOREGROUND));
g.setFont(lh.getAccStyle().getFont(lh.getAccContext()));
lh.getAccGraphicsUtils().paintText(lh.getAccContext(), g, accText,
lr.getAccRect().x, lr.getAccRect().y, -1);
}
}
static void paintText(Graphics g, SynthMenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
if (!lh.getText().equals("")) {
if (lh.getHtmlView() != null) {
// Text is HTML
lh.getHtmlView().paint(g, lr.getTextRect());
} else {
// Text isn't HTML
g.setColor(lh.getStyle().getColor(
lh.getContext(), ColorType.TEXT_FOREGROUND));
g.setFont(lh.getStyle().getFont(lh.getContext()));
lh.getGraphicsUtils().paintText(lh.getContext(), g, lh.getText(),
lr.getTextRect().x, lr.getTextRect().y,
lh.getMenuItem().getDisplayedMnemonicIndex());
}
}
}
static void paintArrowIcon(Graphics g, SynthMenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
if (lh.getArrowIcon() != null) {
Rectangle arrowRect = lr.getArrowRect();
SynthIcon.paintIcon(lh.getArrowIcon(), lh.getContext(), g,
arrowRect.x, arrowRect.y, arrowRect.width, arrowRect.height);
}
}
/**
* Wraps a SynthIcon around the Icon interface, forwarding calls to
* the SynthIcon with a given SynthContext.

View File

@ -0,0 +1,307 @@
/*
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package javax.swing.plaf.synth;
import sun.swing.StringUIClientPropertyKey;
import sun.swing.MenuItemLayoutHelper;
import sun.swing.plaf.synth.SynthIcon;
import javax.swing.*;
import javax.swing.text.View;
import java.awt.*;
/**
* Calculates preferred size and layouts synth menu items.
*
* All JMenuItems (and JMenus) include enough space for the insets
* plus one or more elements. When we say "label" below, we mean
* "icon and/or text."
*
* Cases to consider for SynthMenuItemUI (visualized here in a
* LTR orientation; the RTL case would be reversed):
* label
* check icon + label
* check icon + label + accelerator
* label + accelerator
*
* Cases to consider for SynthMenuUI (again visualized here in a
* LTR orientation):
* label + arrow
*
* Note that in the above scenarios, accelerator and arrow icon are
* mutually exclusive. This means that if a popup menu contains a mix
* of JMenus and JMenuItems, we only need to allow enough space for
* max(maxAccelerator, maxArrow), and both accelerators and arrow icons
* can occupy the same "column" of space in the menu.
*/
class SynthMenuItemLayoutHelper extends MenuItemLayoutHelper {
public static final StringUIClientPropertyKey MAX_ACC_OR_ARROW_WIDTH =
new StringUIClientPropertyKey("maxAccOrArrowWidth");
public static final ColumnAlignment LTR_ALIGNMENT_1 =
new ColumnAlignment(
SwingConstants.LEFT,
SwingConstants.LEFT,
SwingConstants.LEFT,
SwingConstants.RIGHT,
SwingConstants.RIGHT
);
public static final ColumnAlignment LTR_ALIGNMENT_2 =
new ColumnAlignment(
SwingConstants.LEFT,
SwingConstants.LEFT,
SwingConstants.LEFT,
SwingConstants.LEFT,
SwingConstants.RIGHT
);
public static final ColumnAlignment RTL_ALIGNMENT_1 =
new ColumnAlignment(
SwingConstants.RIGHT,
SwingConstants.RIGHT,
SwingConstants.RIGHT,
SwingConstants.LEFT,
SwingConstants.LEFT
);
public static final ColumnAlignment RTL_ALIGNMENT_2 =
new ColumnAlignment(
SwingConstants.RIGHT,
SwingConstants.RIGHT,
SwingConstants.RIGHT,
SwingConstants.RIGHT,
SwingConstants.LEFT
);
private SynthContext context;
private SynthContext accContext;
private SynthStyle style;
private SynthStyle accStyle;
private SynthGraphicsUtils gu;
private SynthGraphicsUtils accGu;
private boolean alignAcceleratorText;
private int maxAccOrArrowWidth;
public SynthMenuItemLayoutHelper(SynthContext context, SynthContext accContext,
JMenuItem mi, Icon checkIcon, Icon arrowIcon,
Rectangle viewRect, int gap, String accDelimiter,
boolean isLeftToRight, boolean useCheckAndArrow,
String propertyPrefix) {
this.context = context;
this.accContext = accContext;
this.style = context.getStyle();
this.accStyle = accContext.getStyle();
this.gu = style.getGraphicsUtils(context);
this.accGu = accStyle.getGraphicsUtils(accContext);
this.alignAcceleratorText = getAlignAcceleratorText(propertyPrefix);
reset(mi, checkIcon, arrowIcon, viewRect, gap, accDelimiter,
isLeftToRight, style.getFont(context), accStyle.getFont(accContext),
useCheckAndArrow, propertyPrefix);
setLeadingGap(0);
}
private boolean getAlignAcceleratorText(String propertyPrefix) {
return style.getBoolean(context,
propertyPrefix + ".alignAcceleratorText", true);
}
protected void calcWidthsAndHeights() {
// iconRect
if (getIcon() != null) {
getIconSize().setWidth(SynthIcon.getIconWidth(getIcon(), context));
getIconSize().setHeight(SynthIcon.getIconHeight(getIcon(), context));
}
// accRect
if (!getAccText().equals("")) {
getAccSize().setWidth(accGu.computeStringWidth(getAccContext(),
getAccFontMetrics().getFont(), getAccFontMetrics(),
getAccText()));
getAccSize().setHeight(getAccFontMetrics().getHeight());
}
// textRect
if (getText() == null) {
setText("");
} else if (!getText().equals("")) {
if (getHtmlView() != null) {
// Text is HTML
getTextSize().setWidth(
(int) getHtmlView().getPreferredSpan(View.X_AXIS));
getTextSize().setHeight(
(int) getHtmlView().getPreferredSpan(View.Y_AXIS));
} else {
// Text isn't HTML
getTextSize().setWidth(gu.computeStringWidth(context,
getFontMetrics().getFont(), getFontMetrics(),
getText()));
getTextSize().setHeight(getFontMetrics().getHeight());
}
}
if (useCheckAndArrow()) {
// checkIcon
if (getCheckIcon() != null) {
getCheckSize().setWidth(
SynthIcon.getIconWidth(getCheckIcon(), context));
getCheckSize().setHeight(
SynthIcon.getIconHeight(getCheckIcon(), context));
}
// arrowRect
if (getArrowIcon() != null) {
getArrowSize().setWidth(
SynthIcon.getIconWidth(getArrowIcon(), context));
getArrowSize().setHeight(
SynthIcon.getIconHeight(getArrowIcon(), context));
}
}
// labelRect
if (isColumnLayout()) {
getLabelSize().setWidth(getIconSize().getWidth()
+ getTextSize().getWidth() + getGap());
getLabelSize().setHeight(MenuItemLayoutHelper.max(
getCheckSize().getHeight(),
getIconSize().getHeight(),
getTextSize().getHeight(),
getAccSize().getHeight(),
getArrowSize().getHeight()));
} else {
Rectangle textRect = new Rectangle();
Rectangle iconRect = new Rectangle();
gu.layoutText(context, getFontMetrics(), getText(), getIcon(),
getHorizontalAlignment(), getVerticalAlignment(),
getHorizontalTextPosition(), getVerticalTextPosition(),
getViewRect(), iconRect, textRect, getGap());
Rectangle labelRect = iconRect.union(textRect);
getLabelSize().setHeight(labelRect.height);
getLabelSize().setWidth(labelRect.width);
}
}
protected void calcMaxWidths() {
calcMaxWidth(getCheckSize(), MAX_CHECK_WIDTH);
maxAccOrArrowWidth =
calcMaxValue(MAX_ACC_OR_ARROW_WIDTH, getArrowSize().getWidth());
maxAccOrArrowWidth =
calcMaxValue(MAX_ACC_OR_ARROW_WIDTH, getAccSize().getWidth());
if (isColumnLayout()) {
calcMaxWidth(getIconSize(), MAX_ICON_WIDTH);
calcMaxWidth(getTextSize(), MAX_TEXT_WIDTH);
int curGap = getGap();
if ((getIconSize().getMaxWidth() == 0)
|| (getTextSize().getMaxWidth() == 0)) {
curGap = 0;
}
getLabelSize().setMaxWidth(
calcMaxValue(MAX_LABEL_WIDTH, getIconSize().getMaxWidth()
+ getTextSize().getMaxWidth() + curGap));
} else {
// We shouldn't use current icon and text widths
// in maximal widths calculation for complex layout.
getIconSize().setMaxWidth(getParentIntProperty(
MAX_ICON_WIDTH));
calcMaxWidth(getLabelSize(), MAX_LABEL_WIDTH);
// If maxLabelWidth is wider
// than the widest icon + the widest text + gap,
// we should update the maximal text witdh
int candidateTextWidth = getLabelSize().getMaxWidth() -
getIconSize().getMaxWidth();
if (getIconSize().getMaxWidth() > 0) {
candidateTextWidth -= getGap();
}
getTextSize().setMaxWidth(calcMaxValue(
MAX_TEXT_WIDTH, candidateTextWidth));
}
}
public SynthContext getContext() {
return context;
}
public SynthContext getAccContext() {
return accContext;
}
public SynthStyle getStyle() {
return style;
}
public SynthStyle getAccStyle() {
return accStyle;
}
public SynthGraphicsUtils getGraphicsUtils() {
return gu;
}
public SynthGraphicsUtils getAccGraphicsUtils() {
return accGu;
}
public boolean alignAcceleratorText() {
return alignAcceleratorText;
}
public int getMaxAccOrArrowWidth() {
return maxAccOrArrowWidth;
}
protected void prepareForLayout(LayoutResult lr) {
lr.getCheckRect().width = getCheckSize().getMaxWidth();
// An item can have an arrow or a check icon at once
if (useCheckAndArrow() && (!"".equals(getAccText()))) {
lr.getAccRect().width = maxAccOrArrowWidth;
} else {
lr.getArrowRect().width = maxAccOrArrowWidth;
}
}
public ColumnAlignment getLTRColumnAlignment() {
if (alignAcceleratorText()) {
return LTR_ALIGNMENT_2;
} else {
return LTR_ALIGNMENT_1;
}
}
public ColumnAlignment getRTLColumnAlignment() {
if (alignAcceleratorText()) {
return RTL_ALIGNMENT_2;
} else {
return RTL_ALIGNMENT_1;
}
}
protected void layoutIconAndTextInLabelRect(LayoutResult lr) {
lr.setTextRect(new Rectangle());
lr.setIconRect(new Rectangle());
gu.layoutText(context, getFontMetrics(), getText(), getIcon(),
getHorizontalAlignment(), getVerticalAlignment(),
getHorizontalTextPosition(), getVerticalTextPosition(),
lr.getLabelRect(), lr.getIconRect(), lr.getTextRect(), getGap());
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,7 +37,7 @@ import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import javax.swing.text.View;
import sun.swing.plaf.synth.*;
import sun.swing.SwingUtilities2;
import sun.swing.MenuItemLayoutHelper;
/**
@ -59,542 +59,16 @@ class SynthMenuItemUI extends BasicMenuItemUI implements
return new SynthMenuItemUI();
}
//
// The next handful of static methods are used by both SynthMenuUI
// and SynthMenuItemUI. This is necessitated by SynthMenuUI not
// extending SynthMenuItemUI.
//
/*
* All JMenuItems (and JMenus) include enough space for the insets
* plus one or more elements. When we say "icon(s)" below, we mean
* "check/radio indicator and/or user icon." If both are defined for
* a given menu item, then in a LTR orientation the check/radio indicator
* is on the left side followed by the user icon to the right; it is
* just the opposite in a RTL orientation.
*
* Cases to consider for SynthMenuItemUI (visualized here in a
* LTR orientation; the RTL case would be reversed):
* text
* icon(s) + text
* icon(s) + text + accelerator
* text + accelerator
*
* Cases to consider for SynthMenuUI (again visualized here in a
* LTR orientation):
* text + arrow
* (user)icon + text + arrow
*
* Note that in the above scenarios, accelerator and arrow icon are
* mutually exclusive. This means that if a popup menu contains a mix
* of JMenus and JMenuItems, we only need to allow enough space for
* max(maxAccelerator, maxArrow), and both accelerators and arrow icons
* can occupy the same "column" of space in the menu.
*
* A quick note about how preferred sizes are calculated... Generally
* speaking, SynthPopupMenuUI will run through the list of its children
* (from top to bottom) and ask each for its preferred size. Each menu
* item will add up the max width of each element (icons, text,
* accelerator spacing, accelerator text or arrow icon) encountered thus
* far, so by the time all menu items have been calculated, we will
* know the maximum (preferred) menu item size for that popup menu.
* Later when it comes time to paint each menu item, we can use those
* same accumulated max element sizes in order to layout the item.
*/
static Dimension getPreferredMenuItemSize(SynthContext context,
SynthContext accContext, JComponent c,
Icon checkIcon, Icon arrowIcon, int defaultTextIconGap,
String acceleratorDelimiter) {
JMenuItem b = (JMenuItem) c;
Icon icon = b.getIcon();
String text = b.getText();
KeyStroke accelerator = b.getAccelerator();
String acceleratorText = "";
if (accelerator != null) {
int modifiers = accelerator.getModifiers();
if (modifiers > 0) {
acceleratorText = KeyEvent.getKeyModifiersText(modifiers);
acceleratorText += acceleratorDelimiter;
}
int keyCode = accelerator.getKeyCode();
if (keyCode != 0) {
acceleratorText += KeyEvent.getKeyText(keyCode);
} else {
acceleratorText += accelerator.getKeyChar();
}
}
Font font = context.getStyle().getFont(context);
FontMetrics fm = b.getFontMetrics(font);
FontMetrics fmAccel = b.getFontMetrics(accContext.getStyle().
getFont(accContext));
resetRects();
layoutMenuItem(
context, fm, accContext, text, fmAccel, acceleratorText,
icon, checkIcon, arrowIcon, b.getVerticalAlignment(),
b.getHorizontalAlignment(), b.getVerticalTextPosition(),
b.getHorizontalTextPosition(), viewRect, iconRect, textRect,
acceleratorRect, checkIconRect, arrowIconRect,
text == null ? 0 : defaultTextIconGap, defaultTextIconGap);
r.setBounds(textRect);
int totalIconWidth = 0;
int maxIconHeight = 0;
if (icon != null) {
// Add in the user icon
totalIconWidth += iconRect.width;
if (textRect.width > 0) {
// Allow for some room between the user icon and the text
totalIconWidth += defaultTextIconGap;
}
maxIconHeight = Math.max(iconRect.height, maxIconHeight);
}
if (checkIcon != null) {
// Add in the checkIcon
totalIconWidth += checkIconRect.width;
if (textRect.width > 0 || icon != null) {
// Allow for some room between the check/radio indicator
// and the text (or user icon, if both are specified)
totalIconWidth += defaultTextIconGap;
}
maxIconHeight = Math.max(checkIconRect.height, maxIconHeight);
}
int arrowWidth = 0;
if (arrowIcon != null) {
// Add in the arrowIcon
arrowWidth += defaultTextIconGap;
arrowWidth += arrowIconRect.width;
maxIconHeight = Math.max(arrowIconRect.height, maxIconHeight);
}
int accelSpacing = 0;
if (acceleratorRect.width > 0) {
// Allow for some room between the text and the accelerator
accelSpacing += 4*defaultTextIconGap;
}
// Take text and all icons into account when determining height
r.height = Math.max(r.height, maxIconHeight);
// To make the accelerator texts appear in a column,
// find the widest MenuItem text and the widest accelerator text.
// Get the parent, which stores the information.
Container parent = b.getParent();
if (parent instanceof JPopupMenu) {
SynthPopupMenuUI popupUI = (SynthPopupMenuUI)SynthLookAndFeel.
getUIOfType(((JPopupMenu)parent).getUI(),
SynthPopupMenuUI.class);
if (popupUI != null) {
// This gives us the widest MenuItem text encountered thus
// far in the parent JPopupMenu
r.width = popupUI.adjustTextWidth(r.width);
// Add in the widest icon (includes both user and
// check/radio icons) encountered thus far
r.width += popupUI.adjustIconWidth(totalIconWidth);
// Add in the widest text/accelerator spacing
// encountered thus far
r.width += popupUI.adjustAccelSpacingWidth(accelSpacing);
// Add in the widest accelerator text (or arrow)
// encountered thus far (at least one of these values
// will always be zero, so we combine them here to
// avoid double counting)
int totalAccelOrArrow = acceleratorRect.width + arrowWidth;
r.width += popupUI.adjustAcceleratorWidth(totalAccelOrArrow);
}
}
else if (parent != null && !(b instanceof JMenu &&
((JMenu)b).isTopLevelMenu())) {
r.width +=
totalIconWidth + accelSpacing +
acceleratorRect.width + arrowWidth;
}
Insets insets = b.getInsets();
if(insets != null) {
r.width += insets.left + insets.right;
r.height += insets.top + insets.bottom;
}
// if the width is even, bump it up one. This is critical
// for the focus dash line to draw properly
if(r.width%2 == 0) {
r.width++;
}
// if the height is even, bump it up one. This is critical
// for the text to center properly
if(r.height%2 == 0) {
r.height++;
}
return r.getSize();
}
static void paint(SynthContext context, SynthContext accContext,
Graphics g, Icon checkIcon, Icon arrowIcon,
String acceleratorDelimiter,
int defaultTextIconGap) {
JComponent c = context.getComponent();
JMenuItem b = (JMenuItem)c;
ButtonModel model = b.getModel();
Insets i = b.getInsets();
resetRects();
viewRect.setBounds(0, 0, b.getWidth(), b.getHeight());
viewRect.x += i.left;
viewRect.y += i.top;
viewRect.width -= (i.right + viewRect.x);
viewRect.height -= (i.bottom + viewRect.y);
SynthStyle style = context.getStyle();
Font f = style.getFont(context);
g.setFont(f);
FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f);
FontMetrics accFM = SwingUtilities2.getFontMetrics(c, g,
accContext.getStyle().
getFont(accContext));
// get Accelerator text
KeyStroke accelerator = b.getAccelerator();
String acceleratorText = "";
if (accelerator != null) {
int modifiers = accelerator.getModifiers();
if (modifiers > 0) {
acceleratorText = KeyEvent.getKeyModifiersText(modifiers);
acceleratorText += acceleratorDelimiter;
}
int keyCode = accelerator.getKeyCode();
if (keyCode != 0) {
acceleratorText += KeyEvent.getKeyText(keyCode);
} else {
acceleratorText += accelerator.getKeyChar();
}
}
// Layout the text and icon
String text = layoutMenuItem(context, fm, accContext,
b.getText(), accFM, acceleratorText, b.getIcon(),
checkIcon, arrowIcon,
b.getVerticalAlignment(), b.getHorizontalAlignment(),
b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
viewRect, iconRect, textRect, acceleratorRect,
checkIconRect, arrowIconRect,
b.getText() == null ? 0 : defaultTextIconGap,
defaultTextIconGap
);
// Paint the Check
if (checkIcon != null) {
SynthIcon.paintIcon(checkIcon, context, g, checkIconRect.x,
checkIconRect.y, checkIconRect.width, checkIconRect.height);
}
// Paint the Icon
if(b.getIcon() != null) {
Icon icon;
if(!model.isEnabled()) {
icon = b.getDisabledIcon();
} else if(model.isPressed() && model.isArmed()) {
icon = b.getPressedIcon();
if(icon == null) {
// Use default icon
icon = b.getIcon();
}
} else {
icon = b.getIcon();
}
if (icon!=null) {
SynthIcon.paintIcon(icon, context, g, iconRect.x,
iconRect.y, iconRect.width, iconRect.height);
}
}
// Draw the Text
if(text != null) {
View v = (View) c.getClientProperty(BasicHTML.propertyKey);
if (v != null) {
v.paint(g, textRect);
} else {
g.setColor(style.getColor(context, ColorType.TEXT_FOREGROUND));
g.setFont(style.getFont(context));
style.getGraphicsUtils(context).paintText(context, g, text,
textRect.x, textRect.y, b.getDisplayedMnemonicIndex());
}
}
// Draw the Accelerator Text
if(acceleratorText != null && !acceleratorText.equals("")) {
// Get the maxAccWidth from the parent to calculate the offset.
int accOffset = 0;
Container parent = b.getParent();
if (parent != null && parent instanceof JPopupMenu) {
SynthPopupMenuUI popupUI = (SynthPopupMenuUI)
((JPopupMenu)parent).getUI();
// Note that we can only get here for SynthMenuItemUI
// (not SynthMenuUI) since acceleratorText is defined,
// so this cast should be safe
SynthMenuItemUI miUI = (SynthMenuItemUI)
SynthLookAndFeel.getUIOfType(b.getUI(),
SynthMenuItemUI.class);
if (popupUI != null && miUI != null) {
String prop =
miUI.getPropertyPrefix() + ".alignAcceleratorText";
boolean align = style.getBoolean(context, prop, true);
// Calculate the offset, with which the accelerator texts
// will be drawn.
if (align) {
// When align==true and we're in the LTR case,
// we add an offset here so that all accelerators
// will be left-justified in their own column.
int max = popupUI.getMaxAcceleratorWidth();
if (max > 0) {
accOffset = max - acceleratorRect.width;
if (!SynthLookAndFeel.isLeftToRight(c)) {
// In the RTL, flip the sign so that all
// accelerators will be right-justified.
accOffset = -accOffset;
}
}
} //else {
// Don't need to do anything special here; in the
// LTR case, the accelerator is already justified
// against the right edge of the menu (and against
// the left edge in the RTL case).
//}
}
}
SynthStyle accStyle = accContext.getStyle();
g.setColor(accStyle.getColor(accContext,
ColorType.TEXT_FOREGROUND));
g.setFont(accStyle.getFont(accContext));
accStyle.getGraphicsUtils(accContext).paintText(
accContext, g, acceleratorText, acceleratorRect.x -
accOffset, acceleratorRect.y, -1);
}
// Paint the Arrow
if (arrowIcon != null) {
SynthIcon.paintIcon(arrowIcon, context, g, arrowIconRect.x,
arrowIconRect.y, arrowIconRect.width, arrowIconRect.height);
public void uninstallUI(JComponent c) {
super.uninstallUI(c);
// Remove values from the parent's Client Properties.
JComponent p = MenuItemLayoutHelper.getMenuItemParent((JMenuItem) c);
if (p != null) {
p.putClientProperty(
SynthMenuItemLayoutHelper.MAX_ACC_OR_ARROW_WIDTH, null);
}
}
/**
* Compute and return the location of the icons origin, the
* location of origin of the text baseline, and a possibly clipped
* version of the compound labels string. Locations are computed
* relative to the viewRect rectangle.
*/
private static String layoutMenuItem(
SynthContext context,
FontMetrics fm,
SynthContext accContext,
String text,
FontMetrics fmAccel,
String acceleratorText,
Icon icon,
Icon checkIcon,
Icon arrowIcon,
int verticalAlignment,
int horizontalAlignment,
int verticalTextPosition,
int horizontalTextPosition,
Rectangle viewRect,
Rectangle iconRect,
Rectangle textRect,
Rectangle acceleratorRect,
Rectangle checkIconRect,
Rectangle arrowIconRect,
int textIconGap,
int menuItemGap
)
{
// If parent is JPopupMenu, get and store it's UI
SynthPopupMenuUI popupUI = null;
JComponent b = context.getComponent();
Container parent = b.getParent();
if(parent instanceof JPopupMenu) {
popupUI = (SynthPopupMenuUI)SynthLookAndFeel.
getUIOfType(((JPopupMenu)parent).getUI(),
SynthPopupMenuUI.class);
}
context.getStyle().getGraphicsUtils(context).layoutText(
context, fm, text, icon,horizontalAlignment, verticalAlignment,
horizontalTextPosition, verticalTextPosition, viewRect,
iconRect, textRect, textIconGap);
/* Initialize the acceleratorText bounds rectangle textRect. If a null
* or and empty String was specified we substitute "" here
* and use 0,0,0,0 for acceleratorTextRect.
*/
if( (acceleratorText == null) || acceleratorText.equals("") ) {
acceleratorRect.width = acceleratorRect.height = 0;
acceleratorText = "";
}
else {
SynthStyle style = accContext.getStyle();
acceleratorRect.width = style.getGraphicsUtils(accContext).
computeStringWidth(accContext, fmAccel.getFont(), fmAccel,
acceleratorText);
acceleratorRect.height = fmAccel.getHeight();
}
// Initialize the checkIcon bounds rectangle width & height.
if (checkIcon != null) {
checkIconRect.width = SynthIcon.getIconWidth(checkIcon,
context);
checkIconRect.height = SynthIcon.getIconHeight(checkIcon,
context);
}
else {
checkIconRect.width = checkIconRect.height = 0;
}
// Initialize the arrowIcon bounds rectangle width & height.
if (arrowIcon != null) {
arrowIconRect.width = SynthIcon.getIconWidth(arrowIcon,
context);
arrowIconRect.height = SynthIcon.getIconHeight(arrowIcon,
context);
} else {
arrowIconRect.width = arrowIconRect.height = 0;
}
// Note: layoutText() has already left room for
// the user icon, so no need to adjust textRect below
// to account for the user icon. However, we do have to
// reposition textRect when the check icon is visible.
Rectangle labelRect = iconRect.union(textRect);
if( SynthLookAndFeel.isLeftToRight(context.getComponent()) ) {
// Position the check and user icons
iconRect.x = viewRect.x;
if (checkIcon != null) {
checkIconRect.x = viewRect.x;
iconRect.x += menuItemGap + checkIconRect.width;
textRect.x += menuItemGap + checkIconRect.width;
}
// Position the arrow icon
arrowIconRect.x =
viewRect.x + viewRect.width - arrowIconRect.width;
// Position the accelerator text rect
acceleratorRect.x =
viewRect.x + viewRect.width - acceleratorRect.width;
/* Align icons and text horizontally */
if(popupUI != null) {
int thisTextOffset = popupUI.adjustTextOffset(textRect.x
- viewRect.x);
textRect.x = thisTextOffset + viewRect.x;
if(icon != null) {
// REMIND: The following code currently assumes the
// default (TRAILING) horizontalTextPosition, which means
// it will always place the icon to the left of the text.
// Other values of horizontalTextPosition aren't very
// useful for menu items, so we ignore them for now, but
// someday we might want to fix this situation.
int thisIconOffset =
popupUI.adjustIconOffset(iconRect.x - viewRect.x);
iconRect.x = thisIconOffset + viewRect.x;
}
}
} else {
// Position the accelerator text rect
acceleratorRect.x = viewRect.x;
// Position the arrow icon
arrowIconRect.x = viewRect.x;
// Position the check and user icons
iconRect.x =
viewRect.x + viewRect.width - iconRect.width;
if (checkIcon != null) {
checkIconRect.x =
viewRect.x + viewRect.width - checkIconRect.width;
textRect.x -= menuItemGap + checkIconRect.width;
iconRect.x -= menuItemGap + checkIconRect.width;
}
/* Align icons and text horizontally */
if(popupUI != null) {
int thisTextOffset = viewRect.x + viewRect.width
- textRect.x - textRect.width;
thisTextOffset = popupUI.adjustTextOffset(thisTextOffset);
textRect.x = viewRect.x + viewRect.width
- thisTextOffset - textRect.width;
if(icon != null) {
// REMIND: The following code currently assumes the
// default (TRAILING) horizontalTextPosition, which means
// it will always place the icon to the right of the text.
// Other values of horizontalTextPosition aren't very
// useful for menu items, so we ignore them for now, but
// someday we might want to fix this situation.
int thisIconOffset = viewRect.x + viewRect.width
- iconRect.x - iconRect.width;
thisIconOffset =
popupUI.adjustIconOffset(thisIconOffset);
iconRect.x = viewRect.x + viewRect.width
- thisIconOffset - iconRect.width;
}
}
}
// Align the accelerator text and all icons vertically
// with the center of the label rect.
int midY = labelRect.y + (labelRect.height/2);
iconRect.y = midY - (iconRect.height/2);
acceleratorRect.y = midY - (acceleratorRect.height/2);
arrowIconRect.y = midY - (arrowIconRect.height/2);
checkIconRect.y = midY - (checkIconRect.height/2);
return text;
}
// these rects are used for painting and preferredsize calculations.
// they used to be regenerated constantly. Now they are reused.
static Rectangle iconRect = new Rectangle();
static Rectangle textRect = new Rectangle();
static Rectangle acceleratorRect = new Rectangle();
static Rectangle checkIconRect = new Rectangle();
static Rectangle arrowIconRect = new Rectangle();
static Rectangle viewRect = new Rectangle(Short.MAX_VALUE,Short.MAX_VALUE);
static Rectangle r = new Rectangle();
private static void resetRects() {
iconRect.setBounds(0, 0, 0, 0);
textRect.setBounds(0, 0, 0, 0);
acceleratorRect.setBounds(0, 0, 0, 0);
checkIconRect.setBounds(0, 0, 0, 0);
arrowIconRect.setBounds(0, 0, 0, 0);
viewRect.setBounds(0,0,Short.MAX_VALUE, Short.MAX_VALUE);
r.setBounds(0, 0, 0, 0);
}
protected void installDefaults() {
updateStyle(menuItem);
}
@ -718,9 +192,11 @@ class SynthMenuItemUI extends BasicMenuItemUI implements
int defaultTextIconGap) {
SynthContext context = getContext(c);
SynthContext accContext = getContext(c, Region.MENU_ITEM_ACCELERATOR);
Dimension value = getPreferredMenuItemSize(context, accContext,
c, checkIcon, arrowIcon, defaultTextIconGap,
acceleratorDelimiter);
Dimension value = SynthGraphicsUtils.getPreferredMenuItemSize(
context, accContext, c, checkIcon, arrowIcon,
defaultTextIconGap, acceleratorDelimiter,
MenuItemLayoutHelper.useCheckAndArrow(menuItem),
getPropertyPrefix());
context.dispose();
accContext.dispose();
return value;
@ -751,14 +227,13 @@ class SynthMenuItemUI extends BasicMenuItemUI implements
String prefix = getPropertyPrefix();
Icon checkIcon = style.getIcon(context, prefix + ".checkIcon");
Icon arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
paint(context, accContext, g, checkIcon, arrowIcon,
acceleratorDelimiter, defaultTextIconGap);
SynthGraphicsUtils.paint(context, accContext, g, checkIcon, arrowIcon,
acceleratorDelimiter, defaultTextIconGap, getPropertyPrefix());
accContext.dispose();
}
void paintBackground(SynthContext context, Graphics g, JComponent c) {
context.getPainter().paintMenuItemBackground(context, g, 0, 0,
c.getWidth(), c.getHeight());
SynthGraphicsUtils.paintBackground(context, g, c);
}
public void paintBorder(SynthContext context, Graphics g, int x,

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,7 +35,7 @@ import javax.swing.border.*;
import java.util.Arrays;
import java.util.ArrayList;
import sun.swing.plaf.synth.SynthUI;
import sun.swing.MenuItemLayoutHelper;
/**
* Synth's MenuUI.
@ -86,7 +86,7 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
acceleratorDelimiter = style.getString(context, prefix +
".acceleratorDelimiter", "+");
if (useCheckAndArrow()) {
if (MenuItemLayoutHelper.useCheckAndArrow(menuItem)) {
checkIcon = style.getIcon(context, prefix + ".checkIcon");
arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
} else {
@ -111,6 +111,16 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
accContext.dispose();
}
public void uninstallUI(JComponent c) {
super.uninstallUI(c);
// Remove values from the parent's Client Properties.
JComponent p = MenuItemLayoutHelper.getMenuItemParent((JMenuItem) c);
if (p != null) {
p.putClientProperty(
SynthMenuItemLayoutHelper.MAX_ACC_OR_ARROW_WIDTH, null);
}
}
protected void uninstallDefaults() {
SynthContext context = getContext(menuItem, ENABLED);
style.uninstallDefaults(context);
@ -182,9 +192,11 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
int defaultTextIconGap) {
SynthContext context = getContext(c);
SynthContext accContext = getContext(c, Region.MENU_ITEM_ACCELERATOR);
Dimension value = SynthMenuItemUI.getPreferredMenuItemSize(
context, accContext, c, checkIcon, arrowIcon,
defaultTextIconGap, acceleratorDelimiter);
Dimension value = SynthGraphicsUtils.getPreferredMenuItemSize(
context, accContext, c, checkIcon, arrowIcon,
defaultTextIconGap, acceleratorDelimiter,
MenuItemLayoutHelper.useCheckAndArrow(menuItem),
getPropertyPrefix());
context.dispose();
accContext.dispose();
return value;
@ -211,21 +223,12 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
protected void paint(SynthContext context, Graphics g) {
SynthContext accContext = getContext(menuItem,
Region.MENU_ITEM_ACCELERATOR);
SynthStyle style = context.getStyle();
Icon checkIcon;
Icon arrowIcon;
if (useCheckAndArrow()) {
// Refetch the appropriate icons for the current state
String prefix = getPropertyPrefix();
checkIcon = style.getIcon(context, prefix + ".checkIcon");
arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
} else {
// Not needed in this case
checkIcon = null;
arrowIcon = null;
}
SynthMenuItemUI.paint(context, accContext, g, checkIcon, arrowIcon,
acceleratorDelimiter, defaultTextIconGap);
// Refetch the appropriate check indicator for the current state
String prefix = getPropertyPrefix();
Icon checkIcon = style.getIcon(context, prefix + ".checkIcon");
Icon arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
SynthGraphicsUtils.paint(context, accContext, g, checkIcon, arrowIcon,
acceleratorDelimiter, defaultTextIconGap, getPropertyPrefix());
accContext.dispose();
}
@ -239,8 +242,4 @@ class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
updateStyle((JMenu)e.getSource());
}
}
private boolean useCheckAndArrow() {
return !((JMenu)menuItem).isTopLevelMenu();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -58,34 +58,6 @@ import sun.swing.plaf.synth.SynthUI;
*/
class SynthPopupMenuUI extends BasicPopupMenuUI implements
PropertyChangeListener, SynthUI {
/**
* Maximum size of the text portion of the children menu items.
*/
private int maxTextWidth;
/**
* Maximum size of the icon portion of the children menu items.
*/
private int maxIconWidth;
/**
* Maximum size of the spacing between the text and accelerator
* portions of the children menu items.
*/
private int maxAccelSpacingWidth;
/**
* Maximum size of the text for the accelerator portion of the children
* menu items.
*/
private int maxAcceleratorWidth;
/*
* Maximum icon and text offsets of the children menu items.
*/
private int maxTextOffset;
private int maxIconOffset;
private SynthStyle style;
public static ComponentUI createUI(JComponent x) {
@ -153,90 +125,6 @@ class SynthPopupMenuUI extends BasicPopupMenuUI implements
return SynthLookAndFeel.getComponentState(c);
}
/**
* Resets the max text and accerator widths,
* text and icon offsets.
*/
void resetAlignmentHints() {
maxTextWidth = maxIconWidth
= maxAccelSpacingWidth = maxAcceleratorWidth
= maxTextOffset = maxIconOffset = 0;
}
/**
* Adjusts the width needed to display the maximum menu item string.
*
* @param width Text width.
* @return max width
*/
int adjustTextWidth(int width) {
maxTextWidth = Math.max(maxTextWidth, width);
return maxTextWidth;
}
/**
* Adjusts the width needed to display the maximum menu item icon.
*
* @param width Icon width.
* @return max width
*/
int adjustIconWidth(int width) {
maxIconWidth = Math.max(maxIconWidth, width);
return maxIconWidth;
}
/**
* Adjusts the width needed to pad between the maximum menu item
* text and accelerator.
*
* @param width Spacing width.
* @return max width
*/
int adjustAccelSpacingWidth(int width) {
maxAccelSpacingWidth = Math.max(maxAccelSpacingWidth, width);
return maxAccelSpacingWidth;
}
/**
* Adjusts the width needed to display the maximum accelerator.
*
* @param width Text width.
* @return max width
*/
int adjustAcceleratorWidth(int width) {
maxAcceleratorWidth = Math.max(maxAcceleratorWidth, width);
return maxAcceleratorWidth;
}
/**
* Maximum size needed to display accelerators of children menu items.
*/
int getMaxAcceleratorWidth() {
return maxAcceleratorWidth;
}
/**
* Adjusts the text offset needed to align text horizontally.
*
* @param offset Text offset
* @return max offset
*/
int adjustTextOffset(int offset) {
maxTextOffset = Math.max(maxTextOffset, offset);
return maxTextOffset;
}
/**
* Adjusts the icon offset needed to align icons horizontally
*
* @param offset Icon offset
* @return max offset
*/
int adjustIconOffset(int offset) {
maxIconOffset = Math.max(maxIconOffset, offset);
return maxIconOffset;
}
public void update(Graphics g, JComponent c) {
SynthContext context = getContext(c);

File diff suppressed because it is too large Load Diff