hillion 01/12/21 06:40:32 Modified: resources/org/apache/batik/apps/svgbrowser/resources GUI.properties sources/org/apache/batik/apps/svgbrowser JSVGViewerFrame.java sources/org/apache/batik/bridge BridgeContext.java BridgeEventSupport.java GVTBuilder.java sources/org/apache/batik/dom DOMImplementationWrapper.java DocumentWrapper.java sources/org/apache/batik/dom/events EventListenerWrapper.java sources/org/apache/batik/swing/gvt JGVTComponent.java sources/org/apache/batik/swing/svg JSVGComponent.java sources/org/apache/batik/util RunnableQueue.java Added: resources/org/apache/batik/apps/svgbrowser/resources pause.gif play.gif sources/org/apache/batik/bridge RepaintManager.java UpdateManager.java UpdateManagerEvent.java UpdateManagerListener.java sources/org/apache/batik/gvt UpdateTracker.java Log: Dynamic threading model now in place: The loading is like before, then the SVG component switches in dynamic mode (in the future the document will be scanned to see if it is dynamic): a batik.brige.UpdateManager is created which holds the update RunnableQueue, the scripting RunnableQueue, the scripting DOM wrapper and the repaint thread (batik.bridge.RepaintManager). The repaint thread sleeps and query the GVT update tracker (batik.gvt.UpdateTracker) to repaint if needed. For the moment the interactions and the scripting work in the right threads, the update tracker does nothing. The browser resizing is not as fast as before since a repaint called from a RunnableQueue is not (must not be?) interrupted. The browser have 2 new items: play and pause. The stop button now stops the update manager. Revision Changes Path 1.41 +25 -3 xml-batik/resources/org/apache/batik/apps/svgbrowser/resources/GUI.properties Index: GUI.properties =================================================================== RCS file: /home/cvs/xml-batik/resources/org/apache/batik/apps/svgbrowser/resources/GUI.properties,v retrieving revision 1.40 retrieving revision 1.41 diff -u -r1.40 -r1.41 --- GUI.properties 2001/12/03 15:44:08 1.40 +++ GUI.properties 2001/12/21 14:40:31 1.41 @@ -9,7 +9,7 @@ # The viewer's GUI resources. # # Author: [EMAIL PROTECTED] -# $Id: GUI.properties,v 1.40 2001/12/03 15:44:08 vhardy Exp $ +# $Id: GUI.properties,v 1.41 2001/12/21 14:40:31 hillion Exp $ # ViewSource.width = 750 @@ -233,11 +233,25 @@ # Processing menu ################ -Processing = Stop +Processing = Play Pause Stop Processing.type = MENU Processing.text = Processing Processing.mnemonic = P +Play.type = ITEM +Play.text = Play +Play.icon = resources/play.gif +Play.mnemonic = P +Play.action = PlayAction +Play.accelerator = Ctrl+H + +Pause.type = ITEM +Pause.text = Pause +Pause.icon = resources/pause.gif +Pause.mnemonic = A +Pause.action = PauseAction +Pause.accelerator = Ctrl+J + Stop.type = ITEM Stop.text = Stop Stop.icon = resources/stop.gif @@ -310,7 +324,7 @@ ToolBar = ToolOpen - ToolReload ToolBack ToolForward - \ ToolZoomIn ToolZoomOut - ToolViewSource ToolDOMViewer - \ - ToolPrint - ToolStop + ToolPrint - ToolPlay ToolPause ToolStop ToolOpen.icon = resources/open.gif ToolOpen.action = OpenAction @@ -347,6 +361,14 @@ ToolDOMViewer.icon = resources/domtree.gif ToolDOMViewer.action = DOMViewerAction ToolDOMViewer.tooltip = Shows the DOM Viewer. + +ToolPlay.icon = resources/play.gif +ToolPlay.action = PlayAction +ToolPlay.tooltip = Continue the Processing of the SVG Document. + +ToolPause.icon = resources/pause.gif +ToolPause.action = PauseAction +ToolPause.tooltip = Pause the Processing of the SVG Document. ToolStop.icon = resources/stop.gif ToolStop.action = StopAction 1.1 xml-batik/resources/org/apache/batik/apps/svgbrowser/resources/pause.gif <<Binary file>> 1.1 xml-batik/resources/org/apache/batik/apps/svgbrowser/resources/play.gif <<Binary file>> 1.68 +152 -2 xml-batik/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java Index: JSVGViewerFrame.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java,v retrieving revision 1.67 retrieving revision 1.68 diff -u -r1.67 -r1.68 --- JSVGViewerFrame.java 2001/12/13 17:56:02 1.67 +++ JSVGViewerFrame.java 2001/12/21 14:40:31 1.68 @@ -12,6 +12,7 @@ import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; +import java.awt.EventQueue; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Rectangle; @@ -81,6 +82,9 @@ import javax.swing.text.Document; import javax.swing.text.PlainDocument; +import org.apache.batik.bridge.UpdateManagerEvent; +import org.apache.batik.bridge.UpdateManagerListener; + import org.apache.batik.dom.StyleSheetProcessingInstruction; import org.apache.batik.dom.svg.SVGOMDocument; @@ -155,7 +159,7 @@ * This class represents a SVG viewer swing frame. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> - * @version $Id: JSVGViewerFrame.java,v 1.67 2001/12/13 17:56:02 vhardy Exp $ + * @version $Id: JSVGViewerFrame.java,v 1.68 2001/12/21 14:40:31 hillion Exp $ */ public class JSVGViewerFrame extends JFrame @@ -163,7 +167,8 @@ SVGDocumentLoaderListener, GVTTreeBuilderListener, GVTTreeRendererListener, - LinkActivationListener { + LinkActivationListener, + UpdateManagerListener { /** * The gui resources file name @@ -193,6 +198,8 @@ public final static String PREVIOUS_TRANSFORM_ACTION = "PreviousTransformAction"; public final static String NEXT_TRANSFORM_ACTION = "NextTransformAction"; public final static String USE_STYLESHEET_ACTION = "UseStylesheetAction"; + public final static String PLAY_ACTION = "PlayAction"; + public final static String PAUSE_ACTION = "PauseAction"; public final static String STOP_ACTION = "StopAction"; public final static String MONITOR_ACTION = "MonitorAction"; public final static String DOM_VIEWER_ACTION = "DOMViewerAction"; @@ -263,6 +270,16 @@ protected ForwardAction forwardAction = new ForwardAction(); /** + * The play action + */ + protected PlayAction playAction = new PlayAction(); + + /** + * The pause action + */ + protected PauseAction pauseAction = new PauseAction(); + + /** * The stop action */ protected StopAction stopAction = new StopAction(); @@ -417,6 +434,8 @@ listeners.put(PREVIOUS_TRANSFORM_ACTION, previousTransformAction); listeners.put(NEXT_TRANSFORM_ACTION, nextTransformAction); listeners.put(USE_STYLESHEET_ACTION, useStylesheetAction); + listeners.put(PLAY_ACTION, playAction); + listeners.put(PAUSE_ACTION, pauseAction); listeners.put(STOP_ACTION, stopAction); listeners.put(MONITOR_ACTION, new MonitorAction()); listeners.put(DOM_VIEWER_ACTION, new DOMViewerAction()); @@ -464,6 +483,7 @@ svgCanvas.addGVTTreeBuilderListener(this); svgCanvas.addGVTTreeRendererListener(this); svgCanvas.addLinkActivationListener(this); + svgCanvas.addUpdateManagerListener(this); svgCanvas.addMouseMotionListener(new MouseMotionAdapter() { public void mouseMoved(MouseEvent e) { @@ -1261,6 +1281,54 @@ } /** + * To restart after a pause. + */ + public class PlayAction extends AbstractAction + implements JComponentModifier { + java.util.List components = new LinkedList(); + public PlayAction() {} + public void actionPerformed(ActionEvent e) { + svgCanvas.resumeProcessing(); + } + + public void addJComponent(JComponent c) { + components.add(c); + c.setEnabled(false); + } + + public void update(boolean enabled) { + Iterator it = components.iterator(); + while (it.hasNext()) { + ((JComponent)it.next()).setEnabled(enabled); + } + } + } + + /** + * To pause a document. + */ + public class PauseAction extends AbstractAction + implements JComponentModifier { + java.util.List components = new LinkedList(); + public PauseAction() {} + public void actionPerformed(ActionEvent e) { + svgCanvas.suspendProcessing(); + } + + public void addJComponent(JComponent c) { + components.add(c); + c.setEnabled(false); + } + + public void update(boolean enabled) { + Iterator it = components.iterator(); + while (it.hasNext()) { + ((JComponent)it.next()).setEnabled(enabled); + } + } + } + + /** * To stop the current processing. */ public class StopAction extends AbstractAction @@ -1683,6 +1751,88 @@ nextTransformAction.update(); } } + } + + // UpdateManagerListener //////////////////////////////////////////////// + + /** + * Called when the manager was started. + */ + public void managerStarted(UpdateManagerEvent e) { + EventQueue.invokeLater(new Runnable() { + public void run() { + if (debug) { + System.out.println("Manager Started"); + } + playAction.update(false); + pauseAction.update(true); + stopAction.update(true); + } + }); + } + + /** + * Called when the manager was suspended. + */ + public void managerSuspended(UpdateManagerEvent e) { + EventQueue.invokeLater(new Runnable() { + public void run() { + if (debug) { + System.out.println("Manager Suspended"); + } + playAction.update(true); + pauseAction.update(false); + } + }); + } + + /** + * Called when the manager was resumed. + */ + public void managerResumed(UpdateManagerEvent e) { + EventQueue.invokeLater(new Runnable() { + public void run() { + if (debug) { + System.out.println("Manager Resumed"); + } + playAction.update(false); + pauseAction.update(true); + } + }); + } + + /** + * Called when the manager was stopped. + */ + public void managerStopped(UpdateManagerEvent e) { + EventQueue.invokeLater(new Runnable() { + public void run() { + if (debug) { + System.out.println("Manager Stopped"); + } + playAction.update(false); + pauseAction.update(false); + stopAction.update(false); + } + }); + } + + /** + * Called when an update started. + */ + public void updateStarted(final UpdateManagerEvent e) { + } + + /** + * Called when an update was completed. + */ + public void updateCompleted(final UpdateManagerEvent e) { + } + + /** + * Called when an update failed. + */ + public void updateFailed(UpdateManagerEvent e) { } /** 1.31 +33 -2 xml-batik/sources/org/apache/batik/bridge/BridgeContext.java Index: BridgeContext.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/BridgeContext.java,v retrieving revision 1.30 retrieving revision 1.31 diff -u -r1.30 -r1.31 --- BridgeContext.java 2001/11/14 20:03:31 1.30 +++ BridgeContext.java 2001/12/21 14:40:31 1.31 @@ -45,7 +45,7 @@ * a SVG DOM tree such as the current viewport or the user agent. * * @author <a href="mailto:[EMAIL PROTECTED]">Thierry Kormann</a> - * @version $Id: BridgeContext.java,v 1.30 2001/11/14 20:03:31 deweese Exp $ + * @version $Id: BridgeContext.java,v 1.31 2001/12/21 14:40:31 hillion Exp $ */ public class BridgeContext implements ErrorConstants { @@ -128,6 +128,16 @@ protected TextPainter textPainter; /** + * Whether the bridge must support dynamic features. + */ + protected boolean dynamic; + + /** + * The update manager. + */ + protected UpdateManager updateManager; + + /** * Constructs a new empty bridge context. */ protected BridgeContext() {} @@ -361,7 +371,28 @@ * false otherwise. */ public boolean isDynamic() { - return true; + return dynamic; + } + + /** + * Sets the dynamic mode. + */ + public void setDynamic(boolean b) { + dynamic = b; + } + + /** + * Returns the update manager, if the bridge supports dynamic features. + */ + public UpdateManager getUpdateManager() { + return updateManager; + } + + /** + * Sets the update manager. + */ + protected void setUpdateManager(UpdateManager um) { + updateManager = um; } ///////////////////////////////////////////////////////////////////////// 1.18 +94 -88 xml-batik/sources/org/apache/batik/bridge/BridgeEventSupport.java Index: BridgeEventSupport.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/BridgeEventSupport.java,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- BridgeEventSupport.java 2001/11/02 09:47:58 1.17 +++ BridgeEventSupport.java 2001/12/21 14:40:31 1.18 @@ -18,6 +18,8 @@ import java.util.List; import java.util.HashMap; +import org.apache.batik.dom.DocumentWrapper; +import org.apache.batik.dom.events.EventWrapper; import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.gvt.event.EventDispatcher; import org.apache.batik.gvt.event.GraphicsNodeKeyEvent; @@ -27,6 +29,7 @@ import org.apache.batik.script.Interpreter; import org.apache.batik.script.InterpreterException; import org.apache.batik.script.InterpreterPool; +import org.apache.batik.util.RunnableQueue; import org.apache.batik.util.SVGConstants; import org.w3c.dom.Document; @@ -53,7 +56,7 @@ * on the GVT root to propagate GVT events to the DOM. * @author <a href="mailto:[EMAIL PROTECTED]>Christophe Jolif</a> * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> - * @version $Id: BridgeEventSupport.java,v 1.17 2001/11/02 09:47:58 tkormann Exp $ + * @version $Id: BridgeEventSupport.java,v 1.18 2001/12/21 14:40:31 hillion Exp $ */ class BridgeEventSupport implements SVGConstants { private static final String[] EVENT_ATTRIBUTES_GRAPHICS = { @@ -67,10 +70,9 @@ "onmouseover", "onmouseout", "onmousemove", - "onload" }; - private static final int FIRST_SVG_EVENT = 10; + private static final int FIRST_SVG_EVENT = 9; private static final String[] EVENT_ATTRIBUTES_SVG = { // document @@ -82,7 +84,7 @@ "onzoom" }; - private static final int FIRST_ANIMATION_EVENT = 16; + private static final int FIRST_ANIMATION_EVENT = 15; private static final String[] EVENT_ATTRIBUTES_ANIMATION = { // animation @@ -102,7 +104,6 @@ "mouseover", "mouseout", "mousemove", - "SVGLoad", // document "SVGUnload", @@ -152,31 +153,15 @@ } } String language = svgElement.getContentScriptType(); - Interpreter interpret = null; String script = null; if (element.getLocalName().equals(SVG_SVG_TAG)) { for (int i = 0; i < EVENT_ATTRIBUTES_SVG.length; i++) { if (!(script = element.getAttribute(EVENT_ATTRIBUTES_SVG[i])). equals("")) { - if (interpret == null) { - // try to get the intepreter only if we have - // a reason to do it! - interpret = ctx.getInterpreterPool(). - getInterpreter(element.getOwnerDocument(), language); - // the interpreter is not avaible => stop it now! - if (interpret == null) { - UserAgent ua = ctx.getUserAgent(); - if (ua != null) - ua.displayError(new Exception("unknow language: "+ - language)); - break; - } - } // <!> TODO this will stop working if someone change // the content of the event attribute addScriptCaller(target, EVENT_NAMES[i+FIRST_SVG_EVENT], - new ScriptCaller(ctx.getUserAgent(), - script, interpret)); + new ScriptCaller(ctx, script, language)); } } // continue @@ -187,27 +172,11 @@ if (!(script = element.getAttribute(EVENT_ATTRIBUTES_ANIMATION[i])). equals("")) { - if (interpret == null) { - // try to get the intepreter only if we have - // a reason to do it! - interpret = ctx.getInterpreterPool(). - getInterpreter(element.getOwnerDocument(), - language); - // the interpreter is not avaible => stop it now! - if (interpret == null) { - UserAgent ua = ctx.getUserAgent(); - if (ua != null) - ua.displayError(new Exception("unknow language: "+ - language)); - break; - } - } // <!> TODO this will stop working if someone change // the content of the event attribute addScriptCaller(target, EVENT_NAMES[i+ FIRST_ANIMATION_EVENT], - new ScriptCaller(ctx.getUserAgent(), - script, interpret)); + new ScriptCaller(ctx, script, language)); } } // not other stuff to do on this kind of events @@ -216,29 +185,38 @@ for (int i = 0; i < EVENT_ATTRIBUTES_GRAPHICS.length; i++) { if (!(script = element.getAttribute(EVENT_ATTRIBUTES_GRAPHICS[i])). equals("")) { - if (interpret == null) { - // try to get the intepreter only if we have - // a reason to do it! - interpret = ctx.getInterpreterPool(). - getInterpreter(element.getOwnerDocument(), language); - // the interpreter is not avaible => stop it now! - if (interpret == null) { - UserAgent ua = ctx.getUserAgent(); - if (ua != null) - ua.displayError(new Exception("unknow language: "+ - language)); - break; - } - } // <!> TODO this will stop working if someone change // the content of the event attribute addScriptCaller(target, EVENT_NAMES[i], - new ScriptCaller(ctx.getUserAgent(), - script, interpret)); + new ScriptCaller(ctx, script, language)); } } } + /** + * Recursively dispatches the onload events. + */ + public static void dispatchOnLoad(BridgeContext ctx, + Element root, + String language) { + for (Node n = root.getFirstChild(); n != null; n = n.getNextSibling()) { + if (n.getNodeType() == n.ELEMENT_NODE) { + dispatchOnLoad(ctx, (Element)n, language); + } + } + + String s = root.getAttributeNS(null, "onload"); + if (s.length() != 0) { + Event ev; + ev = ((DocumentEvent)root.getOwnerDocument()).createEvent("SVGEvents"); + ev.initEvent("SVGLoad", false, false); + EventTarget t = (EventTarget)root; + EventListener l = new ScriptCaller(ctx, s, language); + t.addEventListener("SVGLoad", l, false); + t.dispatchEvent(ev); + t.removeEventListener("SVGLoad", l, false); + } + } public static void updateDOMListener(BridgeContext ctx, SVGElement element) { @@ -327,7 +305,9 @@ } public static void loadScripts(BridgeContext ctx, Element element) { - Document doc = element.getOwnerDocument(); + UpdateManager um = ctx.getUpdateManager(); + RunnableQueue rq = um.getScriptingRunnableQueue(); + Document doc = um.getScriptingDocument(); NodeList list = element.getElementsByTagNameNS(SVG_NAMESPACE_URI, SVG_SCRIPT_TAG); final UserAgent ua = ctx.getUserAgent(); @@ -344,18 +324,22 @@ n = n.getNextSibling()) { script.append(n.getNodeValue()); } - try { - // use Reader mechanism => no caching - // (will not be revaluated + <script> content is - // generally bigger than the one in event attributes - interpret.evaluate(new StringReader(script.toString())); - } catch (IOException io) { - // will never appeared we don't use a file - } catch (InterpreterException e) { - if (ua != null) - ua.displayError(new Exception("scripting error: "+ - e.getMessage())); - } + rq.invokeLater(new Runnable() { + public void run() { + try { + // use Reader mechanism => no caching + // (will not be revaluated + <script> content is + // generally bigger than the one in event attributes + interpret.evaluate(new StringReader(script.toString())); + } catch (IOException io) { + // will never appeared we don't use a file + } catch (InterpreterException e) { + if (ua != null) + ua.displayError(new Exception("scripting error: "+ + e.getMessage())); + } + } + }); } else { if (ua != null) { ua.displayError(new Exception("unknown language: "+language)); @@ -367,13 +351,17 @@ final Interpreter interpret = ctx.getInterpreterPool().getInterpreter(doc, language); if (interpret != null) { - try { - javax.swing.JOptionPane pane = new javax.swing.JOptionPane(); - interpret.bindObject("pane", pane); - interpret.evaluate("function alert(msg) { pane.showMessageDialog(null, msg); }"); - } catch (Exception ex) { - // nothing to do - } + rq.invokeLater(new Runnable() { + public void run() { + try { + javax.swing.JOptionPane pane = new javax.swing.JOptionPane(); + interpret.bindObject("pane", pane); + interpret.evaluate("function alert(msg) { pane.showMessageDialog(null, msg); }"); + } catch (Exception ex) { + // nothing to do + } + } + }); } } @@ -515,31 +503,49 @@ } } - public static class ScriptCaller implements EventListener { private static String EVENT_NAME = "evt"; private String script = null; - private Interpreter interpreter = null; private UserAgent ua = null; + private BridgeContext context; + private String language; - public ScriptCaller(UserAgent agent, - String str, Interpreter interpret) { + public ScriptCaller(BridgeContext ctx, + String str, + String lang) { script = str; - interpreter = interpret; - ua = agent; + context = ctx; + language = lang; + ua = ctx.getUserAgent(); } public void handleEvent(Event evt) { - interpreter.bindObject(EVENT_NAME, evt); - try { - // use the String version to enable caching mechanism - interpreter.evaluate(script); - } catch (InterpreterException e) { + UpdateManager um = context.getUpdateManager(); + final DocumentWrapper dw = um.getScriptingDocument(); + RunnableQueue rq = um.getScriptingRunnableQueue(); + final Interpreter interpreter = context.getInterpreterPool(). + getInterpreter(dw, language); + if (interpreter == null) { if (ua != null) - ua.displayError(new Exception("scripting error: "+ - e.getMessage())); + ua.displayError(new Exception("unknow language: "+ + language)); + return; } + final Event ev = dw.createEventWrapper(evt); + rq.invokeLater(new Runnable() { + public void run() { + interpreter.bindObject(EVENT_NAME, ev); + try { + // use the String version to enable caching mechanism + interpreter.evaluate(script); + } catch (InterpreterException e) { + if (ua != null) + ua.displayError(new Exception("scripting error: "+ + e.getMessage())); + } + } + }); } } } 1.15 +2 -3 xml-batik/sources/org/apache/batik/bridge/GVTBuilder.java Index: GVTBuilder.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/GVTBuilder.java,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- GVTBuilder.java 2001/11/28 16:07:47 1.14 +++ GVTBuilder.java 2001/12/21 14:40:31 1.15 @@ -30,7 +30,7 @@ * This class is responsible for creating a GVT tree using an SVG DOM tree. * * @author <a href="mailto:[EMAIL PROTECTED]">Thierry Kormann</a> - * @version $Id: GVTBuilder.java,v 1.14 2001/11/28 16:07:47 tkormann Exp $ + * @version $Id: GVTBuilder.java,v 1.15 2001/12/21 14:40:31 hillion Exp $ */ public class GVTBuilder implements SVGConstants { @@ -88,7 +88,6 @@ } // <!> FIXME: TO BE REMOVED if (ctx.isDynamic()) { - BridgeEventSupport.loadScripts(ctx, svgElement); BridgeEventSupport.addGVTListener(ctx, svgElement); } return rootNode; @@ -125,7 +124,7 @@ // + may load the script twice (for example // outside 'use' is ok versus local 'use' maybe wrong). if (ctx.isDynamic()) { - BridgeEventSupport.loadScripts(ctx, e); + //BridgeEventSupport.loadScripts(ctx, e); } return gn; } 1.1 xml-batik/sources/org/apache/batik/bridge/RepaintManager.java Index: RepaintManager.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.batik.bridge; import org.apache.batik.gvt.UpdateTracker; /** * This class manages the rendering of a GVT tree. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> * @version $Id: RepaintManager.java,v 1.1 2001/12/21 14:40:31 hillion Exp $ */ public class RepaintManager extends Thread { /** * The associated UpdateManager. */ protected UpdateManager updateManager; /** * Creates a new repaint manager. */ public RepaintManager(UpdateManager um) { updateManager = um; setDaemon(true); } /** * The main method of this thread. */ public void run() { try { while (!Thread.currentThread().isInterrupted()) { final UpdateTracker ut = updateManager.getUpdateTracker(); if (ut.hasChanged()) { updateManager.getUpdateRunnableQueue().invokeAndWait(new Runnable() { public void run() { updateManager.updateRendering(ut.getDirtyArea()); ut.clear(); } }); } sleep(40); } } catch (InterruptedException e) { } } } 1.1 xml-batik/sources/org/apache/batik/bridge/UpdateManager.java Index: UpdateManager.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.batik.bridge; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.apache.batik.dom.DocumentWrapper; import org.apache.batik.dom.DOMImplementationWrapper; import org.apache.batik.gvt.UpdateTracker; import org.apache.batik.gvt.renderer.ImageRenderer; import org.apache.batik.util.RunnableQueue; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.svg.SVGSVGElement; import org.w3c.dom.events.DocumentEvent; import org.w3c.dom.events.Event; import org.w3c.dom.events.EventListener; import org.w3c.dom.events.EventTarget; import org.w3c.dom.events.MutationEvent; /** * This class provides features to manage the update of an SVG document. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> * @version $Id: UpdateManager.java,v 1.1 2001/12/21 14:40:31 hillion Exp $ */ public class UpdateManager implements RunnableQueue.RunHandler { /** * The bridge context. */ protected BridgeContext bridgeContext; /** * The document to manage. */ protected Document document; /** * The renderer used to paint. */ protected ImageRenderer renderer; /** * The document usable from the scripting thread. */ protected DocumentWrapper scriptingDocument; /** * The update RunnableQueue. */ protected RunnableQueue updateRunnableQueue; /** * The scripting RunnableQueue. */ protected RunnableQueue scriptingRunnableQueue; /** * The initial time. */ protected long initialTime; /** * The time elapsed in suspended state. */ protected long suspendedTime; /** * The starting time of the current pause. */ protected long suspendStartTime; /** * Whether the update manager is running. */ protected boolean running; /** * The listeners. */ protected List listeners = Collections.synchronizedList(new LinkedList()); /** * The starting time. */ protected long startingTime; /** * The repaint manager. */ protected RepaintManager repaintManager; /** * The update tracker. */ protected UpdateTracker updateTracker; /** * Creates a new update manager. * @param ctx The bridge context. * @param doc The document to manage. * @param r The renderer. */ public UpdateManager(BridgeContext ctx, Document doc, ImageRenderer r) { bridgeContext = ctx; bridgeContext.setUpdateManager(this); document = doc; renderer = r; updateRunnableQueue = RunnableQueue.createRunnableQueue(); scriptingRunnableQueue = RunnableQueue.createRunnableQueue(); updateRunnableQueue.setRunHandler(this); DOMImplementationWrapper iw; iw = new DOMImplementationWrapper(updateRunnableQueue, scriptingRunnableQueue, document.getImplementation()); scriptingDocument = new DocumentWrapper(iw, document); updateTracker = new UpdateTracker(); repaintManager = new RepaintManager(this); repaintManager.start(); } /** * Returns the update RunnableQueue. */ public RunnableQueue getUpdateRunnableQueue() { return updateRunnableQueue; } /** * Returns the scripting RunnableQueue. */ public RunnableQueue getScriptingRunnableQueue() { return scriptingRunnableQueue; } /** * Returns the repaint manager. */ public RepaintManager getRepaintManager() { return repaintManager; } /** * Returns the GVT update tracker. */ public UpdateTracker getUpdateTracker() { return updateTracker; } /** * Returns a Document usable from the scripting thread. */ public DocumentWrapper getScriptingDocument() { return scriptingDocument; } /** * Tells whether the update manager is currently running. */ public boolean isRunning() { return running; } /** * Returns the presentation time, in milliseconds. */ public long getPresentationTime() { if (running) { return System.currentTimeMillis() - initialTime - suspendedTime; } else { return suspendStartTime - initialTime - suspendedTime; } } /** * Suspends the update manager. */ public void suspend() { scriptingRunnableQueue.suspendExecution(true); updateRunnableQueue.suspendExecution(true); running = false; suspendStartTime = System.currentTimeMillis(); } /** * Resumes the update manager. */ public void resume() { scriptingRunnableQueue.resumeExecution(); updateRunnableQueue.resumeExecution(); running = true; suspendedTime = System.currentTimeMillis() - suspendStartTime; } /** * Dispatches an 'SVGLoad' event to the document. * NOTE: This method starts the update manager threads so one can't use * the update runnable queue to invoke this method. */ public void dispatchSVGLoad() { updateRunnableQueue.resumeExecution(); scriptingRunnableQueue.resumeExecution(); updateRunnableQueue.invokeLater(new Runnable() { public void run() { running = true; startingTime = System.currentTimeMillis(); fireManagerStartedEvent(); SVGSVGElement svgElement = (SVGSVGElement)document.getDocumentElement(); String language = svgElement.getContentScriptType(); BridgeEventSupport.loadScripts(bridgeContext, svgElement); BridgeEventSupport.dispatchOnLoad(bridgeContext, svgElement, language); } }); } /** * Dispatches an 'SVGUnLoad' event to the document. * This method interrupts the update manager threads. * NOTE: this method must be called outside the update thread. */ public void dispatchSVGUnLoad() { try { updateRunnableQueue.invokeAndWait(new Runnable() { public void run() { Event evt = ((DocumentEvent)document).createEvent("SVGEvents"); evt.initEvent("SVGUnload", false, false); ((EventTarget)(document.getDocumentElement())). dispatchEvent(evt); running = false; fireManagerStoppedEvent(); } }); } catch (InterruptedException e) { } repaintManager.interrupt(); scriptingRunnableQueue.getThread().interrupt(); updateRunnableQueue.getThread().interrupt(); } /** * Updates the rendering buffer. * @param u2d The user to device transform. * @param dbr Whether the double buffering should be used. * @param aoi The area of interest in the renderer space units. * @param width height The offscreen buffer size. */ public void updateRendering(AffineTransform u2d, boolean dbr, Shape aoi, int width, int height) { renderer.setTransform(u2d); renderer.setDoubleBuffered(dbr); renderer.updateOffScreen(width, height); renderer.clearOffScreen(); updateRendering(aoi); } /** * Updates the rendering buffer. * @param aoi The area of interest in the renderer space units. */ public void updateRendering(Shape aoi) { try { fireStartedEvent(renderer.getOffScreen()); renderer.repaint(aoi); Rectangle r = renderer.getTransform(). createTransformedShape(aoi).getBounds(); fireCompletedEvent(renderer.getOffScreen(), r); } catch (Exception e) { fireFailedEvent(); } } /** * Adds a UpdateManagerListener to this UpdateManager. */ public void addUpdateManagerListener(UpdateManagerListener l) { listeners.add(l); } /** * Removes a UpdateManagerListener from this UpdateManager. */ public void removeUpdateManagerListener(UpdateManagerListener l) { listeners.remove(l); } /** * Fires a UpdateManagerEvent to notify that the manager was started. */ protected void fireManagerStartedEvent() { Object[] dll = listeners.toArray(); if (dll.length > 0) { UpdateManagerEvent ev = new UpdateManagerEvent(this, null, null); for (int i = 0; i < dll.length; i++) { ((UpdateManagerListener)dll[i]).managerStarted(ev); } } } /** * Fires a UpdateManagerEvent to notify that the manager was stopped. */ protected void fireManagerStoppedEvent() { Object[] dll = listeners.toArray(); if (dll.length > 0) { UpdateManagerEvent ev = new UpdateManagerEvent(this, null, null); for (int i = 0; i < dll.length; i++) { ((UpdateManagerListener)dll[i]).managerStopped(ev); } } } /** * Fires a UpdateManagerEvent to notify that the manager was suspended. */ protected void fireManagerSuspendedEvent() { Object[] dll = listeners.toArray(); if (dll.length > 0) { UpdateManagerEvent ev = new UpdateManagerEvent(this, null, null); for (int i = 0; i < dll.length; i++) { ((UpdateManagerListener)dll[i]).managerSuspended(ev); } } } /** * Fires a UpdateManagerEvent to notify that the manager was resumed. */ protected void fireManagerResumedEvent() { Object[] dll = listeners.toArray(); if (dll.length > 0) { UpdateManagerEvent ev = new UpdateManagerEvent(this, null, null); for (int i = 0; i < dll.length; i++) { ((UpdateManagerListener)dll[i]).managerResumed(ev); } } } /** * Fires a UpdateManagerEvent in the starting phase of an update. */ protected void fireStartedEvent(BufferedImage bi) { Object[] dll = listeners.toArray(); if (dll.length > 0) { UpdateManagerEvent ev = new UpdateManagerEvent(this, bi, null); for (int i = 0; i < dll.length; i++) { ((UpdateManagerListener)dll[i]).updateStarted(ev); } } } /** * Fires a UpdateManagerEvent when an update completed. */ protected void fireCompletedEvent(BufferedImage bi, Rectangle r) { Object[] dll = listeners.toArray(); if (dll.length > 0) { UpdateManagerEvent ev = new UpdateManagerEvent(this, bi, r); for (int i = 0; i < dll.length; i++) { ((UpdateManagerListener)dll[i]).updateCompleted(ev); } } } /** * Fires a UpdateManagerEvent when an update failed. */ protected void fireFailedEvent() { Object[] dll = listeners.toArray(); if (dll.length > 0) { UpdateManagerEvent ev = new UpdateManagerEvent(this, null, null); for (int i = 0; i < dll.length; i++) { ((UpdateManagerListener)dll[i]).updateFailed(ev); } } } // RunnableQueue.RunHandler ///////////////////////////////////////// /** * Called when the given Runnable has just been invoked and * has returned. */ public void runnableInvoked(RunnableQueue rq, Runnable r) { } /** * Called when the execution of the queue has been suspended. */ public void executionSuspended(RunnableQueue rq) { fireManagerSuspendedEvent(); } /** * Called when the execution of the queue has been resumed. */ public void executionResumed(RunnableQueue rq) { fireManagerResumedEvent(); } // // // // // // // // !!! TODO: revisit // // // // // // // /** * To listen to the DOM mutation events. */ protected static class MutationListener implements EventListener { BridgeContext bridgeContext; public MutationListener(BridgeContext bridgeContext) { this.bridgeContext = bridgeContext; } public void handleEvent(Event evt) { BridgeMutationEvent bme; Element target = (Element)evt.getTarget(); bme = new BridgeMutationEvent (target, bridgeContext, BridgeMutationEvent.PROPERTY_MUTATION_TYPE); MutationEvent me = (MutationEvent)evt; bme.setAttrName(me.getAttrName()); bme.setAttrNewValue(me.getNewValue()); GraphicsNodeBridge bridge; bridge = (GraphicsNodeBridge)bridgeContext.getBridge(target); bridge.update(bme); } } } 1.1 xml-batik/sources/org/apache/batik/bridge/UpdateManagerEvent.java Index: UpdateManagerEvent.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.batik.bridge; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.util.EventObject; /** * This class represents an event which indicate an event originated * from a UpdateManager instance. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> * @version $Id: UpdateManagerEvent.java,v 1.1 2001/12/21 14:40:31 hillion Exp $ */ public class UpdateManagerEvent extends EventObject { /** * The buffered image. */ protected BufferedImage image; /** * The dirty area. */ protected Rectangle dirtyArea; /** * Creates a new UpdateManagerEvent. * @param source the object that originated the event, ie. the * UpdateManager. * @param bi the image to paint. * @param r The dirty area. */ public UpdateManagerEvent(Object source, BufferedImage bi, Rectangle r) { super(source); image = bi; dirtyArea = r; } /** * Returns the image to display, or null if the rendering failed. */ public BufferedImage getImage() { return image; } /** * Returns the dirty area. */ public Rectangle getDirtyArea() { return dirtyArea; } } 1.1 xml-batik/sources/org/apache/batik/bridge/UpdateManagerListener.java Index: UpdateManagerListener.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.batik.bridge; /** * This interface represents a listener to the UpdateManagerEvent events. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> * @version $Id: UpdateManagerListener.java,v 1.1 2001/12/21 14:40:31 hillion Exp $ */ public interface UpdateManagerListener { /** * Called when the manager was started. */ void managerStarted(UpdateManagerEvent e); /** * Called when the manager was suspended. */ void managerSuspended(UpdateManagerEvent e); /** * Called when the manager was resumed. */ void managerResumed(UpdateManagerEvent e); /** * Called when the manager was stopped. */ void managerStopped(UpdateManagerEvent e); /** * Called when an update started. */ void updateStarted(UpdateManagerEvent e); /** * Called when an update was completed. */ void updateCompleted(UpdateManagerEvent e); /** * Called when an update failed. */ void updateFailed(UpdateManagerEvent e); } 1.2 +27 -3 xml-batik/sources/org/apache/batik/dom/DOMImplementationWrapper.java Index: DOMImplementationWrapper.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/dom/DOMImplementationWrapper.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- DOMImplementationWrapper.java 2001/08/02 17:57:59 1.1 +++ DOMImplementationWrapper.java 2001/12/21 14:40:31 1.2 @@ -24,7 +24,7 @@ * of the underlying document are called in a single thread. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> - * @version $Id: DOMImplementationWrapper.java,v 1.1 2001/08/02 17:57:59 hillion Exp $ + * @version $Id: DOMImplementationWrapper.java,v 1.2 2001/12/21 14:40:31 hillion Exp $ */ public class DOMImplementationWrapper implements DOMImplementation { @@ -34,6 +34,11 @@ protected RunnableQueue runnableQueue; /** + * The RunnableQueue to use to run the event listeners. + */ + protected RunnableQueue listenersQueue; + + /** * The wrapped DOMImplementation object. */ protected DOMImplementation domImplementation; @@ -41,9 +46,16 @@ /** * Creates a new DOMImplementationWrapper associated with the given * RunnableQueue thread. - */ - public DOMImplementationWrapper(RunnableQueue rq, DOMImplementation di) { + * @param rq The main runnable queue. + * @param lq The RunnableQueue to use to run the event listeners. If + * null, the listeners are called from the main thread. + * @param di The DOMImplementation. + */ + public DOMImplementationWrapper(RunnableQueue rq, + RunnableQueue lq, + DOMImplementation di) { runnableQueue = rq; + listenersQueue = lq; domImplementation = di; } @@ -103,6 +115,18 @@ public Event createEventWrapper(DocumentWrapper dw, Event ev) throws DOMException { return new EventWrapper(dw, ev); + } + + /** + * Invokes the given Runnable from the event listeners RunnableQueue + * thread. + */ + public void invokeEventListener(Runnable r) { + if (listenersQueue == null) { + r.run(); + } else { + listenersQueue.invokeLater(r); + } } /** 1.3 +9 -1 xml-batik/sources/org/apache/batik/dom/DocumentWrapper.java Index: DocumentWrapper.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/dom/DocumentWrapper.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- DocumentWrapper.java 2001/11/09 02:37:11 1.2 +++ DocumentWrapper.java 2001/12/21 14:40:31 1.3 @@ -37,7 +37,7 @@ * of the underlying document are called in a single thread. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> - * @version $Id: DocumentWrapper.java,v 1.2 2001/11/09 02:37:11 deweese Exp $ + * @version $Id: DocumentWrapper.java,v 1.3 2001/12/21 14:40:31 hillion Exp $ */ public class DocumentWrapper extends NodeWrapper @@ -394,6 +394,14 @@ */ public void invokeLater(Runnable r) { domImplementationWrapper.invokeLater(r); + } + + /** + * Invokes the given Runnable from the event listeners RunnableQueue + * thread. + */ + public void invokeEventListener(Runnable r) { + domImplementationWrapper.invokeEventListener(r); } /** 1.2 +11 -7 xml-batik/sources/org/apache/batik/dom/events/EventListenerWrapper.java Index: EventListenerWrapper.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/dom/events/EventListenerWrapper.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- EventListenerWrapper.java 2001/08/02 17:58:00 1.1 +++ EventListenerWrapper.java 2001/12/21 14:40:31 1.2 @@ -20,7 +20,7 @@ * of the underlying document are called in a single thread. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> - * @version $Id: EventListenerWrapper.java,v 1.1 2001/08/02 17:58:00 hillion Exp $ + * @version $Id: EventListenerWrapper.java,v 1.2 2001/12/21 14:40:31 hillion Exp $ */ public class EventListenerWrapper implements EventListener { @@ -52,11 +52,15 @@ /** * <b>DOM</b>: Implements {@link EventListener#handleEvent(Event)}. */ - public void handleEvent(Event ev) { - if (ev instanceof EventWrapper) { - eventListener.handleEvent(ev); - } else { - eventListener.handleEvent(documentWrapper.createEventWrapper(ev)); - } + public void handleEvent(final Event ev) { + documentWrapper.invokeEventListener(new Runnable() { + public void run() { + Event e = ev; + if (!(ev instanceof EventWrapper)) { + e = documentWrapper.createEventWrapper(ev); + } + eventListener.handleEvent(e); + } + }); } } 1.1 xml-batik/sources/org/apache/batik/gvt/UpdateTracker.java Index: UpdateTracker.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.batik.gvt; import java.awt.Shape; /** * This class tracks the changes on a GVT tree * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> * @version $Id: UpdateTracker.java,v 1.1 2001/12/21 14:40:31 hillion Exp $ */ public class UpdateTracker { /** * Tells whether the GVT tree has changed. */ public boolean hasChanged() { return false; } /** * Returns the dirty area on GVT. */ public Shape getDirtyArea() { return null; } /** * Clears the tracker. */ public void clear() { } } 1.22 +83 -11 xml-batik/sources/org/apache/batik/swing/gvt/JGVTComponent.java Index: JGVTComponent.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/swing/gvt/JGVTComponent.java,v retrieving revision 1.21 retrieving revision 1.22 diff -u -r1.21 -r1.22 --- JGVTComponent.java 2001/10/15 09:33:44 1.21 +++ JGVTComponent.java 2001/12/21 14:40:31 1.22 @@ -53,7 +53,7 @@ * This class represents a component which can display a GVT tree. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> - * @version $Id: JGVTComponent.java,v 1.21 2001/10/15 09:33:44 tkormann Exp $ + * @version $Id: JGVTComponent.java,v 1.22 2001/12/21 14:40:31 hillion Exp $ */ public class JGVTComponent extends JComponent { @@ -549,7 +549,7 @@ } /** - * Renders the GVT tree. Used for the initial rendering and resize only. + * Renders the GVT tree. */ protected void renderGVTTree() { Dimension d = getSize(); @@ -784,10 +784,19 @@ if (interactor != null) { interactor.keyTyped(e); deselectInteractor(); + } else if (eventDispatcher != null) { + dispatchKeyTyped(e); } } /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchKeyTyped(KeyEvent e) { + eventDispatcher.keyTyped(e); + } + + /** * Invoked when a key has been pressed. */ public void keyPressed(KeyEvent e) { @@ -796,9 +805,16 @@ interactor.keyPressed(e); deselectInteractor(); } else if (eventDispatcher != null) { - eventDispatcher.keyReleased(e); + dispatchKeyPressed(e); } } + + /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchKeyPressed(KeyEvent e) { + eventDispatcher.keyPressed(e); + } /** * Invoked when a key has been released. @@ -809,10 +825,17 @@ interactor.keyReleased(e); deselectInteractor(); } else if (eventDispatcher != null) { - eventDispatcher.keyReleased(e); + dispatchKeyReleased(e); } } + /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchKeyReleased(KeyEvent e) { + eventDispatcher.keyReleased(e); + } + // MouseListener /////////////////////////////////////////////////////// /** @@ -824,11 +847,18 @@ interactor.mouseClicked(e); deselectInteractor(); } else if (eventDispatcher != null) { - eventDispatcher.mouseClicked(e); + dispatchMouseClicked(e); } } /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMouseClicked(MouseEvent e) { + eventDispatcher.mouseClicked(e); + } + + /** * Invoked when a mouse button has been pressed on a component. */ public void mousePressed(MouseEvent e) { @@ -837,11 +867,18 @@ interactor.mousePressed(e); deselectInteractor(); } else if (eventDispatcher != null) { - eventDispatcher.mousePressed(e); + dispatchMousePressed(e); } } /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMousePressed(MouseEvent e) { + eventDispatcher.mousePressed(e); + } + + /** * Invoked when a mouse button has been released on a component. */ public void mouseReleased(MouseEvent e) { @@ -850,11 +887,18 @@ interactor.mouseReleased(e); deselectInteractor(); } else if (eventDispatcher != null) { - eventDispatcher.mouseReleased(e); + dispatchMouseReleased(e); } } /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMouseReleased(MouseEvent e) { + eventDispatcher.mouseReleased(e); + } + + /** * Invoked when the mouse enters a component. */ public void mouseEntered(MouseEvent e) { @@ -863,11 +907,18 @@ interactor.mouseEntered(e); deselectInteractor(); } else if (eventDispatcher != null) { - eventDispatcher.mouseEntered(e); + dispatchMouseEntered(e); } } /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMouseEntered(MouseEvent e) { + eventDispatcher.mouseEntered(e); + } + + /** * Invoked when the mouse exits a component. */ public void mouseExited(MouseEvent e) { @@ -876,10 +927,17 @@ interactor.mouseExited(e); deselectInteractor(); } else if (eventDispatcher != null) { - eventDispatcher.mouseExited(e); + dispatchMouseExited(e); } } + /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMouseExited(MouseEvent e) { + eventDispatcher.mouseExited(e); + } + // MouseMotionListener ///////////////////////////////////////////////// /** @@ -895,11 +953,18 @@ interactor.mouseDragged(e); deselectInteractor(); } else if (eventDispatcher != null) { - eventDispatcher.mouseDragged(e); + dispatchMouseDragged(e); } } /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMouseDragged(MouseEvent e) { + eventDispatcher.mouseDragged(e); + } + + /** * Invoked when the mouse button has been moved on a component * (with no buttons no down). */ @@ -909,8 +974,15 @@ interactor.mouseMoved(e); deselectInteractor(); } else if (eventDispatcher != null) { - eventDispatcher.mouseMoved(e); + dispatchMouseMoved(e); } + } + + /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMouseMoved(MouseEvent e) { + eventDispatcher.mouseMoved(e); } /** 1.31 +253 -38 xml-batik/sources/org/apache/batik/swing/svg/JSVGComponent.java Index: JSVGComponent.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/swing/svg/JSVGComponent.java,v retrieving revision 1.30 retrieving revision 1.31 diff -u -r1.30 -r1.31 --- JSVGComponent.java 2001/11/14 09:15:25 1.30 +++ JSVGComponent.java 2001/12/21 14:40:32 1.31 @@ -10,11 +10,18 @@ import java.awt.Cursor; import java.awt.Dimension; +import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; + import java.awt.geom.AffineTransform; import java.awt.geom.Dimension2D; +import java.awt.geom.NoninvertibleTransformException; import java.net.MalformedURLException; import java.net.URL; @@ -32,11 +39,13 @@ import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.BridgeException; import org.apache.batik.bridge.BridgeExtension; -import org.apache.batik.bridge.BridgeMutationEvent; import org.apache.batik.bridge.DocumentLoader; import org.apache.batik.bridge.GraphicsNodeBridge; -import org.apache.batik.bridge.ViewBox; +import org.apache.batik.bridge.UpdateManager; +import org.apache.batik.bridge.UpdateManagerEvent; +import org.apache.batik.bridge.UpdateManagerListener; import org.apache.batik.bridge.UserAgent; +import org.apache.batik.bridge.ViewBox; import org.apache.batik.dom.util.XLinkSupport; @@ -59,11 +68,6 @@ import org.w3c.dom.svg.SVGDocument; import org.w3c.dom.svg.SVGSVGElement; -import org.w3c.dom.events.Event; -import org.w3c.dom.events.EventListener; -import org.w3c.dom.events.EventTarget; -import org.w3c.dom.events.MutationEvent; - /** * This class represents a swing component that can display SVG documents. This * component also lets you translate, zoom and rotate the document being @@ -153,7 +157,7 @@ * building/rendering a document (invalid XML file, missing attributes...).</p> * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> - * @version $Id: JSVGComponent.java,v 1.30 2001/11/14 09:15:25 tkormann Exp $ + * @version $Id: JSVGComponent.java,v 1.31 2001/12/21 14:40:32 hillion Exp $ */ public class JSVGComponent extends JGVTComponent { @@ -203,6 +207,11 @@ protected List linkActivationListeners = new LinkedList(); /** + * The update manager listeners. + */ + protected List updateManagerListeners = new LinkedList(); + + /** * The user agent. */ protected UserAgent userAgent; @@ -218,6 +227,11 @@ protected BridgeContext bridgeContext; /** + * The update manager. + */ + protected UpdateManager updateManager; + + /** * The current document fragment identifier. */ protected String fragmentIdentifier; @@ -246,6 +260,25 @@ addSVGDocumentLoaderListener((SVGListener)listener); addGVTTreeBuilderListener((SVGListener)listener); + addUpdateManagerListener((SVGListener)listener); + } + + /** + * Resumes the processing of the current document. + */ + public void resumeProcessing() { + if (updateManager != null) { + updateManager.resume(); + } + } + + /** + * Suspend the processing of the current document. + */ + public void suspendProcessing() { + if (updateManager != null) { + updateManager.suspend(); + } } /** @@ -259,6 +292,12 @@ documentLoader.interrupt(); } else if (gvtTreeBuilder != null) { gvtTreeBuilder.interrupt(); + } else if (updateManager != null) { + if (!updateManager.isRunning()) { + updateManager.resume(); + } + updateManager.dispatchSVGUnLoad(); + updateManager = null; } else { super.stopProcessing(); } @@ -323,11 +362,9 @@ throw new IllegalArgumentException("Invalid DOM implementation."); } - if (eventsEnabled && svgDocument != null) { - // fire the unload event - Event evt = svgDocument.createEvent("SVGEvents"); - evt.initEvent("SVGUnload", false, false); - ((EventTarget)(svgDocument.getRootElement())).dispatchEvent(evt); + if (eventsEnabled && svgDocument != null && updateManager != null) { + updateManager.dispatchSVGUnLoad(); + updateManager = null; } svgDocument = doc; @@ -401,7 +438,9 @@ if (loader == null) { loader = new DocumentLoader(userAgent); } - return new BridgeContext(userAgent, loader); + BridgeContext result = new BridgeContext(userAgent, loader); + result.setDynamic(true); + return result; } /** @@ -431,6 +470,39 @@ } /** + * Renders the GVT tree. + */ + protected void renderGVTTree() { + if (updateManager == null || !updateManager.isRunning()) { + super.renderGVTTree(); + return; + } + + final Dimension d = getSize(); + if (gvtRoot == null || d.width <= 0 || d.height <= 0) { + return; + } + + // Area of interest computation. + AffineTransform inv; + try { + inv = renderingTransform.createInverse(); + } catch (NoninvertibleTransformException e) { + throw new InternalError(e.getMessage()); + } + final Shape s = + inv.createTransformedShape(new Rectangle(0, 0, d.width, d.height)); + + updateManager.getUpdateRunnableQueue().invokeLater(new Runnable() { + public void run() { + updateManager.updateRendering(renderingTransform, + doubleBufferedRendering, + s, d.width, d.height); + } + }); + } + + /** * Handles an exception. */ protected void handleException(Exception e) { @@ -480,6 +552,20 @@ } /** + * Adds a UpdateManagerListener to this component. + */ + public void addUpdateManagerListener(UpdateManagerListener l) { + updateManagerListeners.add(l); + } + + /** + * Removes a UpdateManagerListener from this component. + */ + public void removeUpdateManagerListener(UpdateManagerListener l) { + updateManagerListeners.remove(l); + } + + /** * Creates an instance of Listener. */ protected Listener createListener() { @@ -492,7 +578,8 @@ protected class SVGListener extends Listener implements SVGDocumentLoaderListener, - GVTTreeBuilderListener { + GVTTreeBuilderListener, + UpdateManagerListener { /** * Creates a new SVGListener. @@ -655,11 +742,15 @@ } if (JSVGComponent.this.eventsEnabled) { - Event evt = svgDocument.createEvent("SVGEvents"); - evt.initEvent("SVGLoad", false, false); - ((EventTarget)(svgDocument.getRootElement())).dispatchEvent(evt); - ((EventTarget)svgDocument).addEventListener("DOMAttrModified", - new MutationListener(bridgeContext), false); + updateManager = new UpdateManager(bridgeContext, + svgDocument, + renderer); + Iterator it = updateManagerListeners.iterator(); + while (it.hasNext()) { + updateManager.addUpdateManagerListener + ((UpdateManagerListener)it.next()); + } + updateManager.dispatchSVGLoad(); } } @@ -695,34 +786,158 @@ } } + // UpdateManagerListener ////////////////////////////////////////// + /** - * To listener to the DOM mutation events. + * Called when the manager was started. */ - protected class MutationListener implements EventListener { + public void managerStarted(UpdateManagerEvent e) { + } - BridgeContext bridgeContext; + /** + * Called when the manager was suspended. + */ + public void managerSuspended(UpdateManagerEvent e) { + } - public MutationListener(BridgeContext bridgeContext) { - this.bridgeContext = bridgeContext; + /** + * Called when the manager was resumed. + */ + public void managerResumed(UpdateManagerEvent e) { + } + + /** + * Called when the manager was stopped. + */ + public void managerStopped(UpdateManagerEvent e) { + } + + /** + * Called when an update started. + */ + public void updateStarted(final UpdateManagerEvent e) { + EventQueue.invokeLater(new Runnable() { + public void run() { + paintingTransform = null; + if (!doubleBufferedRendering) { + image = e.getImage(); + } + } + }); + } + + /** + * Called when an update was completed. + */ + public void updateCompleted(final UpdateManagerEvent e) { + try { + EventQueue.invokeAndWait(new Runnable() { + public void run() { + image = e.getImage(); + paintImmediately(e.getDirtyArea()); + suspendInteractions = false; + } + }); + } catch (Exception ex) { + } + } + + /** + * Called when an update failed. + */ + public void updateFailed(UpdateManagerEvent e) { + } + + // Event propagation to GVT /////////////////////////////////////// + + /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMouseClicked(final MouseEvent e) { + if (updateManager != null && updateManager.isRunning()) { + updateManager.getUpdateRunnableQueue().invokeLater(new Runnable() { + public void run() { + eventDispatcher.mouseClicked(e); + } + }); + } + } + + /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMousePressed(final MouseEvent e) { + if (updateManager != null && updateManager.isRunning()) { + updateManager.getUpdateRunnableQueue().invokeLater(new Runnable() { + public void run() { + eventDispatcher.mousePressed(e); + } + }); } + } - public void handleEvent(Event evt) { - BridgeMutationEvent bme; - Element target = (Element)evt.getTarget(); - bme = new BridgeMutationEvent - (target, - bridgeContext, - BridgeMutationEvent.PROPERTY_MUTATION_TYPE); + /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMouseReleased(final MouseEvent e) { + if (updateManager != null && updateManager.isRunning()) { + updateManager.getUpdateRunnableQueue().invokeLater(new Runnable() { + public void run() { + eventDispatcher.mouseReleased(e); + } + }); + } + } - MutationEvent me = (MutationEvent)evt; + /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMouseEntered(final MouseEvent e) { + if (updateManager != null && updateManager.isRunning()) { + updateManager.getUpdateRunnableQueue().invokeLater(new Runnable() { + public void run() { + eventDispatcher.mouseEntered(e); + } + }); + } + } - bme.setAttrName(me.getAttrName()); - bme.setAttrNewValue(me.getNewValue()); + /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMouseExited(final MouseEvent e) { + if (updateManager != null && updateManager.isRunning()) { + updateManager.getUpdateRunnableQueue().invokeLater(new Runnable() { + public void run() { + eventDispatcher.mouseExited(e); + } + }); + } + } - GraphicsNodeBridge bridge; - bridge = (GraphicsNodeBridge)bridgeContext.getBridge(target); + /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMouseDragged(final MouseEvent e) { + if (updateManager != null && updateManager.isRunning()) { + updateManager.getUpdateRunnableQueue().invokeLater(new Runnable() { + public void run() { + eventDispatcher.mouseDragged(e); + } + }); + } + } - bridge.update(bme); + /** + * Dispatches the event to the GVT tree. + */ + protected void dispatchMouseMoved(final MouseEvent e) { + if (updateManager != null && updateManager.isRunning()) { + updateManager.getUpdateRunnableQueue().invokeLater(new Runnable() { + public void run() { + eventDispatcher.mouseMoved(e); + } + }); } } } 1.6 +4 -2 xml-batik/sources/org/apache/batik/util/RunnableQueue.java Index: RunnableQueue.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/util/RunnableQueue.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- RunnableQueue.java 2001/10/04 14:48:40 1.5 +++ RunnableQueue.java 2001/12/21 14:40:32 1.6 @@ -16,7 +16,7 @@ * invocation in a single thread. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> - * @version $Id: RunnableQueue.java,v 1.5 2001/10/04 14:48:40 deweese Exp $ + * @version $Id: RunnableQueue.java,v 1.6 2001/12/21 14:40:32 hillion Exp $ */ public class RunnableQueue implements Runnable { @@ -88,7 +88,9 @@ public static RunnableQueue createRunnableQueue() { RunnableQueue result = new RunnableQueue(); synchronized (result) { - new Thread(result).start(); + Thread t = new Thread(result); + t.setDaemon(true); + t.start(); while (result.getThread() == null) { try { result.wait();
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]