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.util.ArrayList;
22 import java.util.List;
23
24 import net.sourceforge.jeuclid.Constants;
25 import net.sourceforge.jeuclid.elements.AbstractElementWithDelegates;
26 import net.sourceforge.jeuclid.elements.AbstractJEuclidElement;
27 import net.sourceforge.jeuclid.elements.presentation.token.Mo;
28 import net.sourceforge.jeuclid.elements.support.operatordict.OperatorDictionary;
29 import net.sourceforge.jeuclid.layout.LayoutableNode;
30
31 import org.apache.batik.dom.AbstractDocument;
32 import org.w3c.dom.Node;
33 import org.w3c.dom.mathml.MathMLFencedElement;
34
35
36
37
38
39
40 public final class Mfenced extends AbstractElementWithDelegates implements
41 MathMLFencedElement {
42
43
44 public static final String ATTR_SEPARATORS = "separators";
45
46
47 public static final String ATTR_CLOSE = "close";
48
49
50 public static final String ATTR_OPEN = "open";
51
52
53
54
55 public static final String ELEMENT = "mfenced";
56
57 private static final String FENCE_SPACE = "0.2em";
58
59 private static final long serialVersionUID = 1L;
60
61
62
63
64
65
66
67
68
69 public Mfenced(final String qname, final AbstractDocument odoc) {
70 super(qname, odoc);
71 this.setDefaultMathAttribute(Mfenced.ATTR_OPEN, "(");
72 this.setDefaultMathAttribute(Mfenced.ATTR_CLOSE, ")");
73 this.setDefaultMathAttribute(Mfenced.ATTR_SEPARATORS, ",");
74 }
75
76
77 @Override
78 protected Node newNode() {
79 return new Mfenced(this.nodeName, this.ownerDocument);
80 }
81
82
83
84
85 public String getOpen() {
86 return this.getMathAttribute(Mfenced.ATTR_OPEN);
87 }
88
89
90
91
92
93
94
95 public void setOpen(final String open) {
96 this.setAttribute(Mfenced.ATTR_OPEN, open);
97 }
98
99
100
101
102 public String getClose() {
103 return this.getMathAttribute(Mfenced.ATTR_CLOSE);
104 }
105
106
107
108
109
110
111
112 public void setClose(final String close) {
113 this.setAttribute(Mfenced.ATTR_CLOSE, close);
114 }
115
116
117
118
119
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
137
138
139
140
141 public void setSeparators(final String separators) {
142 this.setAttribute(Mfenced.ATTR_SEPARATORS, separators);
143 }
144
145
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 }