/* * Copyright (c) 2002, 2008, Oracle and/or its affiliates. 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.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()); 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()); }}
/*
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.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());
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());
}
}