| <?xml version="1.0"?> |
| |
| <!-- |
| |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| --> |
| |
| <!-- ========================================================================= --> |
| <!-- author shillion@ilog.fr --> |
| <!-- version $Id: javaScripting.xml 201374 2004-08-18 07:17:26Z vhardy $ --> |
| <!-- ========================================================================= --> |
| |
| <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" "http://forrest.apache.org/dtd/document-v20.dtd"> |
| <document> |
| <header> |
| <title>Scripting With Java</title> |
| </header> |
| |
| <body> |
| <p> |
| This page explains how to manipulate the DOM tree of an SVG |
| document from a Java program. |
| </p> |
| |
| <section id="Swing"> |
| <title>How to manipulate a document in a JSVGCanvas</title> |
| <p> |
| The follow code template demonstrates how to manipulate an SVG |
| document displayed in a |
| <a class="class" href="../../javadoc/org/apache/batik/swing/JSVGCanvas.html">JSVGCanvas</a> |
| directly from a Java program. |
| </p> |
| <note> |
| You don’t have to worry about graphics updates; after each event |
| listener invocation the canvas is updated if needed. |
| </note> |
| <source>import java.awt.event.WindowAdapter; |
| import java.awt.event.WindowEvent; |
| |
| import javax.swing.JFrame; |
| |
| import org.apache.batik.swing.JSVGCanvas; |
| import org.apache.batik.swing.svg.SVGLoadEventDispatcherAdapter; |
| import org.apache.batik.swing.svg.SVGLoadEventDispatcherEvent; |
| import org.apache.batik.script.Window; |
| |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.events.Event; |
| import org.w3c.dom.events.EventListener; |
| import org.w3c.dom.events.EventTarget; |
| |
| public class SVGApplication { |
| |
| public static void main(String[] args) { |
| new SVGApplication(); |
| } |
| |
| JFrame frame; |
| JSVGCanvas canvas; |
| Document document; |
| Window window; |
| |
| public SVGApplication() { |
| frame = new JFrame(); |
| canvas = new JSVGCanvas(); |
| // Forces the canvas to always be dynamic even if the current |
| // document does not contain scripting or animation. |
| canvas.setDocumentState(JSVGCanvas.ALWAYS_DYNAMIC); |
| canvas.addSVGLoadEventDispatcherListener |
| (new SVGLoadEventDispatcherAdapter() { |
| public void svgLoadEventDispatchStarted |
| (SVGLoadEventDispatcherEvent e) { |
| // At this time the document is available... |
| document = canvas.getSVGDocument(); |
| // ...and the window object too. |
| window = canvas.getUpdateManager(). |
| getScriptingEnvironment().createWindow(); |
| // Registers the listeners on the document |
| // just before the SVGLoad event is |
| // dispatched. |
| registerListeners(); |
| // It is time to pack the frame. |
| frame.pack(); |
| } |
| }); |
| |
| frame.addWindowListener(new WindowAdapter() { |
| public void windowOpened(WindowEvent e) { |
| // The canvas is ready to load the base document |
| // now, from the AWT thread. |
| canvas.setURI("doc.svg"); |
| } |
| }); |
| |
| frame.getContentPane().add(canvas); |
| frame.setSize(800, 600); |
| frame.show(); |
| } |
| |
| public void registerListeners() { |
| // Gets an element from the loaded document. |
| Element elt = document.getElementById("elt-id"); |
| EventTarget t = (EventTarget)elt; |
| |
| // Adds a 'onload' listener |
| t.addEventListener("SVGLoad", new OnLoadAction(), false); |
| |
| // Adds a 'onclick' listener |
| t.addEventListener("click", new OnClickAction(), false); |
| } |
| |
| public class OnLoadAction implements EventListener { |
| public void handleEvent(Event evt) { |
| // Perform some actions here... |
| |
| // ...for example start an animation loop: |
| window.setInterval(new Animation(), 50); |
| } |
| } |
| |
| public class OnClickAction implements EventListener { |
| public void handleEvent(Event evt) { |
| // Perform some actions here... |
| |
| // ...for example schedule an action for later: |
| window.setTimeout(new DelayedTask(), 500); |
| } |
| } |
| |
| public class Animation implements Runnable { |
| public void run() { |
| // Insert animation code here... |
| } |
| } |
| |
| public class DelayedTask implements Runnable { |
| public void run() { |
| // Perform some actions here... |
| |
| // ...for example displays an alert dialog: |
| window.alert("Delayed Action invoked!"); |
| } |
| } |
| } |
| </source> |
| </section> |
| |
| <section id="Threads"> |
| <title>Writing thread-safe code</title> |
| <p> |
| The DOM listeners registered on the SVG document are called from |
| the canvas update thread. To avoid race conditions, do not manipulate |
| the DOM tree from another thread. |
| </p> |
| <p> |
| The way to switch from an external thread to the canvas update |
| thread is to use the following code: |
| </p> |
| <source>// Returns immediately |
| canvas.getUpdateManager().getUpdateRunnableQueue(). |
| invokeLater(new Runnable() { |
| public void run() { |
| // Insert some actions on the DOM here |
| } |
| });</source> |
| <p>or:</p> |
| <source>// Waits until the Runnable is invoked |
| canvas.getUpdateManager().getUpdateRunnableQueue(). |
| invokeAndWait(new Runnable() { |
| public void run() { |
| // Insert some actions on the DOM here |
| } |
| });</source> |
| <p> |
| Like with event listeners, when a |
| <a class="class" href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Runnable.html">Runnable</a> |
| is invoked from the update thread, the graphics are updated. |
| </p> |
| <note> |
| It is very dangerous to call <code>invokeAndWait</code> from the |
| Swing event thread. This is the only thread that can be |
| used to interact with Swing components. In some cases |
| DOM calls may need to query the canvas for information |
| (such as actual Swing component size, etc). If this |
| happens you will get a thread deadlock. You should |
| only make invokeAndWait calls from “third party” threads. |
| </note> |
| </section> |
| |
| <section id="SVGDOM"> |
| <title>Using the SVG DOM</title> |
| <p> |
| Batik provides a fairly complete implementation of the |
| SVG DOM. The SVG DOM provides all the functionality most |
| applications require. In particular, the DOM implements |
| DOM Events, including mutation and UI Events. As an example, |
| DOM events allow you to get notified when the cursor moves over |
| elements of interest: |
| </p> |
| <source>// Element of Interest. |
| Element theElem = ...; |
| ((EventTarget) theElem).addEventListener("mouseover", mouseOverListener, true);</source> |
| <p> |
| where <code>mouseOverListener</code> implements the |
| <a class="class" href="http://java.sun.com/j2se/1.5.0/docs/api/org/w3c/dom/events/EventListener.html">org.w3c.dom.events.EventListener</a> |
| interface. This interface consists of the method: |
| </p> |
| <source>void handleEvent(Event evt);</source> |
| <p> |
| This is called whenever the event occurs with the |
| element it is registered on. It is worth reviewing the |
| DOM Events specification as there are many useful features |
| to this interface that are not immediately obvious. |
| </p> |
| <p> |
| It is also worth looking at the DOM interfaces defined |
| by the SVG specification as they provide a large number |
| of useful methods, in particular those of |
| <a class="class" href="../../javadoc/org/w3c/dom/svg/SVGLocatable.html">SVGLocatable</a>: |
| </p> |
| <source>// Returns Bounding box of SVG Element. |
| public SVGRect getBBox ( ); |
| // Returns the transformation matrix to the screen. |
| public SVGMatrix getScreenCTM ( ); |
| // Returns the transformation matrix to the given element. |
| public SVGMatrix getTransformToElement ( SVGElement element ) |
| throws SVGException;</source> |
| <p> |
| In particular, <code>getScreenCTM</code> is very useful for |
| taking the <code>clientX</code> and <code>clientY</code> attributes of |
| the DOM |
| <a class="class" href="http://java.sun.com/j2se/1.5.0/docs/api/org/w3c/dom/events/UIEvent.html">UIEvent</a> |
| and mapping them to the coordinate system of an element in the SVG |
| document: |
| </p> |
| <source>SVGMatrix mat = elem.getScreenCTM(); |
| SVGMatrix imat = mat.inverse(); |
| SVGPoint cPt = document.getRootElement().createSVGPoint(); |
| cPt.setX(uiEvt.getClientX()); |
| cPt.setY(uiEvt.getClientY()); |
| cPt = cPt.matrixTransform(imat);</source> |
| </section> |
| |
| <section id="javaInDocument"> |
| <title>Referencing Java code from a document</title> |
| <p> |
| Batik implements the Java bindings for SVG, and thus allows Java |
| code to be referenced from <code>script</code> elements. |
| This feature is available to any application of Batik that uses |
| the bridge module (for example the Swing component and the |
| transcoders). |
| </p> |
| <p> |
| In order to use this extension, the <code>type</code> attribute |
| of a <code>script</code> element must be set to |
| <code>application/java-archive</code>. In addition, the |
| <code>xlink:href</code> attribute must be the URI of a jar file |
| that contains the code to run. |
| </p> |
| <p> |
| The manifest of this jar file must contains an entry of the form: |
| </p> |
| <source>SVG-Handler-Class: <em>classname</em></source> |
| <p> |
| where <em>classname</em> must be the name of a class that |
| implements the |
| <a class="class" href="../../javadoc/org/w3c/dom/svg/EventListenerInitializer.html">org.w3c.dom.svg.EventListenerInitializer</a> |
| interface. Just before the document <code>SVGLoad</code> event |
| is fired, an instance of this class is created, and this instance has |
| its <code>initializeEventListeners</code> method invoked. Note that |
| there is no way to specify Java handlers in event attributes on |
| SVG elements, so having the <code>initializeEventListeners</code> |
| call <code>addEventListener</code> on a node is the only way to |
| attach a Java listener from within the document. |
| </p> |
| <p> |
| The class specified by <code>SVG-Handler-Class</code> can be contained |
| directly in the jar file, but it is also possible for it to be |
| contained in a jar file added to the classpath using the |
| <code>Class-Path</code> entry of the manifest. |
| </p> |
| </section> |
| |
| </body> |
| </document> |