308 lines · 11.6 KB · Java
RawDownload
/* * 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());    }}