001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.dom.svg;
020:
021: import java.util.ArrayList;
022: import java.util.Iterator;
023:
024: import org.apache.batik.anim.values.AnimatablePointListValue;
025: import org.apache.batik.anim.values.AnimatableValue;
026: import org.apache.batik.dom.anim.AnimationTarget;
027:
028: import org.apache.batik.parser.ParseException;
029:
030: import org.w3c.dom.Attr;
031: import org.w3c.dom.DOMException;
032: import org.w3c.dom.svg.SVGAnimatedPoints;
033: import org.w3c.dom.svg.SVGException;
034: import org.w3c.dom.svg.SVGPoint;
035: import org.w3c.dom.svg.SVGPointList;
036:
037: /**
038: * This class is the implementation of the SVGAnimatedPoints interface.
039: *
040: * @author <a href="mailto:nicolas.socheleau@bitflash.com">Nicolas Socheleau</a>
041: * @version $Id: SVGOMAnimatedPoints.java 490655 2006-12-28 05:19:44Z cam $
042: */
043: public class SVGOMAnimatedPoints extends AbstractSVGAnimatedValue
044: implements SVGAnimatedPoints {
045:
046: /**
047: * The base value.
048: */
049: protected BaseSVGPointList baseVal;
050:
051: /**
052: * The animated value.
053: */
054: protected AnimSVGPointList animVal;
055:
056: /**
057: * Whether the list is changing.
058: */
059: protected boolean changing;
060:
061: /**
062: * Default value for the point list.
063: */
064: protected String defaultValue;
065:
066: /**
067: * Creates a new SVGOMAnimatedPoints.
068: * @param elt The associated element.
069: * @param ns The attribute's namespace URI.
070: * @param ln The attribute's local name.
071: * @param defaultValue The default value if the attribute is not specified.
072: */
073: public SVGOMAnimatedPoints(AbstractElement elt, String ns,
074: String ln, String defaultValue) {
075: super (elt, ns, ln);
076: this .defaultValue = defaultValue;
077: }
078:
079: /**
080: * <b>DOM</b>: Implements {@link SVGAnimatedPoints#getPoints()}.
081: */
082: public SVGPointList getPoints() {
083: if (baseVal == null) {
084: baseVal = new BaseSVGPointList();
085: }
086: return baseVal;
087: }
088:
089: /**
090: * <b>DOM</b>: Implements {@link SVGAnimatedPoints#getAnimatedPoints()}.
091: */
092: public SVGPointList getAnimatedPoints() {
093: if (animVal == null) {
094: animVal = new AnimSVGPointList();
095: }
096: return animVal;
097: }
098:
099: /**
100: * Returns the base value of the attribute as an {@link AnimatableValue}.
101: */
102: public AnimatableValue getUnderlyingValue(AnimationTarget target) {
103: SVGPointList pl = getPoints();
104: int n = pl.getNumberOfItems();
105: float[] points = new float[n * 2];
106: for (int i = 0; i < n; i++) {
107: SVGPoint p = pl.getItem(i);
108: points[i * 2] = p.getX();
109: points[i * 2 + 1] = p.getY();
110: }
111: return new AnimatablePointListValue(target, points);
112: }
113:
114: /**
115: * Updates the animated value with the given {@link AnimatableValue}.
116: */
117: protected void updateAnimatedValue(AnimatableValue val) {
118: if (val == null) {
119: hasAnimVal = false;
120: } else {
121: hasAnimVal = true;
122: AnimatablePointListValue animPointList = (AnimatablePointListValue) val;
123: if (animVal == null) {
124: animVal = new AnimSVGPointList();
125: }
126: animVal.setAnimatedValue(animPointList.getNumbers());
127: }
128: fireAnimatedAttributeListeners();
129: }
130:
131: /**
132: * Called when an Attr node has been added.
133: */
134: public void attrAdded(Attr node, String newv) {
135: if (!changing && baseVal != null) {
136: baseVal.invalidate();
137: }
138: fireBaseAttributeListeners();
139: if (!hasAnimVal) {
140: fireAnimatedAttributeListeners();
141: }
142: }
143:
144: /**
145: * Called when an Attr node has been modified.
146: */
147: public void attrModified(Attr node, String oldv, String newv) {
148: if (!changing && baseVal != null) {
149: baseVal.invalidate();
150: }
151: fireBaseAttributeListeners();
152: if (!hasAnimVal) {
153: fireAnimatedAttributeListeners();
154: }
155: }
156:
157: /**
158: * Called when an Attr node has been removed.
159: */
160: public void attrRemoved(Attr node, String oldv) {
161: if (!changing && baseVal != null) {
162: baseVal.invalidate();
163: }
164: fireBaseAttributeListeners();
165: if (!hasAnimVal) {
166: fireAnimatedAttributeListeners();
167: }
168: }
169:
170: /**
171: * {@link SVGPointList} implementation for the base point list value.
172: */
173: protected class BaseSVGPointList extends AbstractSVGPointList {
174:
175: /**
176: * Create a DOMException.
177: */
178: protected DOMException createDOMException(short type,
179: String key, Object[] args) {
180: return element.createDOMException(type, key, args);
181: }
182:
183: /**
184: * Create a SVGException.
185: */
186: protected SVGException createSVGException(short type,
187: String key, Object[] args) {
188:
189: return ((SVGOMElement) element).createSVGException(type,
190: key, args);
191: }
192:
193: /**
194: * Returns the value of the DOM attribute containing the point list.
195: */
196: protected String getValueAsString() {
197: Attr attr = element.getAttributeNodeNS(namespaceURI,
198: localName);
199: if (attr == null) {
200: return defaultValue;
201: }
202: return attr.getValue();
203: }
204:
205: /**
206: * Sets the DOM attribute value containing the point list.
207: */
208: protected void setAttributeValue(String value) {
209: try {
210: changing = true;
211: element.setAttributeNS(namespaceURI, localName, value);
212: } finally {
213: changing = false;
214: }
215: }
216:
217: /**
218: * Initializes the list, if needed.
219: */
220: protected void revalidate() {
221: if (valid) {
222: return;
223: }
224:
225: String s = getValueAsString();
226: if (s == null) {
227: throw new LiveAttributeException(element, localName,
228: LiveAttributeException.ERR_ATTRIBUTE_MISSING,
229: null);
230: }
231: try {
232: ListBuilder builder = new ListBuilder();
233:
234: doParse(s, builder);
235:
236: if (builder.getList() != null) {
237: clear(itemList);
238: }
239: itemList = builder.getList();
240: } catch (ParseException e) {
241: itemList = new ArrayList(1);
242: valid = true;
243: throw new LiveAttributeException(element, localName,
244: LiveAttributeException.ERR_ATTRIBUTE_MALFORMED,
245: s);
246: }
247: valid = true;
248: }
249: }
250:
251: /**
252: * {@link SVGPointList} implementation for the animated point list value.
253: */
254: protected class AnimSVGPointList extends AbstractSVGPointList {
255:
256: /**
257: * Creates a new AnimSVGPointList.
258: */
259: public AnimSVGPointList() {
260: itemList = new ArrayList(1);
261: }
262:
263: /**
264: * Create a DOMException.
265: */
266: protected DOMException createDOMException(short type,
267: String key, Object[] args) {
268: return element.createDOMException(type, key, args);
269: }
270:
271: /**
272: * Create a SVGException.
273: */
274: protected SVGException createSVGException(short type,
275: String key, Object[] args) {
276:
277: return ((SVGOMElement) element).createSVGException(type,
278: key, args);
279: }
280:
281: /**
282: * <b>DOM</b>: Implements {@link SVGPointList#getNumberOfItems()}.
283: */
284: public int getNumberOfItems() {
285: if (hasAnimVal) {
286: return super .getNumberOfItems();
287: }
288: return getPoints().getNumberOfItems();
289: }
290:
291: /**
292: * <b>DOM</b>: Implements {@link SVGPointList#getItem(int)}.
293: */
294: public SVGPoint getItem(int index) throws DOMException {
295: if (hasAnimVal) {
296: return super .getItem(index);
297: }
298: return getPoints().getItem(index);
299: }
300:
301: /**
302: * Returns the value of the DOM attribute containing the point list.
303: */
304: protected String getValueAsString() {
305: if (itemList.size() == 0) {
306: return "";
307: }
308: StringBuffer sb = new StringBuffer(itemList.size() * 8);
309: Iterator i = itemList.iterator();
310: if (i.hasNext()) {
311: sb.append(((SVGItem) i.next()).getValueAsString());
312: }
313: while (i.hasNext()) {
314: sb.append(getItemSeparator());
315: sb.append(((SVGItem) i.next()).getValueAsString());
316: }
317: return sb.toString();
318: }
319:
320: /**
321: * Sets the DOM attribute value containing the point list.
322: */
323: protected void setAttributeValue(String value) {
324: }
325:
326: /**
327: * <b>DOM</b>: Implements {@link SVGPointList#clear()}.
328: */
329: public void clear() throws DOMException {
330: throw element.createDOMException(
331: DOMException.NO_MODIFICATION_ALLOWED_ERR,
332: "readonly.point.list", null);
333: }
334:
335: /**
336: * <b>DOM</b>: Implements {@link SVGPointList#initialize(SVGPoint)}.
337: */
338: public SVGPoint initialize(SVGPoint newItem)
339: throws DOMException, SVGException {
340: throw element.createDOMException(
341: DOMException.NO_MODIFICATION_ALLOWED_ERR,
342: "readonly.point.list", null);
343: }
344:
345: /**
346: * <b>DOM</b>: Implements {@link
347: * SVGPointList#insertItemBefore(SVGPoint, int)}.
348: */
349: public SVGPoint insertItemBefore(SVGPoint newItem, int index)
350: throws DOMException, SVGException {
351: throw element.createDOMException(
352: DOMException.NO_MODIFICATION_ALLOWED_ERR,
353: "readonly.point.list", null);
354: }
355:
356: /**
357: * <b>DOM</b>: Implements {@link
358: * SVGPointList#replaceItem(SVGPoint, int)}.
359: */
360: public SVGPoint replaceItem(SVGPoint newItem, int index)
361: throws DOMException, SVGException {
362: throw element.createDOMException(
363: DOMException.NO_MODIFICATION_ALLOWED_ERR,
364: "readonly.point.list", null);
365: }
366:
367: /**
368: * <b>DOM</b>: Implements {@link SVGPointList#removeItem(int)}.
369: */
370: public SVGPoint removeItem(int index) throws DOMException {
371: throw element.createDOMException(
372: DOMException.NO_MODIFICATION_ALLOWED_ERR,
373: "readonly.point.list", null);
374: }
375:
376: /**
377: * <b>DOM</b>: Implements {@link SVGPointList#appendItem(SVGPoint)}.
378: */
379: public SVGPoint appendItem(SVGPoint newItem)
380: throws DOMException {
381: throw element.createDOMException(
382: DOMException.NO_MODIFICATION_ALLOWED_ERR,
383: "readonly.point.list", null);
384: }
385:
386: /**
387: * Sets the animated value.
388: */
389: protected void setAnimatedValue(float[] pts) {
390: int size = itemList.size();
391: int i = 0;
392: while (i < size && i < pts.length / 2) {
393: SVGPointItem p = (SVGPointItem) itemList.get(i);
394: p.x = pts[i * 2];
395: p.y = pts[i * 2 + 1];
396: i++;
397: }
398: while (i < pts.length / 2) {
399: appendItemImpl(new SVGPointItem(pts[i * 2],
400: pts[i * 2 + 1]));
401: i++;
402: }
403: while (size > pts.length / 2) {
404: removeItemImpl(--size);
405: }
406: }
407:
408: /**
409: * Resets the value of the associated attribute. Does nothing, since
410: * there is no attribute for an animated value.
411: */
412: protected void resetAttribute() {
413: }
414:
415: /**
416: * Resets the value of the associated attribute. Does nothing, since
417: * there is no attribute for an animated value.
418: */
419: protected void resetAttribute(SVGItem item) {
420: }
421:
422: /**
423: * Initializes the list, if needed. Does nothing, since there is no
424: * attribute to read the list from.
425: */
426: protected void revalidate() {
427: valid = true;
428: }
429: }
430: }
|