1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
43
44
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
55
56
57
58
59
60
61 public AbstractRoot(final String qname, final AbstractDocument odoc) {
62 super(qname, odoc);
63 }
64
65
66
67
68
69
70 protected abstract List<LayoutableNode> getContent();
71
72
73
74
75 @Override
76 protected void layoutStageInvariant(final LayoutView view,
77 final LayoutInfo info, final LayoutStage stage,
78 final LayoutContext context) {
79
80
81
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
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
112 xPos += rootwidth;
113
114
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
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
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 }