001    /*
002     * Copyright 2007 - 2009 JEuclid, http://jeuclid.sf.net
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    /* $Id: AbstractTokenWithTextLayout.java,v 923658a2b249 2009/09/11 09:57:31 max $ */
018    
019    package net.sourceforge.jeuclid.elements.presentation.token;
020    
021    import java.awt.Color;
022    import java.awt.Graphics2D;
023    import java.awt.font.TextLayout;
024    import java.text.AttributedCharacterIterator;
025    import java.text.AttributedString;
026    import java.util.Collections;
027    import java.util.List;
028    
029    import net.sourceforge.jeuclid.LayoutContext;
030    import net.sourceforge.jeuclid.context.Parameter;
031    import net.sourceforge.jeuclid.elements.AbstractJEuclidElement;
032    import net.sourceforge.jeuclid.elements.support.text.StringUtil;
033    import net.sourceforge.jeuclid.layout.LayoutInfo;
034    import net.sourceforge.jeuclid.layout.LayoutStage;
035    import net.sourceforge.jeuclid.layout.LayoutView;
036    import net.sourceforge.jeuclid.layout.LayoutableNode;
037    import net.sourceforge.jeuclid.layout.TextObject;
038    
039    import org.apache.batik.dom.AbstractDocument;
040    import org.w3c.dom.mathml.MathMLPresentationToken;
041    
042    /**
043     * Common functionality for all tokens based on a text layout.
044     * 
045     * @version $Revision: 923658a2b249 $
046     */
047    public abstract class AbstractTokenWithTextLayout extends
048            AbstractJEuclidElement implements MathMLPresentationToken {
049    
050        private static final long serialVersionUID = 1L;
051    
052        /**
053         * Default constructor. Sets MathML Namespace.
054         * 
055         * @param qname
056         *            Qualified name.
057         * @param odoc
058         *            Owner Document.
059         */
060        public AbstractTokenWithTextLayout(final String qname,
061                final AbstractDocument odoc) {
062            super(qname, odoc);
063        }
064    
065        /** {@inheritDoc} */
066        @Override
067        public void layoutStageInvariant(final LayoutView view,
068                final LayoutInfo info, final LayoutStage stage,
069                final LayoutContext context) {
070            final Graphics2D g = view.getGraphics();
071            final TextLayout t = this.produceTextLayout(g, context);
072            if (t != null) {
073                final StringUtil.TextLayoutInfo tli = StringUtil.getTextLayoutInfo(
074                        t, false);
075                info.setAscentHeight(tli.getAscent(), stage);
076                info.setDescentHeight(tli.getDescent(), stage);
077                final float width = tli.getWidth();
078                info.setHorizontalCenterOffset(width / 2.0f, stage);
079                info.setWidth(width, stage);
080                info.setGraphicsObject(new TextObject(t, tli.getOffset(),
081                        (Color) this.applyLocalAttributesToContext(context)
082                                .getParameter(Parameter.MATHCOLOR)));
083            }
084        }
085    
086        private TextLayout produceTextLayout(final Graphics2D g2d,
087                final LayoutContext context) {
088            TextLayout layout;
089            final LayoutContext now = this.applyLocalAttributesToContext(context);
090    
091            final AttributedCharacterIterator aci = StringUtil
092                    .textContentAsAttributedCharacterIterator(now, this, this, 1.0f);
093    
094            if (aci.getBeginIndex() == aci.getEndIndex()) {
095                return null;
096            } else {
097                layout = StringUtil.createTextLayoutFromAttributedString(g2d,
098                        new AttributedString(aci), now);
099                return layout;
100            }
101        }
102    
103        /** {@inheritDoc} */
104        @Override
105        public List<LayoutableNode> getChildrenToLayout() {
106            return Collections.emptyList();
107        }
108    
109        /** {@inheritDoc} */
110        @Override
111        public List<LayoutableNode> getChildrenToDraw() {
112            return Collections.emptyList();
113        }
114    
115    }