1324 lines
42 KiB
Java
1324 lines
42 KiB
Java
/*
|
|
* 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 sun.swing;
|
|
|
|
import static sun.swing.SwingUtilities2.BASICMENUITEMUI_MAX_TEXT_OFFSET;
|
|
|
|
import javax.swing.*;
|
|
import javax.swing.plaf.basic.BasicHTML;
|
|
import javax.swing.text.View;
|
|
import java.awt.*;
|
|
import java.awt.event.KeyEvent;
|
|
import java.util.Map;
|
|
import java.util.HashMap;
|
|
|
|
/**
|
|
* Calculates preferred size and layouts menu items.
|
|
*/
|
|
public class MenuItemLayoutHelper {
|
|
|
|
/* Client Property keys for calculation of maximal widths */
|
|
public static final StringUIClientPropertyKey MAX_ARROW_WIDTH =
|
|
new StringUIClientPropertyKey("maxArrowWidth");
|
|
public static final StringUIClientPropertyKey MAX_CHECK_WIDTH =
|
|
new StringUIClientPropertyKey("maxCheckWidth");
|
|
public static final StringUIClientPropertyKey MAX_ICON_WIDTH =
|
|
new StringUIClientPropertyKey("maxIconWidth");
|
|
public static final StringUIClientPropertyKey MAX_TEXT_WIDTH =
|
|
new StringUIClientPropertyKey("maxTextWidth");
|
|
public static final StringUIClientPropertyKey MAX_ACC_WIDTH =
|
|
new StringUIClientPropertyKey("maxAccWidth");
|
|
public static final StringUIClientPropertyKey MAX_LABEL_WIDTH =
|
|
new StringUIClientPropertyKey("maxLabelWidth");
|
|
|
|
private JMenuItem mi;
|
|
private JComponent miParent;
|
|
|
|
private Font font;
|
|
private Font accFont;
|
|
private FontMetrics fm;
|
|
private FontMetrics accFm;
|
|
|
|
private Icon icon;
|
|
private Icon checkIcon;
|
|
private Icon arrowIcon;
|
|
private String text;
|
|
private String accText;
|
|
|
|
private boolean isColumnLayout;
|
|
private boolean useCheckAndArrow;
|
|
private boolean isLeftToRight;
|
|
private boolean isTopLevelMenu;
|
|
private View htmlView;
|
|
|
|
private int verticalAlignment;
|
|
private int horizontalAlignment;
|
|
private int verticalTextPosition;
|
|
private int horizontalTextPosition;
|
|
private int gap;
|
|
private int leadingGap;
|
|
private int afterCheckIconGap;
|
|
private int minTextOffset;
|
|
|
|
private int leftTextExtraWidth;
|
|
|
|
private Rectangle viewRect;
|
|
|
|
private RectSize iconSize;
|
|
private RectSize textSize;
|
|
private RectSize accSize;
|
|
private RectSize checkSize;
|
|
private RectSize arrowSize;
|
|
private RectSize labelSize;
|
|
|
|
/**
|
|
* The empty protected constructor is necessary for derived classes.
|
|
*/
|
|
protected MenuItemLayoutHelper() {
|
|
}
|
|
|
|
public MenuItemLayoutHelper(JMenuItem mi, Icon checkIcon, Icon arrowIcon,
|
|
Rectangle viewRect, int gap, String accDelimiter,
|
|
boolean isLeftToRight, Font font, Font accFont,
|
|
boolean useCheckAndArrow, String propertyPrefix) {
|
|
reset(mi, checkIcon, arrowIcon, viewRect, gap, accDelimiter,
|
|
isLeftToRight, font, accFont, useCheckAndArrow, propertyPrefix);
|
|
}
|
|
|
|
protected void reset(JMenuItem mi, Icon checkIcon, Icon arrowIcon,
|
|
Rectangle viewRect, int gap, String accDelimiter,
|
|
boolean isLeftToRight, Font font, Font accFont,
|
|
boolean useCheckAndArrow, String propertyPrefix) {
|
|
this.mi = mi;
|
|
this.miParent = getMenuItemParent(mi);
|
|
this.accText = getAccText(accDelimiter);
|
|
this.verticalAlignment = mi.getVerticalAlignment();
|
|
this.horizontalAlignment = mi.getHorizontalAlignment();
|
|
this.verticalTextPosition = mi.getVerticalTextPosition();
|
|
this.horizontalTextPosition = mi.getHorizontalTextPosition();
|
|
this.useCheckAndArrow = useCheckAndArrow;
|
|
this.font = font;
|
|
this.accFont = accFont;
|
|
this.fm = mi.getFontMetrics(font);
|
|
this.accFm = mi.getFontMetrics(accFont);
|
|
this.isLeftToRight = isLeftToRight;
|
|
this.isColumnLayout = isColumnLayout(isLeftToRight,
|
|
horizontalAlignment, horizontalTextPosition,
|
|
verticalTextPosition);
|
|
this.isTopLevelMenu = (this.miParent == null) ? true : false;
|
|
this.checkIcon = checkIcon;
|
|
this.icon = getIcon(propertyPrefix);
|
|
this.arrowIcon = arrowIcon;
|
|
this.text = mi.getText();
|
|
this.gap = gap;
|
|
this.afterCheckIconGap = getAfterCheckIconGap(propertyPrefix);
|
|
this.minTextOffset = getMinTextOffset(propertyPrefix);
|
|
this.htmlView = (View) mi.getClientProperty(BasicHTML.propertyKey);
|
|
this.viewRect = viewRect;
|
|
|
|
this.iconSize = new RectSize();
|
|
this.textSize = new RectSize();
|
|
this.accSize = new RectSize();
|
|
this.checkSize = new RectSize();
|
|
this.arrowSize = new RectSize();
|
|
this.labelSize = new RectSize();
|
|
calcExtraWidths();
|
|
calcWidthsAndHeights();
|
|
setOriginalWidths();
|
|
calcMaxWidths();
|
|
|
|
this.leadingGap = getLeadingGap(propertyPrefix);
|
|
calcMaxTextOffset(viewRect);
|
|
}
|
|
|
|
private void calcExtraWidths() {
|
|
leftTextExtraWidth = getLeftExtraWidth(text);
|
|
}
|
|
|
|
private int getLeftExtraWidth(String str) {
|
|
int lsb = SwingUtilities2.getLeftSideBearing(mi, fm, str);
|
|
if (lsb < 0) {
|
|
return -lsb;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
private void setOriginalWidths() {
|
|
iconSize.origWidth = iconSize.width;
|
|
textSize.origWidth = textSize.width;
|
|
accSize.origWidth = accSize.width;
|
|
checkSize.origWidth = checkSize.width;
|
|
arrowSize.origWidth = arrowSize.width;
|
|
}
|
|
|
|
private String getAccText(String acceleratorDelimiter) {
|
|
String accText = "";
|
|
KeyStroke accelerator = mi.getAccelerator();
|
|
if (accelerator != null) {
|
|
int modifiers = accelerator.getModifiers();
|
|
if (modifiers > 0) {
|
|
accText = KeyEvent.getKeyModifiersText(modifiers);
|
|
accText += acceleratorDelimiter;
|
|
}
|
|
int keyCode = accelerator.getKeyCode();
|
|
if (keyCode != 0) {
|
|
accText += KeyEvent.getKeyText(keyCode);
|
|
} else {
|
|
accText += accelerator.getKeyChar();
|
|
}
|
|
}
|
|
return accText;
|
|
}
|
|
|
|
private Icon getIcon(String propertyPrefix) {
|
|
// In case of column layout, .checkIconFactory is defined for this UI,
|
|
// the icon is compatible with it and useCheckAndArrow() is true,
|
|
// then the icon is handled by the checkIcon.
|
|
Icon icon = null;
|
|
MenuItemCheckIconFactory iconFactory =
|
|
(MenuItemCheckIconFactory) UIManager.get(propertyPrefix
|
|
+ ".checkIconFactory");
|
|
if (!isColumnLayout || !useCheckAndArrow || iconFactory == null
|
|
|| !iconFactory.isCompatible(checkIcon, propertyPrefix)) {
|
|
icon = mi.getIcon();
|
|
}
|
|
return icon;
|
|
}
|
|
|
|
private int getMinTextOffset(String propertyPrefix) {
|
|
int minimumTextOffset = 0;
|
|
Object minimumTextOffsetObject =
|
|
UIManager.get(propertyPrefix + ".minimumTextOffset");
|
|
if (minimumTextOffsetObject instanceof Integer) {
|
|
minimumTextOffset = (Integer) minimumTextOffsetObject;
|
|
}
|
|
return minimumTextOffset;
|
|
}
|
|
|
|
private int getAfterCheckIconGap(String propertyPrefix) {
|
|
int afterCheckIconGap = gap;
|
|
Object afterCheckIconGapObject =
|
|
UIManager.get(propertyPrefix + ".afterCheckIconGap");
|
|
if (afterCheckIconGapObject instanceof Integer) {
|
|
afterCheckIconGap = (Integer) afterCheckIconGapObject;
|
|
}
|
|
return afterCheckIconGap;
|
|
}
|
|
|
|
private int getLeadingGap(String propertyPrefix) {
|
|
if (checkSize.getMaxWidth() > 0) {
|
|
return getCheckOffset(propertyPrefix);
|
|
} else {
|
|
return gap; // There is no any check icon
|
|
}
|
|
}
|
|
|
|
private int getCheckOffset(String propertyPrefix) {
|
|
int checkIconOffset = gap;
|
|
Object checkIconOffsetObject =
|
|
UIManager.get(propertyPrefix + ".checkIconOffset");
|
|
if (checkIconOffsetObject instanceof Integer) {
|
|
checkIconOffset = (Integer) checkIconOffsetObject;
|
|
}
|
|
return checkIconOffset;
|
|
}
|
|
|
|
protected void calcWidthsAndHeights() {
|
|
// iconRect
|
|
if (icon != null) {
|
|
iconSize.width = icon.getIconWidth();
|
|
iconSize.height = icon.getIconHeight();
|
|
}
|
|
|
|
// accRect
|
|
if (!accText.equals("")) {
|
|
accSize.width = SwingUtilities2.stringWidth(mi, accFm, accText);
|
|
accSize.height = accFm.getHeight();
|
|
}
|
|
|
|
// textRect
|
|
if (text == null) {
|
|
text = "";
|
|
} else if (!text.equals("")) {
|
|
if (htmlView != null) {
|
|
// Text is HTML
|
|
textSize.width =
|
|
(int) htmlView.getPreferredSpan(View.X_AXIS);
|
|
textSize.height =
|
|
(int) htmlView.getPreferredSpan(View.Y_AXIS);
|
|
} else {
|
|
// Text isn't HTML
|
|
textSize.width = SwingUtilities2.stringWidth(mi, fm, text);
|
|
textSize.height = fm.getHeight();
|
|
}
|
|
}
|
|
|
|
if (useCheckAndArrow) {
|
|
// checkIcon
|
|
if (checkIcon != null) {
|
|
checkSize.width = checkIcon.getIconWidth();
|
|
checkSize.height = checkIcon.getIconHeight();
|
|
}
|
|
// arrowRect
|
|
if (arrowIcon != null) {
|
|
arrowSize.width = arrowIcon.getIconWidth();
|
|
arrowSize.height = arrowIcon.getIconHeight();
|
|
}
|
|
}
|
|
|
|
// labelRect
|
|
if (isColumnLayout) {
|
|
labelSize.width = iconSize.width + textSize.width + gap;
|
|
labelSize.height = max(checkSize.height, iconSize.height,
|
|
textSize.height, accSize.height, arrowSize.height);
|
|
} else {
|
|
Rectangle textRect = new Rectangle();
|
|
Rectangle iconRect = new Rectangle();
|
|
SwingUtilities.layoutCompoundLabel(mi, fm, text, icon,
|
|
verticalAlignment, horizontalAlignment,
|
|
verticalTextPosition, horizontalTextPosition,
|
|
viewRect, iconRect, textRect, gap);
|
|
textRect.width += leftTextExtraWidth;
|
|
Rectangle labelRect = iconRect.union(textRect);
|
|
labelSize.height = labelRect.height;
|
|
labelSize.width = labelRect.width;
|
|
}
|
|
}
|
|
|
|
protected void calcMaxWidths() {
|
|
calcMaxWidth(checkSize, MAX_CHECK_WIDTH);
|
|
calcMaxWidth(arrowSize, MAX_ARROW_WIDTH);
|
|
calcMaxWidth(accSize, MAX_ACC_WIDTH);
|
|
|
|
if (isColumnLayout) {
|
|
calcMaxWidth(iconSize, MAX_ICON_WIDTH);
|
|
calcMaxWidth(textSize, MAX_TEXT_WIDTH);
|
|
int curGap = gap;
|
|
if ((iconSize.getMaxWidth() == 0)
|
|
|| (textSize.getMaxWidth() == 0)) {
|
|
curGap = 0;
|
|
}
|
|
labelSize.maxWidth =
|
|
calcMaxValue(MAX_LABEL_WIDTH, iconSize.maxWidth
|
|
+ textSize.maxWidth + curGap);
|
|
} else {
|
|
// We shouldn't use current icon and text widths
|
|
// in maximal widths calculation for complex layout.
|
|
iconSize.maxWidth = getParentIntProperty(MAX_ICON_WIDTH);
|
|
calcMaxWidth(labelSize, MAX_LABEL_WIDTH);
|
|
// If maxLabelWidth is wider
|
|
// than the widest icon + the widest text + gap,
|
|
// we should update the maximal text witdh
|
|
int candidateTextWidth = labelSize.maxWidth - iconSize.maxWidth;
|
|
if (iconSize.maxWidth > 0) {
|
|
candidateTextWidth -= gap;
|
|
}
|
|
textSize.maxWidth = calcMaxValue(MAX_TEXT_WIDTH, candidateTextWidth);
|
|
}
|
|
}
|
|
|
|
protected void calcMaxWidth(RectSize rs, Object key) {
|
|
rs.maxWidth = calcMaxValue(key, rs.width);
|
|
}
|
|
|
|
/**
|
|
* Calculates and returns maximal value through specified parent component
|
|
* client property.
|
|
*
|
|
* @param propertyName name of the property, which stores the maximal value.
|
|
* @param value a value which pretends to be maximal
|
|
* @return maximal value among the parent property and the value.
|
|
*/
|
|
protected int calcMaxValue(Object propertyName, int value) {
|
|
// Get maximal value from parent client property
|
|
int maxValue = getParentIntProperty(propertyName);
|
|
// Store new maximal width in parent client property
|
|
if (value > maxValue) {
|
|
if (miParent != null) {
|
|
miParent.putClientProperty(propertyName, value);
|
|
}
|
|
return value;
|
|
} else {
|
|
return maxValue;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns parent client property as int.
|
|
* @param propertyName name of the parent property.
|
|
* @return value of the property as int.
|
|
*/
|
|
protected int getParentIntProperty(Object propertyName) {
|
|
Object value = null;
|
|
if (miParent != null) {
|
|
value = miParent.getClientProperty(propertyName);
|
|
}
|
|
if ((value == null) || !(value instanceof Integer)) {
|
|
value = 0;
|
|
}
|
|
return (Integer) value;
|
|
}
|
|
|
|
public static boolean isColumnLayout(boolean isLeftToRight,
|
|
JMenuItem mi) {
|
|
assert(mi != null);
|
|
return isColumnLayout(isLeftToRight, mi.getHorizontalAlignment(),
|
|
mi.getHorizontalTextPosition(), mi.getVerticalTextPosition());
|
|
}
|
|
|
|
/**
|
|
* Answers should we do column layout for a menu item or not.
|
|
* We do it when a user doesn't set any alignments
|
|
* and text positions manually, except the vertical alignment.
|
|
*/
|
|
public static boolean isColumnLayout(boolean isLeftToRight,
|
|
int horizontalAlignment,
|
|
int horizontalTextPosition,
|
|
int verticalTextPosition) {
|
|
if (verticalTextPosition != SwingConstants.CENTER) {
|
|
return false;
|
|
}
|
|
if (isLeftToRight) {
|
|
if (horizontalAlignment != SwingConstants.LEADING
|
|
&& horizontalAlignment != SwingConstants.LEFT) {
|
|
return false;
|
|
}
|
|
if (horizontalTextPosition != SwingConstants.TRAILING
|
|
&& horizontalTextPosition != SwingConstants.RIGHT) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if (horizontalAlignment != SwingConstants.LEADING
|
|
&& horizontalAlignment != SwingConstants.RIGHT) {
|
|
return false;
|
|
}
|
|
if (horizontalTextPosition != SwingConstants.TRAILING
|
|
&& horizontalTextPosition != SwingConstants.LEFT) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Calculates maximal text offset.
|
|
* It is required for some L&Fs (ex: Vista L&F).
|
|
* The offset is meaningful only for L2R column layout.
|
|
*
|
|
* @param viewRect the rectangle, the maximal text offset
|
|
* will be calculated for.
|
|
*/
|
|
private void calcMaxTextOffset(Rectangle viewRect) {
|
|
if (!isColumnLayout || !isLeftToRight) {
|
|
return;
|
|
}
|
|
|
|
// Calculate the current text offset
|
|
int offset = viewRect.x + leadingGap + checkSize.maxWidth
|
|
+ afterCheckIconGap + iconSize.maxWidth + gap;
|
|
if (checkSize.maxWidth == 0) {
|
|
offset -= afterCheckIconGap;
|
|
}
|
|
if (iconSize.maxWidth == 0) {
|
|
offset -= gap;
|
|
}
|
|
|
|
// maximal text offset shouldn't be less than minimal text offset;
|
|
if (offset < minTextOffset) {
|
|
offset = minTextOffset;
|
|
}
|
|
|
|
// Calculate and store the maximal text offset
|
|
calcMaxValue(SwingUtilities2.BASICMENUITEMUI_MAX_TEXT_OFFSET, offset);
|
|
}
|
|
|
|
/**
|
|
* Layout icon, text, check icon, accelerator text and arrow icon
|
|
* in the viewRect and return their positions.
|
|
*
|
|
* If horizontalAlignment, verticalTextPosition and horizontalTextPosition
|
|
* are default (user doesn't set any manually) the layouting algorithm is:
|
|
* Elements are layouted in the five columns:
|
|
* check icon + icon + text + accelerator text + arrow icon
|
|
*
|
|
* In the other case elements are layouted in the four columns:
|
|
* check icon + label + accelerator text + arrow icon
|
|
* Label is union of icon and text.
|
|
*
|
|
* The order of columns can be reversed.
|
|
* It depends on the menu item orientation.
|
|
*/
|
|
public LayoutResult layoutMenuItem() {
|
|
LayoutResult lr = createLayoutResult();
|
|
prepareForLayout(lr);
|
|
|
|
if (isColumnLayout()) {
|
|
if (isLeftToRight()) {
|
|
doLTRColumnLayout(lr, getLTRColumnAlignment());
|
|
} else {
|
|
doRTLColumnLayout(lr, getRTLColumnAlignment());
|
|
}
|
|
} else {
|
|
if (isLeftToRight()) {
|
|
doLTRComplexLayout(lr, getLTRColumnAlignment());
|
|
} else {
|
|
doRTLComplexLayout(lr, getRTLColumnAlignment());
|
|
}
|
|
}
|
|
|
|
alignAccCheckAndArrowVertically(lr);
|
|
return lr;
|
|
}
|
|
|
|
private LayoutResult createLayoutResult() {
|
|
return new LayoutResult(
|
|
new Rectangle(iconSize.width, iconSize.height),
|
|
new Rectangle(textSize.width, textSize.height),
|
|
new Rectangle(accSize.width, accSize.height),
|
|
new Rectangle(checkSize.width, checkSize.height),
|
|
new Rectangle(arrowSize.width, arrowSize.height),
|
|
new Rectangle(labelSize.width, labelSize.height)
|
|
);
|
|
}
|
|
|
|
public ColumnAlignment getLTRColumnAlignment() {
|
|
return ColumnAlignment.LEFT_ALIGNMENT;
|
|
}
|
|
|
|
public ColumnAlignment getRTLColumnAlignment() {
|
|
return ColumnAlignment.RIGHT_ALIGNMENT;
|
|
}
|
|
|
|
protected void prepareForLayout(LayoutResult lr) {
|
|
lr.checkRect.width = checkSize.maxWidth;
|
|
lr.accRect.width = accSize.maxWidth;
|
|
lr.arrowRect.width = arrowSize.maxWidth;
|
|
}
|
|
|
|
/**
|
|
* Aligns the accelertor text and the check and arrow icons vertically
|
|
* with the center of the label rect.
|
|
*/
|
|
private void alignAccCheckAndArrowVertically(LayoutResult lr) {
|
|
lr.accRect.y = (int)(lr.labelRect.y
|
|
+ (float)lr.labelRect.height/2
|
|
- (float)lr.accRect.height/2);
|
|
fixVerticalAlignment(lr, lr.accRect);
|
|
if (useCheckAndArrow) {
|
|
lr.arrowRect.y = (int)(lr.labelRect.y
|
|
+ (float)lr.labelRect.height/2
|
|
- (float)lr.arrowRect.height/2);
|
|
lr.checkRect.y = (int)(lr.labelRect.y
|
|
+ (float)lr.labelRect.height/2
|
|
- (float)lr.checkRect.height/2);
|
|
fixVerticalAlignment(lr, lr.arrowRect);
|
|
fixVerticalAlignment(lr, lr.checkRect);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fixes vertical alignment of all menu item elements if rect.y
|
|
* or (rect.y + rect.height) is out of viewRect bounds
|
|
*/
|
|
private void fixVerticalAlignment(LayoutResult lr, Rectangle r) {
|
|
int delta = 0;
|
|
if (r.y < viewRect.y) {
|
|
delta = viewRect.y - r.y;
|
|
} else if (r.y + r.height > viewRect.y + viewRect.height) {
|
|
delta = viewRect.y + viewRect.height - r.y - r.height;
|
|
}
|
|
if (delta != 0) {
|
|
lr.checkRect.y += delta;
|
|
lr.iconRect.y += delta;
|
|
lr.textRect.y += delta;
|
|
lr.accRect.y += delta;
|
|
lr.arrowRect.y += delta;
|
|
lr.labelRect.y += delta;
|
|
}
|
|
}
|
|
|
|
private void doLTRColumnLayout(LayoutResult lr, ColumnAlignment alignment) {
|
|
// Set maximal width for all the five basic rects
|
|
// (three other ones are already maximal)
|
|
lr.iconRect.width = iconSize.maxWidth;
|
|
lr.textRect.width = textSize.maxWidth;
|
|
|
|
// Set X coordinates
|
|
// All rects will be aligned at the left side
|
|
calcXPositionsLTR(viewRect.x, leadingGap, gap, lr.checkRect,
|
|
lr.iconRect, lr.textRect);
|
|
|
|
// Tune afterCheckIconGap
|
|
if (lr.checkRect.width > 0) { // there is the afterCheckIconGap
|
|
lr.iconRect.x += afterCheckIconGap - gap;
|
|
lr.textRect.x += afterCheckIconGap - gap;
|
|
}
|
|
|
|
calcXPositionsRTL(viewRect.x + viewRect.width, leadingGap, gap,
|
|
lr.arrowRect, lr.accRect);
|
|
|
|
// Take into account minimal text offset
|
|
int textOffset = lr.textRect.x - viewRect.x;
|
|
if (!isTopLevelMenu && (textOffset < minTextOffset)) {
|
|
lr.textRect.x += minTextOffset - textOffset;
|
|
}
|
|
|
|
alignRects(lr, alignment);
|
|
|
|
// Set Y coordinate for text and icon.
|
|
// Y coordinates for other rects
|
|
// will be calculated later in layoutMenuItem.
|
|
calcTextAndIconYPositions(lr);
|
|
|
|
// Calculate valid X and Y coordinates for labelRect
|
|
lr.setLabelRect(lr.textRect.union(lr.iconRect));
|
|
}
|
|
|
|
private void doLTRComplexLayout(LayoutResult lr, ColumnAlignment alignment) {
|
|
lr.labelRect.width = labelSize.maxWidth;
|
|
|
|
// Set X coordinates
|
|
calcXPositionsLTR(viewRect.x, leadingGap, gap, lr.checkRect,
|
|
lr.labelRect);
|
|
|
|
// Tune afterCheckIconGap
|
|
if (lr.checkRect.width > 0) { // there is the afterCheckIconGap
|
|
lr.labelRect.x += afterCheckIconGap - gap;
|
|
}
|
|
|
|
calcXPositionsRTL(viewRect.x + viewRect.width,
|
|
leadingGap, gap, lr.arrowRect, lr.accRect);
|
|
|
|
// Take into account minimal text offset
|
|
int labelOffset = lr.labelRect.x - viewRect.x;
|
|
if (!isTopLevelMenu && (labelOffset < minTextOffset)) {
|
|
lr.labelRect.x += minTextOffset - labelOffset;
|
|
}
|
|
|
|
alignRects(lr, alignment);
|
|
|
|
// Center labelRect vertically
|
|
calcLabelYPosition(lr);
|
|
|
|
layoutIconAndTextInLabelRect(lr);
|
|
}
|
|
|
|
private void doRTLColumnLayout(LayoutResult lr, ColumnAlignment alignment) {
|
|
// Set maximal width for all the five basic rects
|
|
// (three other ones are already maximal)
|
|
lr.iconRect.width = iconSize.maxWidth;
|
|
lr.textRect.width = textSize.maxWidth;
|
|
|
|
// Set X coordinates
|
|
calcXPositionsRTL(viewRect.x + viewRect.width, leadingGap, gap,
|
|
lr.checkRect, lr.iconRect, lr.textRect);
|
|
|
|
// Tune the gap after check icon
|
|
if (lr.checkRect.width > 0) { // there is the gap after check icon
|
|
lr.iconRect.x -= afterCheckIconGap - gap;
|
|
lr.textRect.x -= afterCheckIconGap - gap;
|
|
}
|
|
|
|
calcXPositionsLTR(viewRect.x, leadingGap, gap, lr.arrowRect,
|
|
lr.accRect);
|
|
|
|
// Take into account minimal text offset
|
|
int textOffset = (viewRect.x + viewRect.width)
|
|
- (lr.textRect.x + lr.textRect.width);
|
|
if (!isTopLevelMenu && (textOffset < minTextOffset)) {
|
|
lr.textRect.x -= minTextOffset - textOffset;
|
|
}
|
|
|
|
alignRects(lr, alignment);
|
|
|
|
// Set Y coordinates for text and icon.
|
|
// Y coordinates for other rects
|
|
// will be calculated later in layoutMenuItem.
|
|
calcTextAndIconYPositions(lr);
|
|
|
|
// Calculate valid X and Y coordinate for labelRect
|
|
lr.setLabelRect(lr.textRect.union(lr.iconRect));
|
|
}
|
|
|
|
private void doRTLComplexLayout(LayoutResult lr, ColumnAlignment alignment) {
|
|
lr.labelRect.width = labelSize.maxWidth;
|
|
|
|
// Set X coordinates
|
|
calcXPositionsRTL(viewRect.x + viewRect.width, leadingGap, gap,
|
|
lr.checkRect, lr.labelRect);
|
|
|
|
// Tune the gap after check icon
|
|
if (lr.checkRect.width > 0) { // there is the gap after check icon
|
|
lr.labelRect.x -= afterCheckIconGap - gap;
|
|
}
|
|
|
|
calcXPositionsLTR(viewRect.x, leadingGap, gap, lr.arrowRect, lr.accRect);
|
|
|
|
// Take into account minimal text offset
|
|
int labelOffset = (viewRect.x + viewRect.width)
|
|
- (lr.labelRect.x + lr.labelRect.width);
|
|
if (!isTopLevelMenu && (labelOffset < minTextOffset)) {
|
|
lr.labelRect.x -= minTextOffset - labelOffset;
|
|
}
|
|
|
|
alignRects(lr, alignment);
|
|
|
|
// Center labelRect vertically
|
|
calcLabelYPosition(lr);
|
|
|
|
layoutIconAndTextInLabelRect(lr);
|
|
}
|
|
|
|
private void alignRects(LayoutResult lr, ColumnAlignment alignment) {
|
|
alignRect(lr.checkRect, alignment.getCheckAlignment(),
|
|
checkSize.getOrigWidth());
|
|
alignRect(lr.iconRect, alignment.getIconAlignment(),
|
|
iconSize.getOrigWidth());
|
|
alignRect(lr.textRect, alignment.getTextAlignment(),
|
|
textSize.getOrigWidth());
|
|
alignRect(lr.accRect, alignment.getAccAlignment(),
|
|
accSize.getOrigWidth());
|
|
alignRect(lr.arrowRect, alignment.getArrowAlignment(),
|
|
arrowSize.getOrigWidth());
|
|
}
|
|
|
|
private void alignRect(Rectangle rect, int alignment, int origWidth) {
|
|
if (alignment == SwingConstants.RIGHT) {
|
|
rect.x = rect.x + rect.width - origWidth;
|
|
}
|
|
rect.width = origWidth;
|
|
}
|
|
|
|
protected void layoutIconAndTextInLabelRect(LayoutResult lr) {
|
|
lr.setTextRect(new Rectangle());
|
|
lr.setIconRect(new Rectangle());
|
|
SwingUtilities.layoutCompoundLabel(
|
|
mi, fm, text,icon, verticalAlignment, horizontalAlignment,
|
|
verticalTextPosition, horizontalTextPosition, lr.labelRect,
|
|
lr.iconRect, lr.textRect, gap);
|
|
}
|
|
|
|
private void calcXPositionsLTR(int startXPos, int leadingGap,
|
|
int gap, Rectangle... rects) {
|
|
int curXPos = startXPos + leadingGap;
|
|
for (Rectangle rect : rects) {
|
|
rect.x = curXPos;
|
|
if (rect.width > 0) {
|
|
curXPos += rect.width + gap;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void calcXPositionsRTL(int startXPos, int leadingGap,
|
|
int gap, Rectangle... rects) {
|
|
int curXPos = startXPos - leadingGap;
|
|
for (Rectangle rect : rects) {
|
|
rect.x = curXPos - rect.width;
|
|
if (rect.width > 0) {
|
|
curXPos -= rect.width + gap;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets Y coordinates of text and icon
|
|
* taking into account the vertical alignment
|
|
*/
|
|
private void calcTextAndIconYPositions(LayoutResult lr) {
|
|
if (verticalAlignment == SwingUtilities.TOP) {
|
|
lr.textRect.y = (int)(viewRect.y
|
|
+ (float)lr.labelRect.height/2
|
|
- (float)lr.textRect.height/2);
|
|
lr.iconRect.y = (int)(viewRect.y
|
|
+ (float)lr.labelRect.height/2
|
|
- (float)lr.iconRect.height/2);
|
|
} else if (verticalAlignment == SwingUtilities.CENTER) {
|
|
lr.textRect.y = (int)(viewRect.y
|
|
+ (float)viewRect.height/2
|
|
- (float)lr.textRect.height/2);
|
|
lr.iconRect.y = (int)(viewRect.y
|
|
+ (float)viewRect.height/2
|
|
- (float)lr.iconRect.height/2);
|
|
}
|
|
else if (verticalAlignment == SwingUtilities.BOTTOM) {
|
|
lr.textRect.y = (int)(viewRect.y
|
|
+ viewRect.height
|
|
- (float)lr.labelRect.height/2
|
|
- (float)lr.textRect.height/2);
|
|
lr.iconRect.y = (int)(viewRect.y
|
|
+ viewRect.height
|
|
- (float)lr.labelRect.height/2
|
|
- (float)lr.iconRect.height/2);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets labelRect Y coordinate
|
|
* taking into account the vertical alignment
|
|
*/
|
|
private void calcLabelYPosition(LayoutResult lr) {
|
|
if (verticalAlignment == SwingUtilities.TOP) {
|
|
lr.labelRect.y = viewRect.y;
|
|
} else if (verticalAlignment == SwingUtilities.CENTER) {
|
|
lr.labelRect.y = (int)(viewRect.y
|
|
+ (float)viewRect.height/2
|
|
- (float)lr.labelRect.height/2);
|
|
} else if (verticalAlignment == SwingUtilities.BOTTOM) {
|
|
lr.labelRect.y = viewRect.y + viewRect.height
|
|
- lr.labelRect.height;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns parent of this component if it is not a top-level menu
|
|
* Otherwise returns null.
|
|
* @param menuItem the menu item whose parent will be returned.
|
|
* @return parent of this component if it is not a top-level menu
|
|
* Otherwise returns null.
|
|
*/
|
|
public static JComponent getMenuItemParent(JMenuItem menuItem) {
|
|
Container parent = menuItem.getParent();
|
|
if ((parent instanceof JComponent) &&
|
|
(!(menuItem instanceof JMenu) ||
|
|
!((JMenu)menuItem).isTopLevelMenu())) {
|
|
return (JComponent) parent;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static void clearUsedParentClientProperties(JMenuItem menuItem) {
|
|
clearUsedClientProperties(getMenuItemParent(menuItem));
|
|
}
|
|
|
|
public static void clearUsedClientProperties(JComponent c) {
|
|
if (c != null) {
|
|
c.putClientProperty(MAX_ARROW_WIDTH, null);
|
|
c.putClientProperty(MAX_CHECK_WIDTH, null);
|
|
c.putClientProperty(MAX_ACC_WIDTH, null);
|
|
c.putClientProperty(MAX_TEXT_WIDTH, null);
|
|
c.putClientProperty(MAX_ICON_WIDTH, null);
|
|
c.putClientProperty(MAX_LABEL_WIDTH, null);
|
|
c.putClientProperty(BASICMENUITEMUI_MAX_TEXT_OFFSET, null);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Finds and returns maximal integer value in the given array.
|
|
* @param values array where the search will be performed.
|
|
* @return maximal vaule.
|
|
*/
|
|
public static int max(int... values) {
|
|
int maxValue = Integer.MIN_VALUE;
|
|
for (int i : values) {
|
|
if (i > maxValue) {
|
|
maxValue = i;
|
|
}
|
|
}
|
|
return maxValue;
|
|
}
|
|
|
|
public static Rectangle createMaxRect() {
|
|
return new Rectangle(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
|
}
|
|
|
|
public static void addMaxWidth(RectSize size, int gap, Dimension result) {
|
|
if (size.maxWidth > 0) {
|
|
result.width += size.maxWidth + gap;
|
|
}
|
|
}
|
|
|
|
public static void addWidth(int width, int gap, Dimension result) {
|
|
if (width > 0) {
|
|
result.width += width + gap;
|
|
}
|
|
}
|
|
|
|
public JMenuItem getMenuItem() {
|
|
return mi;
|
|
}
|
|
|
|
public JComponent getMenuItemParent() {
|
|
return miParent;
|
|
}
|
|
|
|
public Font getFont() {
|
|
return font;
|
|
}
|
|
|
|
public Font getAccFont() {
|
|
return accFont;
|
|
}
|
|
|
|
public FontMetrics getFontMetrics() {
|
|
return fm;
|
|
}
|
|
|
|
public FontMetrics getAccFontMetrics() {
|
|
return accFm;
|
|
}
|
|
|
|
public Icon getIcon() {
|
|
return icon;
|
|
}
|
|
|
|
public Icon getCheckIcon() {
|
|
return checkIcon;
|
|
}
|
|
|
|
public Icon getArrowIcon() {
|
|
return arrowIcon;
|
|
}
|
|
|
|
public String getText() {
|
|
return text;
|
|
}
|
|
|
|
public String getAccText() {
|
|
return accText;
|
|
}
|
|
|
|
public boolean isColumnLayout() {
|
|
return isColumnLayout;
|
|
}
|
|
|
|
public boolean useCheckAndArrow() {
|
|
return useCheckAndArrow;
|
|
}
|
|
|
|
public boolean isLeftToRight() {
|
|
return isLeftToRight;
|
|
}
|
|
|
|
public boolean isTopLevelMenu() {
|
|
return isTopLevelMenu;
|
|
}
|
|
|
|
public View getHtmlView() {
|
|
return htmlView;
|
|
}
|
|
|
|
public int getVerticalAlignment() {
|
|
return verticalAlignment;
|
|
}
|
|
|
|
public int getHorizontalAlignment() {
|
|
return horizontalAlignment;
|
|
}
|
|
|
|
public int getVerticalTextPosition() {
|
|
return verticalTextPosition;
|
|
}
|
|
|
|
public int getHorizontalTextPosition() {
|
|
return horizontalTextPosition;
|
|
}
|
|
|
|
public int getGap() {
|
|
return gap;
|
|
}
|
|
|
|
public int getLeadingGap() {
|
|
return leadingGap;
|
|
}
|
|
|
|
public int getAfterCheckIconGap() {
|
|
return afterCheckIconGap;
|
|
}
|
|
|
|
public int getMinTextOffset() {
|
|
return minTextOffset;
|
|
}
|
|
|
|
public Rectangle getViewRect() {
|
|
return viewRect;
|
|
}
|
|
|
|
public RectSize getIconSize() {
|
|
return iconSize;
|
|
}
|
|
|
|
public RectSize getTextSize() {
|
|
return textSize;
|
|
}
|
|
|
|
public RectSize getAccSize() {
|
|
return accSize;
|
|
}
|
|
|
|
public RectSize getCheckSize() {
|
|
return checkSize;
|
|
}
|
|
|
|
public RectSize getArrowSize() {
|
|
return arrowSize;
|
|
}
|
|
|
|
public RectSize getLabelSize() {
|
|
return labelSize;
|
|
}
|
|
|
|
protected void setMenuItem(JMenuItem mi) {
|
|
this.mi = mi;
|
|
}
|
|
|
|
protected void setMenuItemParent(JComponent miParent) {
|
|
this.miParent = miParent;
|
|
}
|
|
|
|
protected void setFont(Font font) {
|
|
this.font = font;
|
|
}
|
|
|
|
protected void setAccFont(Font accFont) {
|
|
this.accFont = accFont;
|
|
}
|
|
|
|
protected void setFontMetrics(FontMetrics fm) {
|
|
this.fm = fm;
|
|
}
|
|
|
|
protected void setAccFontMetrics(FontMetrics accFm) {
|
|
this.accFm = accFm;
|
|
}
|
|
|
|
protected void setIcon(Icon icon) {
|
|
this.icon = icon;
|
|
}
|
|
|
|
protected void setCheckIcon(Icon checkIcon) {
|
|
this.checkIcon = checkIcon;
|
|
}
|
|
|
|
protected void setArrowIcon(Icon arrowIcon) {
|
|
this.arrowIcon = arrowIcon;
|
|
}
|
|
|
|
protected void setText(String text) {
|
|
this.text = text;
|
|
}
|
|
|
|
protected void setAccText(String accText) {
|
|
this.accText = accText;
|
|
}
|
|
|
|
protected void setColumnLayout(boolean columnLayout) {
|
|
isColumnLayout = columnLayout;
|
|
}
|
|
|
|
protected void setUseCheckAndArrow(boolean useCheckAndArrow) {
|
|
this.useCheckAndArrow = useCheckAndArrow;
|
|
}
|
|
|
|
protected void setLeftToRight(boolean leftToRight) {
|
|
isLeftToRight = leftToRight;
|
|
}
|
|
|
|
protected void setTopLevelMenu(boolean topLevelMenu) {
|
|
isTopLevelMenu = topLevelMenu;
|
|
}
|
|
|
|
protected void setHtmlView(View htmlView) {
|
|
this.htmlView = htmlView;
|
|
}
|
|
|
|
protected void setVerticalAlignment(int verticalAlignment) {
|
|
this.verticalAlignment = verticalAlignment;
|
|
}
|
|
|
|
protected void setHorizontalAlignment(int horizontalAlignment) {
|
|
this.horizontalAlignment = horizontalAlignment;
|
|
}
|
|
|
|
protected void setVerticalTextPosition(int verticalTextPosition) {
|
|
this.verticalTextPosition = verticalTextPosition;
|
|
}
|
|
|
|
protected void setHorizontalTextPosition(int horizontalTextPosition) {
|
|
this.horizontalTextPosition = horizontalTextPosition;
|
|
}
|
|
|
|
protected void setGap(int gap) {
|
|
this.gap = gap;
|
|
}
|
|
|
|
protected void setLeadingGap(int leadingGap) {
|
|
this.leadingGap = leadingGap;
|
|
}
|
|
|
|
protected void setAfterCheckIconGap(int afterCheckIconGap) {
|
|
this.afterCheckIconGap = afterCheckIconGap;
|
|
}
|
|
|
|
protected void setMinTextOffset(int minTextOffset) {
|
|
this.minTextOffset = minTextOffset;
|
|
}
|
|
|
|
protected void setViewRect(Rectangle viewRect) {
|
|
this.viewRect = viewRect;
|
|
}
|
|
|
|
protected void setIconSize(RectSize iconSize) {
|
|
this.iconSize = iconSize;
|
|
}
|
|
|
|
protected void setTextSize(RectSize textSize) {
|
|
this.textSize = textSize;
|
|
}
|
|
|
|
protected void setAccSize(RectSize accSize) {
|
|
this.accSize = accSize;
|
|
}
|
|
|
|
protected void setCheckSize(RectSize checkSize) {
|
|
this.checkSize = checkSize;
|
|
}
|
|
|
|
protected void setArrowSize(RectSize arrowSize) {
|
|
this.arrowSize = arrowSize;
|
|
}
|
|
|
|
protected void setLabelSize(RectSize labelSize) {
|
|
this.labelSize = labelSize;
|
|
}
|
|
|
|
public int getLeftTextExtraWidth() {
|
|
return leftTextExtraWidth;
|
|
}
|
|
|
|
/**
|
|
* Returns false if the component is a JMenu and it is a top
|
|
* level menu (on the menubar).
|
|
*/
|
|
public static boolean useCheckAndArrow(JMenuItem menuItem) {
|
|
boolean b = true;
|
|
if ((menuItem instanceof JMenu) &&
|
|
(((JMenu) menuItem).isTopLevelMenu())) {
|
|
b = false;
|
|
}
|
|
return b;
|
|
}
|
|
|
|
public static class LayoutResult {
|
|
private Rectangle iconRect;
|
|
private Rectangle textRect;
|
|
private Rectangle accRect;
|
|
private Rectangle checkRect;
|
|
private Rectangle arrowRect;
|
|
private Rectangle labelRect;
|
|
|
|
public LayoutResult() {
|
|
iconRect = new Rectangle();
|
|
textRect = new Rectangle();
|
|
accRect = new Rectangle();
|
|
checkRect = new Rectangle();
|
|
arrowRect = new Rectangle();
|
|
labelRect = new Rectangle();
|
|
}
|
|
|
|
public LayoutResult(Rectangle iconRect, Rectangle textRect,
|
|
Rectangle accRect, Rectangle checkRect,
|
|
Rectangle arrowRect, Rectangle labelRect) {
|
|
this.iconRect = iconRect;
|
|
this.textRect = textRect;
|
|
this.accRect = accRect;
|
|
this.checkRect = checkRect;
|
|
this.arrowRect = arrowRect;
|
|
this.labelRect = labelRect;
|
|
}
|
|
|
|
public Rectangle getIconRect() {
|
|
return iconRect;
|
|
}
|
|
|
|
public void setIconRect(Rectangle iconRect) {
|
|
this.iconRect = iconRect;
|
|
}
|
|
|
|
public Rectangle getTextRect() {
|
|
return textRect;
|
|
}
|
|
|
|
public void setTextRect(Rectangle textRect) {
|
|
this.textRect = textRect;
|
|
}
|
|
|
|
public Rectangle getAccRect() {
|
|
return accRect;
|
|
}
|
|
|
|
public void setAccRect(Rectangle accRect) {
|
|
this.accRect = accRect;
|
|
}
|
|
|
|
public Rectangle getCheckRect() {
|
|
return checkRect;
|
|
}
|
|
|
|
public void setCheckRect(Rectangle checkRect) {
|
|
this.checkRect = checkRect;
|
|
}
|
|
|
|
public Rectangle getArrowRect() {
|
|
return arrowRect;
|
|
}
|
|
|
|
public void setArrowRect(Rectangle arrowRect) {
|
|
this.arrowRect = arrowRect;
|
|
}
|
|
|
|
public Rectangle getLabelRect() {
|
|
return labelRect;
|
|
}
|
|
|
|
public void setLabelRect(Rectangle labelRect) {
|
|
this.labelRect = labelRect;
|
|
}
|
|
|
|
public Map<String, Rectangle> getAllRects() {
|
|
Map<String, Rectangle> result = new HashMap<String, Rectangle>();
|
|
result.put("checkRect", checkRect);
|
|
result.put("iconRect", iconRect);
|
|
result.put("textRect", textRect);
|
|
result.put("accRect", accRect);
|
|
result.put("arrowRect", arrowRect);
|
|
result.put("labelRect", labelRect);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public static class ColumnAlignment {
|
|
private int checkAlignment;
|
|
private int iconAlignment;
|
|
private int textAlignment;
|
|
private int accAlignment;
|
|
private int arrowAlignment;
|
|
|
|
public static final ColumnAlignment LEFT_ALIGNMENT =
|
|
new ColumnAlignment(
|
|
SwingConstants.LEFT,
|
|
SwingConstants.LEFT,
|
|
SwingConstants.LEFT,
|
|
SwingConstants.LEFT,
|
|
SwingConstants.LEFT
|
|
);
|
|
|
|
public static final ColumnAlignment RIGHT_ALIGNMENT =
|
|
new ColumnAlignment(
|
|
SwingConstants.RIGHT,
|
|
SwingConstants.RIGHT,
|
|
SwingConstants.RIGHT,
|
|
SwingConstants.RIGHT,
|
|
SwingConstants.RIGHT
|
|
);
|
|
|
|
public ColumnAlignment(int checkAlignment, int iconAlignment,
|
|
int textAlignment, int accAlignment,
|
|
int arrowAlignment) {
|
|
this.checkAlignment = checkAlignment;
|
|
this.iconAlignment = iconAlignment;
|
|
this.textAlignment = textAlignment;
|
|
this.accAlignment = accAlignment;
|
|
this.arrowAlignment = arrowAlignment;
|
|
}
|
|
|
|
public int getCheckAlignment() {
|
|
return checkAlignment;
|
|
}
|
|
|
|
public int getIconAlignment() {
|
|
return iconAlignment;
|
|
}
|
|
|
|
public int getTextAlignment() {
|
|
return textAlignment;
|
|
}
|
|
|
|
public int getAccAlignment() {
|
|
return accAlignment;
|
|
}
|
|
|
|
public int getArrowAlignment() {
|
|
return arrowAlignment;
|
|
}
|
|
}
|
|
|
|
public static class RectSize {
|
|
private int width;
|
|
private int height;
|
|
private int origWidth;
|
|
private int maxWidth;
|
|
|
|
public RectSize() {
|
|
}
|
|
|
|
public RectSize(int width, int height, int origWidth, int maxWidth) {
|
|
this.width = width;
|
|
this.height = height;
|
|
this.origWidth = origWidth;
|
|
this.maxWidth = maxWidth;
|
|
}
|
|
|
|
public int getWidth() {
|
|
return width;
|
|
}
|
|
|
|
public int getHeight() {
|
|
return height;
|
|
}
|
|
|
|
public int getOrigWidth() {
|
|
return origWidth;
|
|
}
|
|
|
|
public int getMaxWidth() {
|
|
return maxWidth;
|
|
}
|
|
|
|
public void setWidth(int width) {
|
|
this.width = width;
|
|
}
|
|
|
|
public void setHeight(int height) {
|
|
this.height = height;
|
|
}
|
|
|
|
public void setOrigWidth(int origWidth) {
|
|
this.origWidth = origWidth;
|
|
}
|
|
|
|
public void setMaxWidth(int maxWidth) {
|
|
this.maxWidth = maxWidth;
|
|
}
|
|
|
|
public String toString() {
|
|
return "[w=" + width + ",h=" + height + ",ow="
|
|
+ origWidth + ",mw=" + maxWidth + "]";
|
|
}
|
|
}
|
|
}
|