Logo Search packages:      
Sourcecode: jeuclid version File versions

Mfrac.java

/*
 * Copyright 2002 - 2007 JEuclid, http://jeuclid.sf.net
 * 
 * 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: Mfrac.java 811 2008-06-26 07:26:41Z maxberger $ */

package net.sourceforge.jeuclid.elements.presentation.general;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Dimension2D;

import net.sourceforge.jeuclid.LayoutContext;
import net.sourceforge.jeuclid.context.InlineLayoutContext;
import net.sourceforge.jeuclid.context.Parameter;
import net.sourceforge.jeuclid.elements.AbstractJEuclidElement;
import net.sourceforge.jeuclid.elements.support.Dimension2DImpl;
import net.sourceforge.jeuclid.elements.support.ElementListSupport;
import net.sourceforge.jeuclid.elements.support.GraphicsSupport;
import net.sourceforge.jeuclid.elements.support.attributes.AttributesHelper;
import net.sourceforge.jeuclid.elements.support.attributes.HAlign;
import net.sourceforge.jeuclid.layout.GraphicsObject;
import net.sourceforge.jeuclid.layout.LayoutInfo;
import net.sourceforge.jeuclid.layout.LayoutStage;
import net.sourceforge.jeuclid.layout.LayoutView;
import net.sourceforge.jeuclid.layout.LayoutableNode;
import net.sourceforge.jeuclid.layout.LineObject;

import org.w3c.dom.Node;
import org.w3c.dom.mathml.MathMLElement;
import org.w3c.dom.mathml.MathMLFractionElement;

/**
 * This math element presents a mathematical fraction.
 * 
 * @version $Revision: 811 $
 */
00050 public final class Mfrac extends AbstractJEuclidElement implements
        MathMLFractionElement {

    /**
     * The XML element from this class.
     */
00056     public static final String ELEMENT = "mfrac";

    /**
     * Tilt angle for frac.
     */
00061     public static final float FRAC_TILT_ANGLE = 0.577f;

    /**
     * Attribute name of the linethickness property.
     */
00066     public static final String ATTR_LINETHICKNESS = "linethickness";

    /** The wrong beveled attribute. */
00069     public static final String ATTR_BEVELED_WRONG = "beveled";

    /** The real beveled attribute. */
00072     public static final String ATTR_BEVELLED = "bevelled";

    /** The numalign attribute. */
00075     public static final String ATTR_NUMALIGN = "numalign";

    /** The denomalign attribute. */
00078     public static final String ATTR_DENOMALIGN = "denomalign";

    private static final String EXTRA_SPACE_AROUND = "0.1em";

    private static final long serialVersionUID = 1L;

    /**
     * Lines thinner than this are ignored.
     */
00087     private static final float NOLINE_THRESHHOLD = 0.001f;

    /**
     * Creates a math element.
     */
00092     public Mfrac() {
        super();
        this.setDefaultMathAttribute(Mfrac.ATTR_LINETHICKNESS, "1");
        this.setDefaultMathAttribute(Mfrac.ATTR_BEVELLED, Boolean.FALSE
                .toString());
        this
                .setDefaultMathAttribute(Mfrac.ATTR_NUMALIGN,
                        HAlign.ALIGN_CENTER);
        this.setDefaultMathAttribute(Mfrac.ATTR_DENOMALIGN,
                HAlign.ALIGN_CENTER);
    }

    /** {@inheritDoc} */
    @Override
00106     protected Node newNode() {
        return new Mfrac();
    }

    /** {@inheritDoc} */
    @Override
00112     public LayoutContext getChildLayoutContext(final int childNum,
            final LayoutContext context) {
        return new InlineLayoutContext(this
                .applyLocalAttributesToContext(context), !((Boolean) context
                .getParameter(Parameter.MFRAC_KEEP_SCRIPTLEVEL))
                .booleanValue());
    }

    /**
     * Sets the thickness of the fraction line.
     * 
     * @param newLinethickness
     *            Thickness
     */
00126     public void setLinethickness(final String newLinethickness) {
        this.setAttribute(Mfrac.ATTR_LINETHICKNESS, newLinethickness);
    }

    /**
     * @return thickness of the fraction line
     * @param context
     *            LayoutContext to use
     * @param g
     *            Graphics2D context to use.
     */
00137     public float getLinethickness(final Graphics2D g,
            final LayoutContext context) {
        final String sThickness = this.getLinethickness();
        float thickness;
        try {
            thickness = Float.parseFloat(sThickness);
            thickness *= GraphicsSupport.lineWidth(context);
        } catch (final NumberFormatException nfe) {
            thickness = AttributesHelper.convertSizeToPt(sThickness, this
                    .applyLocalAttributesToContext(context),
                    AttributesHelper.PT);
            if ((thickness < GraphicsSupport.MIN_LINEWIDTH)
                    && (thickness >= Mfrac.NOLINE_THRESHHOLD)) {
                thickness = GraphicsSupport.MIN_LINEWIDTH;
            }
        }
        return thickness;
    }

    /**
     * Set value of the beveled attribute.
     * 
     * @param bevelled
     *            Value
     */
00162     public void setBevelled(final String bevelled) {
        this.setAttribute(Mfrac.ATTR_BEVELLED, bevelled);
    }

    /**
     * @return Value of beveled attribute
     */
00169     public String getBevelled() {
        final String wrongAttr = this.getMathAttribute(
                Mfrac.ATTR_BEVELED_WRONG, false);
        if (wrongAttr == null) {
            return this.getMathAttribute(Mfrac.ATTR_BEVELLED);
        } else {
            return wrongAttr;
        }
    }

    /** {@inheritDoc} */
00180     public MathMLElement getDenominator() {
        return this.getMathElement(1);
    }

    /** {@inheritDoc} */
00185     public String getLinethickness() {
        return this.getMathAttribute(Mfrac.ATTR_LINETHICKNESS);
    }

    /** {@inheritDoc} */
00190     public MathMLElement getNumerator() {
        return this.getMathElement(0);
    }

    /** {@inheritDoc} */
00195     public void setDenominator(final MathMLElement denominator) {
        this.setMathElement(1, denominator);
    }

    /** {@inheritDoc} */
00200     public void setNumerator(final MathMLElement numerator) {
        this.setMathElement(0, numerator);
    }

    /** {@inheritDoc} */
00205     public String getDenomalign() {
        return this.getMathAttribute(Mfrac.ATTR_DENOMALIGN);
    }

    /** {@inheritDoc} */
00210     public String getNumalign() {
        return this.getMathAttribute(Mfrac.ATTR_NUMALIGN);
    }

    /** {@inheritDoc} */
00215     public void setDenomalign(final String denomalign) {
        this.setAttribute(Mfrac.ATTR_DENOMALIGN, denomalign);
    }

    /** {@inheritDoc} */
00220     public void setNumalign(final String numalign) {
        this.setAttribute(Mfrac.ATTR_NUMALIGN, numalign);
    }

    /** {@inheritDoc} */
    @Override
00226     protected void layoutStageInvariant(final LayoutView view,
            final LayoutInfo info, final LayoutStage stage,
            final LayoutContext context) {
        final Graphics2D g = view.getGraphics();

        final float middleShift = this.getMiddleShift(g, context);
        final boolean beveled = Boolean.parseBoolean(this.getBevelled());
        final float linethickness = this.getLinethickness(g, context);
        final float extraSpace = AttributesHelper.convertSizeToPt(
                Mfrac.EXTRA_SPACE_AROUND, this
                        .applyLocalAttributesToContext(context), "");

        final LayoutInfo numerator = view.getInfo((LayoutableNode) this
                .getNumerator());
        final LayoutInfo denominator = view.getInfo((LayoutableNode) this
                .getDenominator());

        if (beveled) {
            this.layoutBeveled(info, stage, middleShift, linethickness,
                    extraSpace, numerator, denominator, context);
        } else {
            this.layoutStacked(info, stage, middleShift, linethickness,
                    extraSpace, numerator, denominator, context);
        }

        final Dimension2D borderLeftTop = new Dimension2DImpl(extraSpace
                + linethickness, 0.0f);
        final Dimension2D borderRightBottom = new Dimension2DImpl(extraSpace
                + linethickness, 0.0f);
        ElementListSupport.fillInfoFromChildren(view, info, this, stage,
                borderLeftTop, borderRightBottom);
    }

    // CHECKSTYLE:OFF
    // More than 7 parameters - but only used here, so this is ok.
    private void layoutStacked(final LayoutInfo info,
            final LayoutStage stage, final float middleShift,
            final float linethickness, final float extraSpace,
            final LayoutInfo numerator, final LayoutInfo denominator,
            final LayoutContext context) {
        // CHECKSTLYE:ON
        final float numWidth = numerator.getWidth(stage);
        final float denumWidth = denominator.getWidth(stage);
        final float width = Math.max(denumWidth, numWidth);

        final float numOffset = HAlign.parseString(this.getNumalign(),
                HAlign.CENTER).getHAlignOffset(stage, numerator, width);
        final float denumOffset = HAlign.parseString(this.getDenomalign(),
                HAlign.CENTER).getHAlignOffset(stage, denominator, width);

        numerator.moveTo(numOffset + extraSpace, -(middleShift
                + linethickness / 2.0f + extraSpace + numerator
                .getDescentHeight(stage)), stage);

        denominator.moveTo(denumOffset + extraSpace, -middleShift
                + linethickness / 2.0f + extraSpace
                + denominator.getAscentHeight(stage), stage);

        if (linethickness > Mfrac.NOLINE_THRESHHOLD) {
            final GraphicsObject line = new LineObject(extraSpace,
                    -middleShift, extraSpace + width, -middleShift,
                    linethickness, (Color) this
                            .applyLocalAttributesToContext(context)
                            .getParameter(Parameter.MATHCOLOR));
            info.setGraphicsObject(line);
        }
    }

    // CHECKSTYLE:OFF
    // More than 7 parameters - but only used here, so this is ok.
    private void layoutBeveled(final LayoutInfo info,
            final LayoutStage stage, final float middleShift,
            final float linethickness, final float extraSpace,
            final LayoutInfo numerator, final LayoutInfo denominator,
            final LayoutContext context) {
        // CHECKSTYLE:ON
        final float numPosY = -middleShift / 2.0f
                + numerator.getDescentHeight(stage);
        final float denPosY = middleShift / 2.0f
                + denominator.getDescentHeight(stage);

        final float totalAscent = Math.max(-numPosY
                + numerator.getAscentHeight(stage), -denPosY
                + denominator.getAscentHeight(stage));
        final float totalDescent = Math.max(numPosY
                + numerator.getDescentHeight(stage), denPosY
                + denominator.getDescentHeight(stage));

        final float totalHeight = totalAscent + totalDescent;
        final float lineWidth = totalHeight * Mfrac.FRAC_TILT_ANGLE;

        numerator.moveTo(extraSpace, numPosY, stage);
        float posX = numerator.getWidth(stage) + extraSpace;
        if (linethickness > Mfrac.NOLINE_THRESHHOLD) {
            final GraphicsObject line = new LineObject(posX, totalDescent,
                    lineWidth + posX, totalDescent - totalHeight,
                    linethickness, (Color) this
                            .applyLocalAttributesToContext(context)
                            .getParameter(Parameter.MATHCOLOR));
            info.setGraphicsObject(line);
        }
        posX += lineWidth;
        denominator.moveTo(posX, denPosY, stage);
    }
}

Generated by  Doxygen 1.6.0   Back to index