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.bridge;
020:
021: import org.apache.batik.gvt.CompositeGraphicsNode;
022: import org.apache.batik.gvt.GraphicsNode;
023: import org.apache.batik.gvt.RootGraphicsNode;
024: import org.apache.batik.util.HaltingThread;
025: import org.apache.batik.util.SVGConstants;
026:
027: import org.w3c.dom.Document;
028: import org.w3c.dom.Element;
029: import org.w3c.dom.Node;
030:
031: /**
032: * This class is responsible for creating a GVT tree using an SVG DOM tree.
033: *
034: * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
035: * @version $Id: GVTBuilder.java 475477 2006-11-15 22:44:28Z cam $
036: */
037: public class GVTBuilder implements SVGConstants {
038:
039: /**
040: * Constructs a new builder.
041: */
042: public GVTBuilder() {
043: }
044:
045: /**
046: * Builds using the specified bridge context the specified SVG document.
047: *
048: * @param ctx the bridge context
049: * @param document the SVG document to build
050: * @exception BridgeException if an error occured while constructing
051: * the GVT tree
052: */
053: public GraphicsNode build(BridgeContext ctx, Document document) {
054: // the bridge context is now associated to one document
055: ctx.setDocument(document);
056: ctx.initializeDocument(document);
057:
058: // inform the bridge context the builder to use
059: ctx.setGVTBuilder(this );
060:
061: // build the GVT tree
062: RootGraphicsNode rootNode = new RootGraphicsNode();
063: Element svgElement = document.getDocumentElement();
064: GraphicsNode topNode = null;
065: try {
066: // get the appropriate bridge according to the specified element
067: Bridge bridge = ctx.getBridge(svgElement);
068: if (bridge == null
069: || !(bridge instanceof GraphicsNodeBridge)) {
070: return null;
071: }
072: // create the associated composite graphics node
073: GraphicsNodeBridge gnBridge = (GraphicsNodeBridge) bridge;
074: topNode = gnBridge.createGraphicsNode(ctx, svgElement);
075: if (topNode == null) {
076: return null;
077: }
078: rootNode.getChildren().add(topNode);
079:
080: buildComposite(ctx, svgElement,
081: (CompositeGraphicsNode) topNode);
082: gnBridge.buildGraphicsNode(ctx, svgElement, topNode);
083: } catch (BridgeException ex) {
084: // update the exception with the missing parameters
085: ex.setGraphicsNode(rootNode);
086: ex.printStackTrace();
087: throw ex; // re-throw the udpated exception
088: }
089:
090: // For cursor handling
091: if (ctx.isInteractive()) {
092: ctx.addUIEventListeners(document);
093:
094: // register GVT listeners for AWT event support
095: ctx.addGVTListener(document);
096: }
097:
098: // <!> FIXME: TO BE REMOVED
099: if (ctx.isDynamic()) {
100: // register DOM listeners for dynamic support
101: ctx.addDOMListeners();
102: }
103: return rootNode;
104: }
105:
106: /**
107: * Builds using the specified bridge context the specified Element.
108: *
109: * @param ctx the bridge context
110: * @param e the element to build
111: * @exception BridgeException if an error occured while constructing
112: * the GVT tree
113: */
114: public GraphicsNode build(BridgeContext ctx, Element e) {
115: // get the appropriate bridge according to the specified element
116: Bridge bridge = ctx.getBridge(e);
117: if (bridge instanceof GenericBridge) {
118: // If it is a GenericBridge just handle it and any GenericBridge
119: // descendents and return.
120: ((GenericBridge) bridge).handleElement(ctx, e);
121: handleGenericBridges(ctx, e);
122: return null;
123: } else if (bridge == null
124: || !(bridge instanceof GraphicsNodeBridge)) {
125: handleGenericBridges(ctx, e);
126: return null;
127: }
128: // create the associated graphics node
129: GraphicsNodeBridge gnBridge = (GraphicsNodeBridge) bridge;
130: // check the display property
131: if (!gnBridge.getDisplay(e)) {
132: handleGenericBridges(ctx, e);
133: return null;
134: }
135: GraphicsNode gn = gnBridge.createGraphicsNode(ctx, e);
136: if (gn != null) {
137: if (gnBridge.isComposite()) {
138: buildComposite(ctx, e, (CompositeGraphicsNode) gn);
139: } else {
140: handleGenericBridges(ctx, e);
141: }
142: gnBridge.buildGraphicsNode(ctx, e, gn);
143: }
144: // <!> FIXME: see build(BridgeContext, Element)
145: // + may load the script twice (for example
146: // outside 'use' is ok versus local 'use' maybe wrong).
147: if (ctx.isDynamic()) {
148: //BridgeEventSupport.loadScripts(ctx, e);
149: }
150: return gn;
151: }
152:
153: /**
154: * Builds a composite Element.
155: *
156: * @param ctx the bridge context
157: * @param e the element to build
158: * @param parentNode the composite graphics node, parent of the
159: * graphics node to build
160: * @exception BridgeException if an error occured while constructing
161: * the GVT tree
162: */
163: protected void buildComposite(BridgeContext ctx, Element e,
164: CompositeGraphicsNode parentNode) {
165: for (Node n = e.getFirstChild(); n != null; n = n
166: .getNextSibling()) {
167: if (n.getNodeType() == Node.ELEMENT_NODE) {
168: buildGraphicsNode(ctx, (Element) n, parentNode);
169: }
170: }
171: }
172:
173: /**
174: * Builds a 'leaf' Element.
175: *
176: * @param ctx the bridge context
177: * @param e the element to build
178: * @param parentNode the composite graphics node, parent of the
179: * graphics node to build
180: * @exception BridgeException if an error occured while constructing
181: * the GVT tree
182: */
183: protected void buildGraphicsNode(BridgeContext ctx, Element e,
184: CompositeGraphicsNode parentNode) {
185: // Check If we should halt early.
186: if (HaltingThread.hasBeenHalted()) {
187: throw new InterruptedBridgeException();
188: }
189: // get the appropriate bridge according to the specified element
190: Bridge bridge = ctx.getBridge(e);
191: if (bridge instanceof GenericBridge) {
192: // If it is a GenericBridge just handle it and any GenericBridge
193: // descendents and return.
194: ((GenericBridge) bridge).handleElement(ctx, e);
195: handleGenericBridges(ctx, e);
196: return;
197: } else if (bridge == null
198: || !(bridge instanceof GraphicsNodeBridge)) {
199: handleGenericBridges(ctx, e);
200: return;
201: }
202: // check the display property
203: if (!CSSUtilities.convertDisplay(e)) {
204: handleGenericBridges(ctx, e);
205: return;
206: }
207: GraphicsNodeBridge gnBridge = (GraphicsNodeBridge) bridge;
208: try {
209: // create the associated graphics node
210: GraphicsNode gn = gnBridge.createGraphicsNode(ctx, e);
211: if (gn != null) {
212: // attach the graphics node to the GVT tree now !
213: parentNode.getChildren().add(gn);
214: // check if the element has children to build
215: if (gnBridge.isComposite()) {
216: buildComposite(ctx, e, (CompositeGraphicsNode) gn);
217: } else {
218: // if not then still handle the GenericBridges
219: handleGenericBridges(ctx, e);
220: }
221: gnBridge.buildGraphicsNode(ctx, e, gn);
222: } else {
223: handleGenericBridges(ctx, e);
224: }
225: } catch (BridgeException ex) {
226: // some bridge may decide that the node in error can be
227: // displayed (e.g. polyline, path...)
228: // In this case, the exception contains the GraphicsNode
229: GraphicsNode errNode = ex.getGraphicsNode();
230: if (errNode != null) {
231: parentNode.getChildren().add(errNode);
232: gnBridge.buildGraphicsNode(ctx, e, errNode);
233: ex.setGraphicsNode(null);
234: }
235: //ex.printStackTrace();
236: throw ex;
237: }
238: }
239:
240: /**
241: * Handles any GenericBridge elements which are children of the
242: * specified element.
243: * @param ctx the bridge context
244: * @param e the element whose child elements should be handled
245: */
246: protected void handleGenericBridges(BridgeContext ctx, Element e) {
247: for (Node n = e.getFirstChild(); n != null; n = n
248: .getNextSibling()) {
249: if (n instanceof Element) {
250: Element e2 = (Element) n;
251: Bridge b = ctx.getBridge(e2);
252: if (b instanceof GenericBridge) {
253: ((GenericBridge) b).handleElement(ctx, e2);
254: }
255: handleGenericBridges(ctx, e2);
256: }
257: }
258: }
259: }
|