001 /* 002 * Copyright 2002 - 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: Mfenced.java,v 34009469c57a 2009/08/07 13:21:37 max $ */ 018 019 package net.sourceforge.jeuclid.elements.presentation.general; 020 021 import java.util.ArrayList; 022 import java.util.List; 023 024 import net.sourceforge.jeuclid.Constants; 025 import net.sourceforge.jeuclid.elements.AbstractElementWithDelegates; 026 import net.sourceforge.jeuclid.elements.AbstractJEuclidElement; 027 import net.sourceforge.jeuclid.elements.presentation.token.Mo; 028 import net.sourceforge.jeuclid.elements.support.operatordict.OperatorDictionary; 029 import net.sourceforge.jeuclid.layout.LayoutableNode; 030 031 import org.apache.batik.dom.AbstractDocument; 032 import org.w3c.dom.Node; 033 import org.w3c.dom.mathml.MathMLFencedElement; 034 035 /** 036 * The class represents the mfenced element. 037 * 038 * @version $Revision: 34009469c57a $ 039 */ 040 public final class Mfenced extends AbstractElementWithDelegates implements 041 MathMLFencedElement { 042 043 /** The separators attribute. */ 044 public static final String ATTR_SEPARATORS = "separators"; 045 046 /** The close attribute. */ 047 public static final String ATTR_CLOSE = "close"; 048 049 /** The open attribute. */ 050 public static final String ATTR_OPEN = "open"; 051 052 /** 053 * The XML element from this class. 054 */ 055 public static final String ELEMENT = "mfenced"; 056 057 private static final String FENCE_SPACE = "0.2em"; 058 059 private static final long serialVersionUID = 1L; 060 061 /** 062 * Default constructor. Sets MathML Namespace. 063 * 064 * @param qname 065 * Qualified name. 066 * @param odoc 067 * Owner Document. 068 */ 069 public Mfenced(final String qname, final AbstractDocument odoc) { 070 super(qname, odoc); 071 this.setDefaultMathAttribute(Mfenced.ATTR_OPEN, "("); 072 this.setDefaultMathAttribute(Mfenced.ATTR_CLOSE, ")"); 073 this.setDefaultMathAttribute(Mfenced.ATTR_SEPARATORS, ","); 074 } 075 076 /** {@inheritDoc} */ 077 @Override 078 protected Node newNode() { 079 return new Mfenced(this.nodeName, this.ownerDocument); 080 } 081 082 /** 083 * @return opening delimiter 084 */ 085 public String getOpen() { 086 return this.getMathAttribute(Mfenced.ATTR_OPEN); 087 } 088 089 /** 090 * Set the opening delimiter. 091 * 092 * @param open 093 * Delimiter 094 */ 095 public void setOpen(final String open) { 096 this.setAttribute(Mfenced.ATTR_OPEN, open); 097 } 098 099 /** 100 * @return Return the closing delimiter 101 */ 102 public String getClose() { 103 return this.getMathAttribute(Mfenced.ATTR_CLOSE); 104 } 105 106 /** 107 * Set the closing delimiter. 108 * 109 * @param close 110 * New close delimeter 111 */ 112 public void setClose(final String close) { 113 this.setAttribute(Mfenced.ATTR_CLOSE, close); 114 } 115 116 /** 117 * Return the separators. 118 * 119 * @return separators 120 */ 121 public String getSeparators() { 122 final StringBuilder retVal = new StringBuilder(); 123 final String attValue = this.getMathAttribute(Mfenced.ATTR_SEPARATORS); 124 if (attValue != null) { 125 for (int i = 0; i < attValue.length(); i++) { 126 final char c = attValue.charAt(i); 127 if (c > AbstractJEuclidElement.TRIVIAL_SPACE_MAX) { 128 retVal.append(c); 129 } 130 } 131 } 132 return retVal.toString(); 133 } 134 135 /** 136 * Set the separators. 137 * 138 * @param separators 139 * New separators 140 */ 141 public void setSeparators(final String separators) { 142 this.setAttribute(Mfenced.ATTR_SEPARATORS, separators); 143 } 144 145 /** {@inheritDoc} */ 146 @Override 147 protected List<LayoutableNode> createDelegates() { 148 final int contentCount = this.getMathElementCount(); 149 final List<LayoutableNode> retVal = new ArrayList<LayoutableNode>( 150 2 * contentCount + 1); 151 152 final Mo opOpen = this.createFenceOperator(); 153 opOpen.setForm(OperatorDictionary.FORM_PREFIX); 154 opOpen.setTextContent(this.getOpen()); 155 156 retVal.add(opOpen); 157 final String sep = this.getSeparators(); 158 final boolean haveSep = (sep != null) && (sep.length() > 0); 159 160 for (int i = 0; i < contentCount; i++) { 161 retVal.add(this.getMathElement(i)); 162 163 if (haveSep && (i < (contentCount - 1))) { 164 final Mo opSep = (Mo) this.getOwnerDocument().createElement( 165 Mo.ELEMENT); 166 opSep.setSeparator(Constants.TRUE); 167 if (i < sep.length()) { 168 opSep.setTextContent(String.valueOf(sep.charAt(i))); 169 } else { 170 opSep.setTextContent(String.valueOf(sep 171 .charAt(sep.length() - 1))); 172 } 173 retVal.add(opSep); 174 } 175 } 176 final Mo opClose = this.createFenceOperator(); 177 opClose.setForm(OperatorDictionary.FORM_POSTFIX); 178 opClose.setTextContent(this.getClose()); 179 retVal.add(opClose); 180 181 return retVal; 182 } 183 184 private Mo createFenceOperator() { 185 final Mo opOpen = (Mo) this.getOwnerDocument() 186 .createElement(Mo.ELEMENT); 187 opOpen.setFence(Constants.TRUE); 188 opOpen.setStretchy(Constants.TRUE); 189 opOpen.setRspace(Mfenced.FENCE_SPACE); 190 opOpen.setLspace(Mfenced.FENCE_SPACE); 191 opOpen.setSymmetric(Constants.FALSE); 192 return opOpen; 193 } 194 195 }