001 /*
002 * Copyright 2002 - 2007 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: Menclose.java 310 2007-05-18 20:26:36Z maxberger $ */
018
019 package net.sourceforge.jeuclid.elements.presentation.general;
020
021 import java.awt.BasicStroke;
022 import java.awt.Graphics2D;
023 import java.awt.Stroke;
024 import java.awt.geom.Line2D;
025 import java.lang.reflect.Constructor;
026 import java.lang.reflect.InvocationTargetException;
027 import java.util.HashMap;
028 import java.util.List;
029 import java.util.Locale;
030 import java.util.Map;
031 import java.util.Stack;
032 import java.util.Vector;
033
034 import net.sourceforge.jeuclid.MathBase;
035 import net.sourceforge.jeuclid.elements.AbstractElementWithDelegates;
036 import net.sourceforge.jeuclid.elements.JEuclidElement;
037 import net.sourceforge.jeuclid.elements.presentation.token.Mspace;
038 import net.sourceforge.jeuclid.elements.support.ElementListSupport;
039 import net.sourceforge.jeuclid.elements.support.GraphicsSupport;
040
041 import org.apache.commons.logging.Log;
042 import org.apache.commons.logging.LogFactory;
043 import org.w3c.dom.mathml.MathMLEncloseElement;
044
045 /**
046 * Class for supporting "menclose" elements.
047 *
048 * @author Max Berger
049 * @version $Revision: 310 $
050 */
051 public class Menclose extends AbstractElementWithDelegates implements
052 MathMLEncloseElement {
053
054 /**
055 * Char for rendering left part of the long division.
056 */
057 public static final char LONGDIV_CHAR = ')';
058
059 /**
060 * Represents the US long-division notation, to support the notation
061 * "longdiv".
062 *
063 * @author Max Berger
064 */
065 public static class Longdiv extends AbstractRoot {
066 /**
067 * Default constructor.
068 *
069 * @param base
070 * MathBase to use.
071 */
072 public Longdiv(final MathBase base) {
073 super(base, Menclose.LONGDIV_CHAR);
074 }
075
076 /** {@inheritDoc} */
077 @Override
078 protected JEuclidElement getActualIndex() {
079 return new Mspace(this.getMathBase());
080 }
081
082 /** {@inheritDoc} */
083 @Override
084 protected List<JEuclidElement> getContent() {
085 return ElementListSupport.createListOfChildren(this);
086 }
087
088 /** {@inheritDoc} */
089 public String getTagName() {
090 return "";
091 }
092
093 }
094
095 /**
096 * base class for all row-like notations.
097 *
098 * @author Max Berger
099 */
100 public abstract static class AbstractRowLikeNotation extends
101 AbstractRowLike {
102
103 /**
104 * Default constructor.
105 *
106 * @param base
107 * MathBase to use.
108 */
109 public AbstractRowLikeNotation(final MathBase base) {
110 super(base);
111 }
112
113 /** {@inheritDoc} */
114 public String getTagName() {
115 return "";
116 }
117 }
118
119 /**
120 * base class for all row-like notations.
121 *
122 * @author Max Berger
123 */
124 public static class Updiagonalstrike extends
125 Menclose.AbstractRowLikeNotation {
126
127 /**
128 * Default constructor.
129 *
130 * @param base
131 * MathBase to use.
132 */
133 public Updiagonalstrike(final MathBase base) {
134 super(base);
135 }
136
137 /** {@inheritDoc} */
138 @Override
139 public void paint(final Graphics2D g, final float posX,
140 final float posY) {
141 super.paint(g, posX, posY);
142 final Stroke oldStroke = g.getStroke();
143 g.setStroke(new BasicStroke(GraphicsSupport.lineWidth(this)));
144 g.draw(new Line2D.Float(posX, posY, posX + this.getWidth(g), posY
145 - this.getHeight(g)));
146 g.setStroke(oldStroke);
147 }
148 }
149
150 /**
151 * base class for all row-like notations.
152 *
153 * @author Max Berger
154 */
155 public static class Downdiagonalstrike extends
156 Menclose.AbstractRowLikeNotation {
157
158 /**
159 * Default constructor.
160 *
161 * @param base
162 * MathBase to use.
163 */
164 public Downdiagonalstrike(final MathBase base) {
165 super(base);
166 }
167
168 /** {@inheritDoc} */
169 @Override
170 public void paint(final Graphics2D g, final float posX,
171 final float posY) {
172 super.paint(g, posX, posY);
173 final Stroke oldStroke = g.getStroke();
174 g.setStroke(new BasicStroke(GraphicsSupport.lineWidth(this)));
175 g.draw(new Line2D.Float(posX, posY - this.getHeight(g), posX
176 + this.getWidth(g), posY));
177 g.setStroke(oldStroke);
178 }
179 }
180
181 /**
182 * The XML element from this class.
183 */
184 public static final String ELEMENT = "menclose";
185
186 /** The notation attribute. */
187 public static final String ATTR_NOTATION = "notation";
188
189 /**
190 * Logger for this class
191 */
192 private static final Log LOGGER = LogFactory.getLog(Menclose.class);
193
194 private static final Map<String, Constructor<?>> IMPL_CLASSES = new HashMap<String, Constructor<?>>();;
195
196 /**
197 * Creates a math element.
198 *
199 * @param base
200 * The base for the math element tree.
201 */
202 public Menclose(final MathBase base) {
203 super(base);
204 this.setDefaultMathAttribute(Menclose.ATTR_NOTATION, "");
205 }
206
207 /**
208 * @return notation of menclose element
209 */
210 public String getNotation() {
211 return this.getMathAttribute(Menclose.ATTR_NOTATION);
212 }
213
214 /**
215 * Sets notation for menclose element.
216 *
217 * @param notation
218 * Notation
219 */
220 public void setNotation(final String notation) {
221 this.setAttribute(Menclose.ATTR_NOTATION, notation);
222 }
223
224 /** {@inheritDoc} */
225 public String getTagName() {
226 return Menclose.ELEMENT;
227 }
228
229 /** {@inheritDoc} */
230 @Override
231 protected List<JEuclidElement> createDelegates() {
232 final String[] notations = this.getNotation().split(" ");
233 final Stack<Constructor<?>> notationImpls = new Stack<Constructor<?>>();
234 for (final String curNotation : notations) {
235 final Constructor<?> con = Menclose.IMPL_CLASSES.get(curNotation
236 .toLowerCase(Locale.ENGLISH));
237 if (con != null) {
238 notationImpls.push(con);
239 } else if (curNotation.length() > 0) {
240 Menclose.LOGGER.info("Unsupported notation for menclose: "
241 + curNotation);
242 }
243 }
244 // This is just to make sure that there is at least one delegate, and
245 // that each of the standard delegates has exactly one child.
246 JEuclidElement lastChild;
247 if (this.getMathElementCount() != 1) {
248 lastChild = new Mrow(this.getMathBase());
249 for (final JEuclidElement child : ElementListSupport
250 .createListOfChildren(this)) {
251 lastChild.appendChild(child);
252 }
253 } else {
254 lastChild = this.getMathElement(0);
255 }
256 while (!notationImpls.isEmpty()) {
257 final Constructor<?> con = notationImpls.pop();
258 try {
259 final JEuclidElement element = (JEuclidElement) con
260 .newInstance(this.getMathBase());
261 element.appendChild(lastChild);
262 lastChild = element;
263 } catch (final InstantiationException e) {
264 Menclose.LOGGER.warn(e);
265 } catch (final IllegalAccessException e) {
266 Menclose.LOGGER.warn(e);
267 } catch (final InvocationTargetException e) {
268 Menclose.LOGGER.warn(e);
269 }
270 }
271 final List<JEuclidElement> delegates = new Vector<JEuclidElement>(1);
272 delegates.add(lastChild);
273 return delegates;
274 }
275
276 static {
277 try {
278 Menclose.IMPL_CLASSES.put("radical", Msqrt.class
279 .getConstructor(MathBase.class));
280 Menclose.IMPL_CLASSES.put("longdiv", Menclose.Longdiv.class
281 .getConstructor(MathBase.class));
282 Menclose.IMPL_CLASSES.put("updiagonalstrike",
283 Menclose.Updiagonalstrike.class
284 .getConstructor(MathBase.class));
285 Menclose.IMPL_CLASSES.put("downdiagonalstrike",
286 Menclose.Downdiagonalstrike.class
287 .getConstructor(MathBase.class));
288 } catch (NoSuchMethodException e) {
289 Menclose.LOGGER.fatal(e);
290 }
291 }
292 }