/*

   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.

 */
package org.apache.batik.bridge;

import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.util.Collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.batik.bridge.svg12.DefaultXBLManager;
import org.apache.batik.bridge.svg12.SVG12BridgeContext;
import org.apache.batik.bridge.svg12.SVG12ScriptingEnvironment;
import org.apache.batik.dom.events.AbstractEvent;
import org.apache.batik.dom.svg.SVGOMDocument;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.RootGraphicsNode;
import org.apache.batik.gvt.UpdateTracker;
import org.apache.batik.gvt.renderer.ImageRenderer;
import org.apache.batik.util.EventDispatcher;
import org.apache.batik.util.XMLConstants;
import org.apache.batik.util.EventDispatcher.Dispatcher;
import org.apache.batik.util.RunnableQueue;
import org.w3c.dom.Document;
import org.w3c.dom.events.DocumentEvent;
import org.w3c.dom.events.EventTarget;

/**
 * This class provides features to manage the update of an SVG document.
 *
 * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
 * @version $Id$
 */
public class UpdateManager  {

    static final int MIN_REPAINT_TIME;
    static {
        int value = 20;
        try {
            String s = System.getProperty
            ("org.apache.batik.min_repaint_time", "20");
            value = Integer.parseInt(s);
        } catch (SecurityException se) {
        } catch (NumberFormatException nfe){
        } finally {
            MIN_REPAINT_TIME = value;
        }
    }

    /**
     * The bridge context.
     */
    protected BridgeContext bridgeContext;

    /**
     * The document to manage.
     */
    protected Document document;

    /**
     * The update RunnableQueue.
     */
    protected RunnableQueue updateRunnableQueue;

    /**
     * The RunHandler for the RunnableQueue.
     */
    protected RunnableQueue.RunHandler runHandler;

    /**
     * Whether the update manager is running.
     */
    protected volatile boolean running;

    /**
     * Whether the suspend() method was called.
     */
    protected volatile boolean suspendCalled;

    /**
     * The listeners.
     */
    protected List listeners = Collections.synchronizedList(new LinkedList());

    /**
     * The scripting environment.
     */
    protected ScriptingEnvironment scriptingEnvironment;

    /**
     * The repaint manager.
     */
    protected RepaintManager repaintManager;

    /**
     * The update tracker.
     */
    protected UpdateTracker updateTracker;

    /**
     * The GraphicsNode whose updates are to be tracked.
     */
    protected GraphicsNode graphicsNode;

    /**
     * Whether the manager was started.
     */
    protected boolean started;

    /**
     * Array of resource documents' BridgeContexts.
     */
    protected BridgeContext[] secondaryBridgeContexts;

    /**
     * Array of resource documents' ScriptingEnvironments that should
     * have their SVGLoad event dispatched.
     */
    protected ScriptingEnvironment[] secondaryScriptingEnvironments;

    /**
     * The current minRepaintTime
     */
    protected int minRepaintTime;

    /**
     * Creates a new update manager.
     * @param ctx The bridge context.
     * @param gn GraphicsNode whose updates are to be tracked.
     * @param doc The document to manage.
     */
    public UpdateManager(BridgeContext ctx,
                         GraphicsNode gn,
                         Document doc) {
        bridgeContext = ctx;
        bridgeContext.setUpdateManager(this);

        document = doc;

        updateRunnableQueue = RunnableQueue.createRunnableQueue();
        runHandler = createRunHandler();
        updateRunnableQueue.setRunHandler(runHandler);

        graphicsNode = gn;

        scriptingEnvironment = initializeScriptingEnvironment(bridgeContext);

        // Any BridgeContexts for resource documents that exist
        // when initializing the scripting environment for the
        // primary document also need to have their scripting
        // environments initialized.
        secondaryBridgeContexts =
            (BridgeContext[]) ctx.getChildContexts().clone();
        secondaryScriptingEnvironments =
            new ScriptingEnvironment[secondaryBridgeContexts.length];
        for (int i = 0; i < secondaryBridgeContexts.length; i++) {
            BridgeContext resCtx = secondaryBridgeContexts[i];
            if (!((SVGOMDocument) resCtx.getDocument()).isSVG12()) {
                continue;
            }
            resCtx.setUpdateManager(this);
            ScriptingEnvironment se = initializeScriptingEnvironment(resCtx);
            secondaryScriptingEnvironments[i] = se;
        }
        minRepaintTime = MIN_REPAINT_TIME;
    }

    public int getMinRepaintTime() {
        return minRepaintTime;
    }

    public void setMinRepaintTime(int minRepaintTime) {
        this.minRepaintTime = minRepaintTime;
    }

    /**
     * Creates an appropriate ScriptingEnvironment and XBL manager for
     * the given document.
     */
    protected ScriptingEnvironment initializeScriptingEnvironment
            (BridgeContext ctx) {
        SVGOMDocument d = (SVGOMDocument) ctx.getDocument();
        ScriptingEnvironment se;
        if (d.isSVG12()) {
            se = new SVG12ScriptingEnvironment(ctx);
            ctx.xblManager = new DefaultXBLManager(d, ctx);
            d.setXBLManager(ctx.xblManager);
        } else {
            se = new ScriptingEnvironment(ctx);
        }
        return se;
    }

    /**
     * Dispatches an 'SVGLoad' event to the document.
     */
    public synchronized void dispatchSVGLoadEvent()
            throws InterruptedException {
        dispatchSVGLoadEvent(bridgeContext, scriptingEnvironment);
        for (int i = 0; i < secondaryScriptingEnvironments.length; i++) {
            BridgeContext ctx = secondaryBridgeContexts[i];
            if (!((SVGOMDocument) ctx.getDocument()).isSVG12()) {
                continue;
            }
            ScriptingEnvironment se = secondaryScriptingEnvironments[i];
            dispatchSVGLoadEvent(ctx, se);
        }
        secondaryBridgeContexts = null;
        secondaryScriptingEnvironments = null;
    }

    /**
     * Dispatches an 'SVGLoad' event to the document.
     */
    protected void dispatchSVGLoadEvent(BridgeContext ctx,
                                        ScriptingEnvironment se) {
        se.loadScripts();
        se.dispatchSVGLoadEvent();
        if (ctx.isSVG12() && ctx.xblManager != null) {
            SVG12BridgeContext ctx12 = (SVG12BridgeContext) ctx;
            ctx12.addBindingListener();
            ctx12.xblManager.startProcessing();
        }
    }

    /**
     * Dispatches an "SVGZoom" event to the document.
     */
    public void dispatchSVGZoomEvent()
        throws InterruptedException {
        scriptingEnvironment.dispatchSVGZoomEvent();
    }

    /**
     * Dispatches an "SVGZoom" event to the document.
     */
    public void dispatchSVGScrollEvent()
        throws InterruptedException {
        scriptingEnvironment.dispatchSVGScrollEvent();
    }

    /**
     * Dispatches an "SVGZoom" event to the document.
     */
    public void dispatchSVGResizeEvent()
        throws InterruptedException {
        scriptingEnvironment.dispatchSVGResizeEvent();
    }

    /**
     * Finishes the UpdateManager initialization.
     */
    public void manageUpdates(final ImageRenderer r) {
        updateRunnableQueue.preemptLater(new Runnable() {
                public void run() {
                    synchronized (UpdateManager.this) {
                        running = true;

                        updateTracker = new UpdateTracker();
                        RootGraphicsNode root = graphicsNode.getRoot();
                        if (root != null){
                            root.addTreeGraphicsNodeChangeListener
                                (updateTracker);
                        }

                        repaintManager = new RepaintManager(r);

                        // Send the UpdateManagerStarted event.
                        UpdateManagerEvent ev = new UpdateManagerEvent
                            (UpdateManager.this, null, null);
                        fireEvent(startedDispatcher, ev);
                        started = true;
                    }
                }
            });
        resume();
    }


    /**
     * Returns the bridge context.
     */
    public BridgeContext getBridgeContext() {
        return bridgeContext;
    }

    /**
     * Returns the update RunnableQueue.
     */
    public RunnableQueue getUpdateRunnableQueue() {
        return updateRunnableQueue;
    }

    /**
     * Returns the repaint manager.
     */
    public RepaintManager getRepaintManager() {
        return repaintManager;
    }

    /**
     * Returns the GVT update tracker.
     */
    public UpdateTracker getUpdateTracker() {
        return updateTracker;
    }

    /**
     * Returns the current Document.
     */
    public Document getDocument() {
        return document;
    }

    /**
     * Returns the scripting environment.
     */
    public ScriptingEnvironment getScriptingEnvironment() {
        return scriptingEnvironment;
    }

    /**
     * Tells whether the update manager is currently running.
     */
    public synchronized boolean isRunning() {
        return running;
    }

    /**
     * Suspends the update manager.
     */
    public synchronized void suspend() {
        // System.err.println("Suspend: " + suspendCalled + " : " + running);
        if (updateRunnableQueue.getQueueState() == RunnableQueue.RUNNING) {
            updateRunnableQueue.suspendExecution(false);
        }
        suspendCalled = true;
    }

    /**
     * Resumes the update manager.
     */
    public synchronized void resume() {
        // System.err.println("Resume: " + suspendCalled + " : " + running);

        // if (suspendCalled) {
        //     UpdateManagerEvent ev = new UpdateManagerEvent
        //         (this, null, null);
        //     // FIXX: Must happen in a different thread!
        //     fireEvent(suspendedDispatcher, ev);
        //     fireEvent(resumedDispatcher, ev);
        // }
        if (updateRunnableQueue.getQueueState() != RunnableQueue.RUNNING) {
            updateRunnableQueue.resumeExecution();
        }
    }

    /**
     * Interrupts the manager tasks.
     */
    public void interrupt() {
        Runnable r = new Runnable() {
                public void run() {
                    synchronized (UpdateManager.this) {
                        if (started) {
                            dispatchSVGUnLoadEvent();
                        } else {
                            running = false;
                            scriptingEnvironment.interrupt();
                            updateRunnableQueue.getThread().halt();
                        }
                    }
                }
            };
        try {
            // Preempt to cancel the pending tasks
            updateRunnableQueue.preemptLater(r);
            updateRunnableQueue.resumeExecution(); // ensure runnable runs...
        } catch (IllegalStateException ise) {
            // Not running, which is probably ok since that's what we
            // wanted.  Might be an issue if SVGUnload wasn't issued...
        }
    }

    /**
     * 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 dispatchSVGUnLoadEvent() {
        if (!started) {
            throw new IllegalStateException("UpdateManager not started.");
        }

        // Invoke first to cancel the pending tasks
        updateRunnableQueue.preemptLater(new Runnable() {
                public void run() {
                    synchronized (UpdateManager.this) {
                        AbstractEvent evt = (AbstractEvent)
                            ((DocumentEvent)document).createEvent("SVGEvents");
                        String type;
                        if (bridgeContext.isSVG12()) {
                            type = "unload";
                        } else {
                            type = "SVGUnload";
                        }
                        evt.initEventNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
                                        type,
                                        false,    // canBubbleArg
                                        false);   // cancelableArg
                        ((EventTarget)(document.getDocumentElement())).
                            dispatchEvent(evt);
                        running = false;

                        // Now shut everything down and disconnect
                        // everything before we send the
                        // UpdateMangerStopped event.
                        scriptingEnvironment.interrupt();
                        updateRunnableQueue.getThread().halt();
                        bridgeContext.dispose();

                        // Send the UpdateManagerStopped event.
                        UpdateManagerEvent ev = new UpdateManagerEvent
                            (UpdateManager.this, null, null);
                        fireEvent(stoppedDispatcher, ev);
                    }
                }
            });
        resume();
    }

    /**
     * Updates the rendering buffer.  Only to be called from the
     * update thread.
     * @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 The offscreen buffer width.
     * @param height The offscreen buffer height.
     */
    public void updateRendering(AffineTransform u2d,
                                boolean dbr,
                                Shape aoi,
                                int width,
                                int height) {
        repaintManager.setupRenderer(u2d,dbr,aoi,width,height);
        List l = new ArrayList(1);
        l.add(aoi);
        updateRendering(l, false);
    }

    /**
     * Updates the rendering buffer.  Only to be called from the
     * update thread.
     * @param u2d The user to device transform.
     * @param dbr Whether the double buffering should be used.
     * @param cpt If the canvas painting transform should be cleared
     *            when the update complets
     * @param aoi The area of interest in the renderer space units.
     * @param width The offscreen buffer width.
     * @param height The offscreen buffer height.
     */
    public void updateRendering(AffineTransform u2d,
                                boolean dbr,
                                boolean cpt,
                                Shape aoi,
                                int width,
                                int height) {
        repaintManager.setupRenderer(u2d,dbr,aoi,width,height);
        List l = new ArrayList(1);
        l.add(aoi);
        updateRendering(l, cpt);
    }

    /**
     * Updates the rendering buffer.
     * @param areas List of areas of interest in rederer space units.
     * @param clearPaintingTransform Indicates if the painting transform
     *        should be cleared as a result of this update.
     */
    protected void updateRendering(List areas,
                                   boolean clearPaintingTransform) {
        try {
            UpdateManagerEvent ev = new UpdateManagerEvent
                (this, repaintManager.getOffScreen(), null);
            fireEvent(updateStartedDispatcher, ev);

            Collection c = repaintManager.updateRendering(areas);
            List l = new ArrayList(c);

            ev = new UpdateManagerEvent
                (this, repaintManager.getOffScreen(),
                 l, clearPaintingTransform);
            fireEvent(updateCompletedDispatcher, ev);
        } catch (ThreadDeath td) {
            UpdateManagerEvent ev = new UpdateManagerEvent
                (this, null, null);
            fireEvent(updateFailedDispatcher, ev);
            throw td;
        } catch (Throwable t) {
            UpdateManagerEvent ev = new UpdateManagerEvent
                (this, null, null);
            fireEvent(updateFailedDispatcher, ev);
        }
    }

    /**
     * This tracks when the rendering first got 'out of date'
     * with respect to the document.
     */
    long outOfDateTime=0;

    /**
     * Repaints the dirty areas, if needed.
     */
    protected void repaint() {
        if (!updateTracker.hasChanged()) {
            // No changes, nothing to repaint.
            outOfDateTime = 0;
            return;
        }

        long ctime = System.currentTimeMillis();
        if (ctime < allResumeTime) {
            createRepaintTimer();
            return;
        }
        if (allResumeTime > 0) {
            // All suspendRedraw requests have expired.
            releaseAllRedrawSuspension();
        }

        if (ctime-outOfDateTime < minRepaintTime) {
            // We very recently did a repaint check if other
            // repaint runnables are pending.
            synchronized (updateRunnableQueue.getIteratorLock()) {
                Iterator i = updateRunnableQueue.iterator();
                while (i.hasNext())
                    if (!(i.next() instanceof NoRepaintRunnable))
                        // have a pending repaint runnable so we
                        // will skip this repaint and we will let
                        // the next one pick it up.
                        return;

            }
        }

        List dirtyAreas = updateTracker.getDirtyAreas();
        updateTracker.clear();
        if (dirtyAreas != null) {
            updateRendering(dirtyAreas, false);
        }
        outOfDateTime = 0;
    }

    /**
     * Users of Batik should essentially never call
     * this directly from Java.  If the Canvas is not
     * updating when you change the SVG Document it is almost
     * certainly because you are not making your changes
     * in the RunnableQueue (getUpdateRunnableQueue()).
     * You will have problems if you are not making all
     * changes to the document in the UpdateManager's
     * RunnableQueue.
     *
     * This method exists to implement the
     * 'SVGSVGElement.forceRedraw()' method.
     */
    public void forceRepaint() {
        if (!updateTracker.hasChanged()) {
            // No changes, nothing to repaint.
            outOfDateTime = 0;
            return;
        }

        List dirtyAreas = updateTracker.getDirtyAreas();
        updateTracker.clear();
        if (dirtyAreas != null) {
            updateRendering(dirtyAreas, false);
        }
        outOfDateTime = 0;
    }

    protected class SuspensionInfo {
        /**
         * The index of this redraw suspension
         */
        int index;
        /**
         * The system time in millisec that this suspension
         * will expire and redraws can resume (at least for
         * this suspension.
         */
        long resumeMilli;
        public SuspensionInfo(int index, long resumeMilli) {
            this.index = index;
            this.resumeMilli = resumeMilli;
        }
        public int getIndex() { return index; }
        public long getResumeMilli() { return resumeMilli; }
    }

    protected class RepaintTimerTask extends TimerTask {
        UpdateManager um;
        RepaintTimerTask(UpdateManager um) {
            this.um = um;
        }
        public void run() {
            RunnableQueue rq = um.getUpdateRunnableQueue();
            if (rq == null) return;
            rq.invokeLater(new Runnable() {
                    public void run() { }
                });
        }
    }

    List suspensionList = new ArrayList();
    int nextSuspensionIndex = 1;
    long allResumeTime = -1;
    Timer repaintTriggerTimer = null;
    TimerTask repaintTimerTask = null;

    void createRepaintTimer() {
        if (repaintTimerTask != null) return;
        if (allResumeTime < 0)        return;
        if (repaintTriggerTimer == null)
            repaintTriggerTimer = new Timer(true);

        long delay = allResumeTime - System.currentTimeMillis();
        if (delay < 0) delay = 0;
        repaintTimerTask = new RepaintTimerTask(this);
        repaintTriggerTimer.schedule(repaintTimerTask, delay);
        // System.err.println("CTimer delay: " + delay);
    }
    /**
     * Sets up a timer that will trigger a repaint
     * when it fires.
     * If create is true it will construct a timer even
     * if one
     */
    void resetRepaintTimer() {
        if (repaintTimerTask == null) return;
        if (allResumeTime < 0)        return;
        if (repaintTriggerTimer == null)
            repaintTriggerTimer = new Timer(true);

        long delay = allResumeTime - System.currentTimeMillis();
        if (delay < 0) delay = 0;
        repaintTimerTask = new RepaintTimerTask(this);
        repaintTriggerTimer.schedule(repaintTimerTask, delay);
        // System.err.println("Timer delay: " + delay);
    }

    int addRedrawSuspension(int max_wait_milliseconds) {
        long resumeTime = System.currentTimeMillis() + max_wait_milliseconds;
        SuspensionInfo si = new SuspensionInfo(nextSuspensionIndex++,
                                               resumeTime);
        if (resumeTime > allResumeTime) {
            allResumeTime = resumeTime;
            // System.err.println("Added AllRes Time: " + allResumeTime);
            resetRepaintTimer();
        }
        suspensionList.add(si);
        return si.getIndex();
    }

    void releaseAllRedrawSuspension() {
        suspensionList.clear();
        allResumeTime = -1;
        resetRepaintTimer();
    }

    boolean releaseRedrawSuspension(int index) {
        if (index > nextSuspensionIndex) return false;
        if (suspensionList.size() == 0) return true;

        int lo = 0, hi=suspensionList.size()-1;
        while (lo < hi) {
            int mid = (lo+hi)>>1;
            SuspensionInfo si = (SuspensionInfo)suspensionList.get(mid);
            int idx = si.getIndex();
            if      (idx == index) { lo = hi = mid; }
            else if (idx <  index) { lo = mid+1; }
            else                   { hi = mid-1; }
        }

        SuspensionInfo si = (SuspensionInfo)suspensionList.get(lo);
        int idx = si.getIndex();
        if (idx != index)
            return true;  // currently not in list but was at some point...

        suspensionList.remove(lo);
        if (suspensionList.size() == 0) {
            // No more active suspensions
            allResumeTime = -1;
            resetRepaintTimer();
        } else {
            // Check if we need to find a new 'bounding' suspension.
            long resumeTime = si.getResumeMilli();
            if (resumeTime == allResumeTime) {
                allResumeTime = findNewAllResumeTime();
                // System.err.println("New AllRes Time: " + allResumeTime);
                resetRepaintTimer();
            }
        }
        return true;
    }

    long findNewAllResumeTime() {
        long ret = -1;
        Iterator i = suspensionList.iterator();
        while (i.hasNext()) {
            SuspensionInfo si = (SuspensionInfo)i.next();
            long t = si.getResumeMilli();
            if (t > ret) ret = t;
        }
        return ret;
    }

    /**
     * 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);
    }

    protected void fireEvent(Dispatcher dispatcher, Object event) {
        EventDispatcher.fireEvent(dispatcher, listeners, event, false);
    }


    /**
     * Dispatches a UpdateManagerEvent to notify that the manager was
     * started
     */
    static Dispatcher startedDispatcher = new Dispatcher() {
            public void dispatch(Object listener,
                                 Object event) {
                ((UpdateManagerListener)listener).managerStarted
                    ((UpdateManagerEvent)event);
            }
        };

    /**
     * Dispatches a UpdateManagerEvent to notify that the manager was
     * stopped.
     */
    static Dispatcher stoppedDispatcher = new Dispatcher() {
            public void dispatch(Object listener,
                                 Object event) {
                ((UpdateManagerListener)listener).managerStopped
                    ((UpdateManagerEvent)event);
            }
        };

    /**
     * Dispatches a UpdateManagerEvent to notify that the manager was
     * suspended.
     */
    static Dispatcher suspendedDispatcher = new Dispatcher() {
            public void dispatch(Object listener,
                                 Object event) {
                ((UpdateManagerListener)listener).managerSuspended
                    ((UpdateManagerEvent)event);
            }
        };

    /**
     * Dispatches a UpdateManagerEvent to notify that the manager was
     * resumed.
     */
    static Dispatcher resumedDispatcher = new Dispatcher() {
            public void dispatch(Object listener,
                                 Object event) {
                ((UpdateManagerListener)listener).managerResumed
                    ((UpdateManagerEvent)event);
            }
        };

    /**
     * Dispatches a UpdateManagerEvent to notify that an update
     * started
     */
    static Dispatcher updateStartedDispatcher = new Dispatcher() {
            public void dispatch(Object listener,
                                 Object event) {
                ((UpdateManagerListener)listener).updateStarted
                    ((UpdateManagerEvent)event);
            }
        };

    /**
     * Dispatches a UpdateManagerEvent to notify that an update
     * completed
     */
    static Dispatcher updateCompletedDispatcher = new Dispatcher() {
            public void dispatch(Object listener,
                                 Object event) {
                ((UpdateManagerListener)listener).updateCompleted
                    ((UpdateManagerEvent)event);
            }
        };

    /**
     * Dispatches a UpdateManagerEvent to notify that an update
     * failed
     */
    static Dispatcher updateFailedDispatcher = new Dispatcher() {
            public void dispatch(Object listener,
                                 Object event) {
                ((UpdateManagerListener)listener).updateFailed
                    ((UpdateManagerEvent)event);
            }
        };



    // RunnableQueue.RunHandler /////////////////////////////////////////
    protected RunnableQueue.RunHandler createRunHandler() {
        return new UpdateManagerRunHander();
    }

    protected class UpdateManagerRunHander
        extends RunnableQueue.RunHandlerAdapter {

        public void runnableStart(RunnableQueue rq, Runnable r) {
            if (running && !(r instanceof NoRepaintRunnable)) {
                // Mark the document as updated when the
                // runnable starts.
                if (outOfDateTime == 0)
                    outOfDateTime = System.currentTimeMillis();
            }
        }


        /**
         * Called when the given Runnable has just been invoked and
         * has returned.
         */
        public void runnableInvoked(RunnableQueue rq, Runnable r) {
            if (running && !(r instanceof NoRepaintRunnable)) {
                repaint();
            }
        }

        /**
         * Called when the execution of the queue has been suspended.
         */
        public void executionSuspended(RunnableQueue rq) {
            synchronized (UpdateManager.this) {
                // System.err.println("Suspended: " + suspendCalled);
                if (suspendCalled) {
                    running = false;
                    UpdateManagerEvent ev = new UpdateManagerEvent
                        (this, null, null);
                    fireEvent(suspendedDispatcher, ev);
                }
            }
        }

        /**
         * Called when the execution of the queue has been resumed.
         */
        public void executionResumed(RunnableQueue rq) {
            synchronized (UpdateManager.this) {
                // System.err.println("Resumed: " + suspendCalled +
                //                    " : " + running);
                if (suspendCalled && !running) {
                    running = true;
                    suspendCalled = false;

                    UpdateManagerEvent ev = new UpdateManagerEvent
                        (this, null, null);
                    fireEvent(resumedDispatcher, ev);
                }
            }
        }
    }
}
