You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
11 KiB
309 lines
11 KiB
/*
|
|
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
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());
|
|
textRect.width += getLeftTextExtraWidth();
|
|
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());
|
|
}
|
|
}
|