/*
 * Copyright (c) 2009 Kathryn Huxtable and Kenneth Orr.
 *
 * This file is part of the SeaGlass Pluggable Look and Feel.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * $Id: org.eclipse.jdt.ui.prefs 172 2009-10-06 18:31:12Z [email protected] $
 */
package com.seaglasslookandfeel.util;

import java.awt.Rectangle;

import javax.swing.Icon;
import javax.swing.JMenuItem;
import javax.swing.SwingConstants;
import javax.swing.plaf.synth.SynthContext;
import javax.swing.plaf.synth.SynthGraphicsUtils;
import javax.swing.plaf.synth.SynthStyle;
import javax.swing.text.View;

import sun.swing.MenuItemLayoutHelper;
import sun.swing.StringUIClientPropertyKey;
import sun.swing.MenuItemLayoutHelper.ColumnAlignment;
import sun.swing.MenuItemLayoutHelper.LayoutResult;
import sun.swing.plaf.synth.SynthIcon;

/**
 * @author Kathryn Huxtable
 *
 */
public class SeaGlassMenuItemLayoutHelper 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 SeaGlassMenuItemLayoutHelper(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());
    }

}