View Javadoc

1   /*
2    * Copyright 2007 - 2007 JEuclid, http://jeuclid.sf.net
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  /* $Id: AbstractRoot.java,v bc1d5fde7b73 2009/06/01 14:40:54 maxberger $ */
18  
19  package net.sourceforge.jeuclid.elements.presentation.general;
20  
21  import java.awt.Color;
22  import java.awt.FontMetrics;
23  import java.awt.Graphics2D;
24  import java.util.List;
25  
26  import net.sourceforge.jeuclid.LayoutContext;
27  import net.sourceforge.jeuclid.context.Parameter;
28  import net.sourceforge.jeuclid.elements.AbstractJEuclidElement;
29  import net.sourceforge.jeuclid.elements.support.GraphicsSupport;
30  import net.sourceforge.jeuclid.elements.support.attributes.AttributesHelper;
31  import net.sourceforge.jeuclid.layout.GraphicsObject;
32  import net.sourceforge.jeuclid.layout.LayoutInfo;
33  import net.sourceforge.jeuclid.layout.LayoutStage;
34  import net.sourceforge.jeuclid.layout.LayoutView;
35  import net.sourceforge.jeuclid.layout.LayoutableNode;
36  import net.sourceforge.jeuclid.layout.LineObject;
37  
38  import org.apache.batik.dom.AbstractDocument;
39  import org.w3c.dom.mathml.MathMLRadicalElement;
40  
41  /**
42   * common superclass for root like elements (root, sqrt).
43   * 
44   * @version $Revision: bc1d5fde7b73 $
45   */
46  public abstract class AbstractRoot extends AbstractJEuclidElement implements
47          MathMLRadicalElement {
48  
49      private static final String EXTRA_SPACE = "0.1ex";
50  
51      private static final String ROOT_WIDTH = "0.5em";
52  
53      /**
54       * Default constructor. Sets MathML Namespace.
55       * 
56       * @param qname
57       *            Qualified name.
58       * @param odoc
59       *            Owner Document.
60       */
61      public AbstractRoot(final String qname, final AbstractDocument odoc) {
62          super(qname, odoc);
63      }
64  
65      /**
66       * retrieve the content of this radical element.
67       * 
68       * @return A List<MathElement> with the contents for this element.
69       */
70      protected abstract List<LayoutableNode> getContent();
71  
72      /** {@inheritDoc} */
73      // CHECKSTYLE:OFF
74      // This function is too long, but it depends on too many parameters.
75      @Override
76      protected void layoutStageInvariant(final LayoutView view,
77              final LayoutInfo info, final LayoutStage stage,
78              final LayoutContext context) {
79          // CHECKSTYLE:ON
80  
81          // Basic Calculations
82          final Graphics2D g = view.getGraphics();
83          final LayoutContext now = this.applyLocalAttributesToContext(context);
84          final float middleShift = this.getMiddleShift(g, context);
85          final float linethickness = GraphicsSupport.lineWidth(now);
86          final float extraSpace = AttributesHelper.convertSizeToPt(
87                  AbstractRoot.EXTRA_SPACE, now, "");
88          final float rootwidth = AttributesHelper.convertSizeToPt(
89                  AbstractRoot.ROOT_WIDTH, context, "");
90          final Color color = (Color) now.getParameter(Parameter.MATHCOLOR);
91          float xPos = linethickness;
92          final LayoutableNode index = (LayoutableNode) this.getIndex();
93          final List<GraphicsObject> graphicObjects = info.getGraphicObjects();
94          graphicObjects.clear();
95  
96          // Draw Index
97          float indexAscent;
98          if (index == null) {
99              indexAscent = 0.0f;
100         } else {
101             final LayoutInfo indexInfo = view.getInfo(index);
102             final float indexPos = middleShift + linethickness / 2.0f
103                     + extraSpace + indexInfo.getDescentHeight(stage);
104             indexInfo.moveTo(xPos, -indexPos, stage);
105             xPos += indexInfo.getWidth(stage);
106             graphicObjects.add(new LineObject(linethickness, -middleShift,
107                     xPos, -middleShift, linethickness, color));
108             indexAscent = indexPos + indexInfo.getAscentHeight(stage);
109         }
110 
111         // Skip Root Space
112         xPos += rootwidth;
113 
114         // Draw Content below Root
115         final float contentStartX = xPos;
116         final FontMetrics metrics = this
117                 .getFontMetrics(view.getGraphics(), now);
118         float maxAscent = metrics.getAscent();
119         float maxDescent = metrics.getDescent();
120         for (final LayoutableNode child : this.getContent()) {
121             final LayoutInfo childInfo = view.getInfo(child);
122             childInfo.moveTo(xPos, 0, stage);
123             maxAscent = Math.max(maxAscent, childInfo.getAscentHeight(stage));
124             maxDescent = Math
125                     .max(maxDescent, childInfo.getDescentHeight(stage));
126             xPos += childInfo.getWidth(stage);
127         }
128         xPos += 2 * extraSpace;
129         final float topLinePos = maxAscent + 2 * extraSpace + linethickness
130                 / 2.0f;
131 
132         // Fill in Info
133         info.setAscentHeight(Math.max(topLinePos + linethickness / 2.0f,
134                 indexAscent), stage);
135         info.setDescentHeight(maxDescent + linethickness / 2.0f, stage);
136         info.setHorizontalCenterOffset(xPos / 2.0f, stage);
137         info.setWidth(xPos + linethickness, stage);
138         info.setStretchAscent(maxAscent);
139         info.setStretchDescent(maxDescent);
140 
141         // Add Root Glyph
142         graphicObjects.add(new LineObject(contentStartX - rootwidth,
143                 -middleShift, contentStartX - rootwidth / 2.0f, maxDescent,
144                 linethickness, color));
145         graphicObjects.add(new LineObject(contentStartX - rootwidth / 2.0f,
146                 maxDescent, contentStartX, -topLinePos, linethickness, color));
147         graphicObjects.add(new LineObject(contentStartX, -topLinePos, xPos,
148                 -topLinePos, linethickness, color));
149     }
150 }