jdk/src/share/classes/javax/swing/DebugGraphics.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/javax/swing/DebugGraphics.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,1470 @@
+/*
+ * Copyright 1997-2004 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.swing;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.text.AttributedCharacterIterator;
+
+/**
+ * Graphics subclass supporting graphics debugging. Overrides most methods
+ * from Graphics.  DebugGraphics objects are rarely created by hand.  They
+ * are most frequently created automatically when a JComponent's
+ * debugGraphicsOptions are changed using the setDebugGraphicsOptions()
+ * method.
+ * <p>
+ * NOTE: You must turn off double buffering to use DebugGraphics:
+ *       RepaintManager repaintManager = RepaintManager.currentManager(component);
+ *       repaintManager.setDoubleBufferingEnabled(false);
+ *
+ * @see JComponent#setDebugGraphicsOptions
+ * @see RepaintManager#currentManager
+ * @see RepaintManager#setDoubleBufferingEnabled
+ *
+ * @author Dave Karlton
+ */
+public class DebugGraphics extends Graphics {
+    Graphics                    graphics;
+    Image                       buffer;
+    int                         debugOptions;
+    int                         graphicsID = graphicsCount++;
+    int                         xOffset, yOffset;
+    private static int          graphicsCount = 0;
+    private static ImageIcon    imageLoadingIcon = new ImageIcon();
+
+    /** Log graphics operations. */
+    public static final int     LOG_OPTION   = 1 << 0;
+    /** Flash graphics operations. */
+    public static final int     FLASH_OPTION = 1 << 1;
+    /** Show buffered operations in a separate <code>Frame</code>. */
+    public static final int     BUFFERED_OPTION = 1 << 2;
+    /** Don't debug graphics operations. */
+    public static final int     NONE_OPTION = -1;
+
+    static {
+        JComponent.DEBUG_GRAPHICS_LOADED = true;
+    }
+
+    /**
+     * Constructs a new debug graphics context that supports slowed
+     * down drawing.
+     */
+    public DebugGraphics() {
+        super();
+        buffer = null;
+        xOffset = yOffset = 0;
+    }
+
+    /**
+     * Constructs a debug graphics context from an existing graphics
+     * context that slows down drawing for the specified component.
+     *
+     * @param graphics  the Graphics context to slow down
+     * @param component the JComponent to draw slowly
+     */
+    public DebugGraphics(Graphics graphics, JComponent component) {
+        this(graphics);
+        setDebugOptions(component.shouldDebugGraphics());
+    }
+
+    /**
+     * Constructs a debug graphics context from an existing graphics
+     * context that supports slowed down drawing.
+     *
+     * @param graphics  the Graphics context to slow down
+     */
+    public DebugGraphics(Graphics graphics) {
+        this();
+        this.graphics = graphics;
+    }
+
+    /**
+     * Overrides <code>Graphics.create</code> to return a DebugGraphics object.
+     */
+    public Graphics create() {
+        DebugGraphics debugGraphics;
+
+        debugGraphics = new DebugGraphics();
+        debugGraphics.graphics = graphics.create();
+        debugGraphics.debugOptions = debugOptions;
+        debugGraphics.buffer = buffer;
+
+        return debugGraphics;
+    }
+
+    /**
+     * Overrides <code>Graphics.create</code> to return a DebugGraphics object.
+     */
+    public Graphics create(int x, int y, int width, int height) {
+        DebugGraphics debugGraphics;
+
+        debugGraphics = new DebugGraphics();
+        debugGraphics.graphics = graphics.create(x, y, width, height);
+        debugGraphics.debugOptions = debugOptions;
+        debugGraphics.buffer = buffer;
+        debugGraphics.xOffset = xOffset + x;
+        debugGraphics.yOffset = yOffset + y;
+
+        return debugGraphics;
+    }
+
+
+    //------------------------------------------------
+    //  NEW METHODS
+    //------------------------------------------------
+
+    /**
+     * Sets the Color used to flash drawing operations.
+     */
+    public static void setFlashColor(Color flashColor) {
+        info().flashColor = flashColor;
+    }
+
+    /**
+     * Returns the Color used to flash drawing operations.
+     * @see #setFlashColor
+     */
+    public static Color flashColor() {
+        return info().flashColor;
+    }
+
+    /**
+     * Sets the time delay of drawing operation flashing.
+     */
+    public static void setFlashTime(int flashTime) {
+        info().flashTime = flashTime;
+    }
+
+    /**
+     * Returns the time delay of drawing operation flashing.
+     * @see #setFlashTime
+     */
+    public static int flashTime() {
+        return info().flashTime;
+    }
+
+    /**
+     * Sets the number of times that drawing operations will flash.
+     */
+    public static void setFlashCount(int flashCount) {
+        info().flashCount = flashCount;
+    }
+
+    /** Returns the number of times that drawing operations will flash.
+      * @see #setFlashCount
+      */
+    public static int flashCount() {
+        return info().flashCount;
+    }
+
+    /** Sets the stream to which the DebugGraphics logs drawing operations.
+      */
+    public static void setLogStream(java.io.PrintStream stream) {
+        info().stream = stream;
+    }
+
+    /** Returns the stream to which the DebugGraphics logs drawing operations.
+      * @see #setLogStream
+      */
+    public static java.io.PrintStream logStream() {
+        return info().stream;
+    }
+
+    /** Sets the Font used for text drawing operations.
+      */
+    public void setFont(Font aFont) {
+        if (debugLog()) {
+            info().log(toShortString() + " Setting font: " + aFont);
+        }
+        graphics.setFont(aFont);
+    }
+
+    /** Returns the Font used for text drawing operations.
+      * @see #setFont
+      */
+    public Font getFont() {
+        return graphics.getFont();
+    }
+
+    /** Sets the color to be used for drawing and filling lines and shapes.
+      */
+    public void setColor(Color aColor) {
+        if (debugLog()) {
+            info().log(toShortString() + " Setting color: " + aColor);
+        }
+        graphics.setColor(aColor);
+    }
+
+    /** Returns the Color used for text drawing operations.
+      * @see #setColor
+      */
+    public Color getColor() {
+        return graphics.getColor();
+    }
+
+
+    //-----------------------------------------------
+    // OVERRIDDEN METHODS
+    //------------------------------------------------
+
+    /**
+     * Overrides <code>Graphics.getFontMetrics</code>.
+     */
+    public FontMetrics getFontMetrics() {
+        return graphics.getFontMetrics();
+    }
+
+    /**
+     * Overrides <code>Graphics.getFontMetrics</code>.
+     */
+    public FontMetrics getFontMetrics(Font f) {
+        return graphics.getFontMetrics(f);
+    }
+
+    /**
+     * Overrides <code>Graphics.translate</code>.
+     */
+    public void translate(int x, int y) {
+        if (debugLog()) {
+            info().log(toShortString() +
+                " Translating by: " + new Point(x, y));
+        }
+        xOffset += x;
+        yOffset += y;
+        graphics.translate(x, y);
+    }
+
+    /**
+     * Overrides <code>Graphics.setPaintMode</code>.
+     */
+    public void setPaintMode() {
+        if (debugLog()) {
+            info().log(toShortString() + " Setting paint mode");
+        }
+        graphics.setPaintMode();
+    }
+
+    /**
+     * Overrides <code>Graphics.setXORMode</code>.
+     */
+    public void setXORMode(Color aColor) {
+        if (debugLog()) {
+            info().log(toShortString() + " Setting XOR mode: " + aColor);
+        }
+        graphics.setXORMode(aColor);
+    }
+
+    /**
+     * Overrides <code>Graphics.getClipBounds</code>.
+     */
+    public Rectangle getClipBounds() {
+        return graphics.getClipBounds();
+    }
+
+    /**
+     * Overrides <code>Graphics.clipRect</code>.
+     */
+    public void clipRect(int x, int y, int width, int height) {
+        graphics.clipRect(x, y, width, height);
+        if (debugLog()) {
+            info().log(toShortString() +
+                " Setting clipRect: " + (new Rectangle(x, y, width, height)) +
+                " New clipRect: " + graphics.getClip());
+        }
+    }
+
+    /**
+     * Overrides <code>Graphics.setClip</code>.
+     */
+    public void setClip(int x, int y, int width, int height) {
+        graphics.setClip(x, y, width, height);
+        if (debugLog()) {
+            info().log(toShortString() +
+                        " Setting new clipRect: " + graphics.getClip());
+        }
+    }
+
+    /**
+     * Overrides <code>Graphics.getClip</code>.
+     */
+    public Shape getClip() {
+        return graphics.getClip();
+    }
+
+    /**
+     * Overrides <code>Graphics.setClip</code>.
+     */
+    public void setClip(Shape clip) {
+        graphics.setClip(clip);
+        if (debugLog()) {
+            info().log(toShortString() +
+                       " Setting new clipRect: " +  graphics.getClip());
+        }
+    }
+
+    /**
+     * Overrides <code>Graphics.drawRect</code>.
+     */
+    public void drawRect(int x, int y, int width, int height) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Drawing rect: " +
+                      new Rectangle(x, y, width, height));
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawRect(x, y, width, height);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.drawRect(x, y, width, height);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.drawRect(x, y, width, height);
+    }
+
+    /**
+     * Overrides <code>Graphics.fillRect</code>.
+     */
+    public void fillRect(int x, int y, int width, int height) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Filling rect: " +
+                      new Rectangle(x, y, width, height));
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.fillRect(x, y, width, height);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.fillRect(x, y, width, height);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.fillRect(x, y, width, height);
+    }
+
+    /**
+     * Overrides <code>Graphics.clearRect</code>.
+     */
+    public void clearRect(int x, int y, int width, int height) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Clearing rect: " +
+                      new Rectangle(x, y, width, height));
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.clearRect(x, y, width, height);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.clearRect(x, y, width, height);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.clearRect(x, y, width, height);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawRoundRect</code>.
+     */
+    public void drawRoundRect(int x, int y, int width, int height,
+                              int arcWidth, int arcHeight) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Drawing round rect: " +
+                      new Rectangle(x, y, width, height) +
+                      " arcWidth: " + arcWidth +
+                      " archHeight: " + arcHeight);
+        }
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawRoundRect(x, y, width, height,
+                                            arcWidth, arcHeight);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.drawRoundRect(x, y, width, height,
+                                       arcWidth, arcHeight);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
+    }
+
+    /**
+     * Overrides <code>Graphics.fillRoundRect</code>.
+     */
+    public void fillRoundRect(int x, int y, int width, int height,
+                              int arcWidth, int arcHeight) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Filling round rect: " +
+                      new Rectangle(x, y, width, height) +
+                      " arcWidth: " + arcWidth +
+                      " archHeight: " + arcHeight);
+        }
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.fillRoundRect(x, y, width, height,
+                                            arcWidth, arcHeight);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.fillRoundRect(x, y, width, height,
+                                       arcWidth, arcHeight);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawLine</code>.
+     */
+    public void drawLine(int x1, int y1, int x2, int y2) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                       " Drawing line: from " + pointToString(x1, y1) +
+                       " to " +  pointToString(x2, y2));
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawLine(x1, y1, x2, y2);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.drawLine(x1, y1, x2, y2);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.drawLine(x1, y1, x2, y2);
+    }
+
+    /**
+     * Overrides <code>Graphics.draw3DRect</code>.
+     */
+    public void draw3DRect(int x, int y, int width, int height,
+                           boolean raised) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                       " Drawing 3D rect: " +
+                       new Rectangle(x, y, width, height) +
+                       " Raised bezel: " + raised);
+        }
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.draw3DRect(x, y, width, height, raised);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.draw3DRect(x, y, width, height, raised);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.draw3DRect(x, y, width, height, raised);
+    }
+
+    /**
+     * Overrides <code>Graphics.fill3DRect</code>.
+     */
+    public void fill3DRect(int x, int y, int width, int height,
+                           boolean raised) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                       " Filling 3D rect: " +
+                       new Rectangle(x, y, width, height) +
+                       " Raised bezel: " + raised);
+        }
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.fill3DRect(x, y, width, height, raised);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.fill3DRect(x, y, width, height, raised);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.fill3DRect(x, y, width, height, raised);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawOval</code>.
+     */
+    public void drawOval(int x, int y, int width, int height) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Drawing oval: " +
+                      new Rectangle(x, y, width, height));
+        }
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawOval(x, y, width, height);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.drawOval(x, y, width, height);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.drawOval(x, y, width, height);
+    }
+
+    /**
+     * Overrides <code>Graphics.fillOval</code>.
+     */
+    public void fillOval(int x, int y, int width, int height) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Filling oval: " +
+                      new Rectangle(x, y, width, height));
+        }
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.fillOval(x, y, width, height);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.fillOval(x, y, width, height);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.fillOval(x, y, width, height);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawArc</code>.
+     */
+    public void drawArc(int x, int y, int width, int height,
+                        int startAngle, int arcAngle) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Drawing arc: " +
+                      new Rectangle(x, y, width, height) +
+                      " startAngle: " + startAngle +
+                      " arcAngle: " + arcAngle);
+        }
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawArc(x, y, width, height,
+                                      startAngle, arcAngle);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.drawArc(x, y, width, height, startAngle, arcAngle);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.drawArc(x, y, width, height, startAngle, arcAngle);
+    }
+
+    /**
+     * Overrides <code>Graphics.fillArc</code>.
+     */
+    public void fillArc(int x, int y, int width, int height,
+                        int startAngle, int arcAngle) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Filling arc: " +
+                      new Rectangle(x, y, width, height) +
+                      " startAngle: " + startAngle +
+                      " arcAngle: " + arcAngle);
+        }
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.fillArc(x, y, width, height,
+                                      startAngle, arcAngle);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.fillArc(x, y, width, height, startAngle, arcAngle);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.fillArc(x, y, width, height, startAngle, arcAngle);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawPolyline</code>.
+     */
+    public void drawPolyline(int xPoints[], int yPoints[], int nPoints) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Drawing polyline: " +
+                      " nPoints: " + nPoints +
+                      " X's: " + xPoints +
+                      " Y's: " + yPoints);
+        }
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawPolyline(xPoints, yPoints, nPoints);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.drawPolyline(xPoints, yPoints, nPoints);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.drawPolyline(xPoints, yPoints, nPoints);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawPolygon</code>.
+     */
+    public void drawPolygon(int xPoints[], int yPoints[], int nPoints) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Drawing polygon: " +
+                      " nPoints: " + nPoints +
+                      " X's: " + xPoints +
+                      " Y's: " + yPoints);
+        }
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawPolygon(xPoints, yPoints, nPoints);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.drawPolygon(xPoints, yPoints, nPoints);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.drawPolygon(xPoints, yPoints, nPoints);
+    }
+
+    /**
+     * Overrides <code>Graphics.fillPolygon</code>.
+     */
+    public void fillPolygon(int xPoints[], int yPoints[], int nPoints) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Filling polygon: " +
+                      " nPoints: " + nPoints +
+                      " X's: " + xPoints +
+                      " Y's: " + yPoints);
+        }
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.fillPolygon(xPoints, yPoints, nPoints);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
+                graphics.fillPolygon(xPoints, yPoints, nPoints);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.fillPolygon(xPoints, yPoints, nPoints);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawString</code>.
+     */
+    public void drawString(String aString, int x, int y) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                       " Drawing string: \"" + aString +
+                       "\" at: " + new Point(x, y));
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawString(aString, x, y);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor
+                                  : oldColor);
+                graphics.drawString(aString, x, y);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.drawString(aString, x, y);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawString</code>.
+     */
+    public void drawString(AttributedCharacterIterator iterator, int x, int y) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                       " Drawing text: \"" + iterator +
+                       "\" at: " + new Point(x, y));
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawString(iterator, x, y);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor
+                                  : oldColor);
+                graphics.drawString(iterator, x, y);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.drawString(iterator, x, y);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawBytes</code>.
+     */
+    public void drawBytes(byte data[], int offset, int length, int x, int y) {
+        DebugGraphicsInfo info = info();
+
+        Font font = graphics.getFont();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                       " Drawing bytes at: " + new Point(x, y));
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawBytes(data, offset, length, x, y);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor
+                                  : oldColor);
+                graphics.drawBytes(data, offset, length, x, y);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.drawBytes(data, offset, length, x, y);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawChars</code>.
+     */
+    public void drawChars(char data[], int offset, int length, int x, int y) {
+        DebugGraphicsInfo info = info();
+
+        Font font = graphics.getFont();
+
+        if (debugLog()) {
+            info().log(toShortString() +
+                       " Drawing chars at " +  new Point(x, y));
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawChars(data, offset, length, x, y);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            Color oldColor = getColor();
+            int i, count = (info.flashCount * 2) - 1;
+
+            for (i = 0; i < count; i++) {
+                graphics.setColor((i % 2) == 0 ? info.flashColor
+                                  : oldColor);
+                graphics.drawChars(data, offset, length, x, y);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+            graphics.setColor(oldColor);
+        }
+        graphics.drawChars(data, offset, length, x, y);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawImage</code>.
+     */
+    public boolean drawImage(Image img, int x, int y,
+                             ImageObserver observer) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info.log(toShortString() +
+                     " Drawing image: " + img +
+                     " at: " + new Point(x, y));
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawImage(img, x, y, observer);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            int i, count = (info.flashCount * 2) - 1;
+            ImageProducer oldProducer = img.getSource();
+            ImageProducer newProducer
+                = new FilteredImageSource(oldProducer,
+                                new DebugGraphicsFilter(info.flashColor));
+            Image newImage
+                = Toolkit.getDefaultToolkit().createImage(newProducer);
+            DebugGraphicsObserver imageObserver
+                = new DebugGraphicsObserver();
+
+            Image imageToDraw;
+            for (i = 0; i < count; i++) {
+                imageToDraw = (i % 2) == 0 ? newImage : img;
+                loadImage(imageToDraw);
+                graphics.drawImage(imageToDraw, x, y,
+                                   imageObserver);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+        }
+        return graphics.drawImage(img, x, y, observer);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawImage</code>.
+     */
+    public boolean drawImage(Image img, int x, int y, int width, int height,
+                             ImageObserver observer) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info.log(toShortString() +
+                     " Drawing image: " + img +
+                     " at: " + new Rectangle(x, y, width, height));
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawImage(img, x, y, width, height, observer);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            int i, count = (info.flashCount * 2) - 1;
+            ImageProducer oldProducer = img.getSource();
+            ImageProducer newProducer
+                = new FilteredImageSource(oldProducer,
+                                new DebugGraphicsFilter(info.flashColor));
+            Image newImage
+                = Toolkit.getDefaultToolkit().createImage(newProducer);
+            DebugGraphicsObserver imageObserver
+                = new DebugGraphicsObserver();
+
+            Image imageToDraw;
+            for (i = 0; i < count; i++) {
+                imageToDraw = (i % 2) == 0 ? newImage : img;
+                loadImage(imageToDraw);
+                graphics.drawImage(imageToDraw, x, y,
+                                   width, height, imageObserver);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+        }
+        return graphics.drawImage(img, x, y, width, height, observer);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawImage</code>.
+     */
+    public boolean drawImage(Image img, int x, int y,
+                             Color bgcolor,
+                             ImageObserver observer) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info.log(toShortString() +
+                     " Drawing image: " + img +
+                     " at: " + new Point(x, y) +
+                     ", bgcolor: " + bgcolor);
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawImage(img, x, y, bgcolor, observer);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            int i, count = (info.flashCount * 2) - 1;
+            ImageProducer oldProducer = img.getSource();
+            ImageProducer newProducer
+                = new FilteredImageSource(oldProducer,
+                                new DebugGraphicsFilter(info.flashColor));
+            Image newImage
+                = Toolkit.getDefaultToolkit().createImage(newProducer);
+            DebugGraphicsObserver imageObserver
+                = new DebugGraphicsObserver();
+
+            Image imageToDraw;
+            for (i = 0; i < count; i++) {
+                imageToDraw = (i % 2) == 0 ? newImage : img;
+                loadImage(imageToDraw);
+                graphics.drawImage(imageToDraw, x, y,
+                                   bgcolor, imageObserver);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+        }
+        return graphics.drawImage(img, x, y, bgcolor, observer);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawImage</code>.
+     */
+    public boolean drawImage(Image img, int x, int y,int width, int height,
+                             Color bgcolor,
+                             ImageObserver observer) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info.log(toShortString() +
+                     " Drawing image: " + img +
+                     " at: " + new Rectangle(x, y, width, height) +
+                     ", bgcolor: " + bgcolor);
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawImage(img, x, y, width, height,
+                                        bgcolor, observer);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            int i, count = (info.flashCount * 2) - 1;
+            ImageProducer oldProducer = img.getSource();
+            ImageProducer newProducer
+                = new FilteredImageSource(oldProducer,
+                                new DebugGraphicsFilter(info.flashColor));
+            Image newImage
+                = Toolkit.getDefaultToolkit().createImage(newProducer);
+            DebugGraphicsObserver imageObserver
+                = new DebugGraphicsObserver();
+
+            Image imageToDraw;
+            for (i = 0; i < count; i++) {
+                imageToDraw = (i % 2) == 0 ? newImage : img;
+                loadImage(imageToDraw);
+                graphics.drawImage(imageToDraw, x, y,
+                                   width, height, bgcolor, imageObserver);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+        }
+        return graphics.drawImage(img, x, y, width, height, bgcolor, observer);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawImage</code>.
+     */
+    public boolean drawImage(Image img,
+                             int dx1, int dy1, int dx2, int dy2,
+                             int sx1, int sy1, int sx2, int sy2,
+                             ImageObserver observer) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info.log(toShortString() +
+                     " Drawing image: " + img +
+                     " destination: " + new Rectangle(dx1, dy1, dx2, dy2) +
+                     " source: " + new Rectangle(sx1, sy1, sx2, sy2));
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawImage(img, dx1, dy1, dx2, dy2,
+                                        sx1, sy1, sx2, sy2, observer);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            int i, count = (info.flashCount * 2) - 1;
+            ImageProducer oldProducer = img.getSource();
+            ImageProducer newProducer
+                = new FilteredImageSource(oldProducer,
+                                new DebugGraphicsFilter(info.flashColor));
+            Image newImage
+                = Toolkit.getDefaultToolkit().createImage(newProducer);
+            DebugGraphicsObserver imageObserver
+                = new DebugGraphicsObserver();
+
+            Image imageToDraw;
+            for (i = 0; i < count; i++) {
+                imageToDraw = (i % 2) == 0 ? newImage : img;
+                loadImage(imageToDraw);
+                graphics.drawImage(imageToDraw,
+                                   dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
+                                   imageObserver);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+        }
+        return graphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
+                                  observer);
+    }
+
+    /**
+     * Overrides <code>Graphics.drawImage</code>.
+     */
+    public boolean drawImage(Image img,
+                             int dx1, int dy1, int dx2, int dy2,
+                             int sx1, int sy1, int sx2, int sy2,
+                             Color bgcolor,
+                             ImageObserver observer) {
+        DebugGraphicsInfo info = info();
+
+        if (debugLog()) {
+            info.log(toShortString() +
+                     " Drawing image: " + img +
+                     " destination: " + new Rectangle(dx1, dy1, dx2, dy2) +
+                     " source: " + new Rectangle(sx1, sy1, sx2, sy2) +
+                     ", bgcolor: " + bgcolor);
+        }
+
+        if (isDrawingBuffer()) {
+            if (debugBuffered()) {
+                Graphics debugGraphics = debugGraphics();
+
+                debugGraphics.drawImage(img, dx1, dy1, dx2, dy2,
+                                        sx1, sy1, sx2, sy2, bgcolor, observer);
+                debugGraphics.dispose();
+            }
+        } else if (debugFlash()) {
+            int i, count = (info.flashCount * 2) - 1;
+            ImageProducer oldProducer = img.getSource();
+            ImageProducer newProducer
+                = new FilteredImageSource(oldProducer,
+                                new DebugGraphicsFilter(info.flashColor));
+            Image newImage
+                = Toolkit.getDefaultToolkit().createImage(newProducer);
+            DebugGraphicsObserver imageObserver
+                = new DebugGraphicsObserver();
+
+            Image imageToDraw;
+            for (i = 0; i < count; i++) {
+                imageToDraw = (i % 2) == 0 ? newImage : img;
+                loadImage(imageToDraw);
+                graphics.drawImage(imageToDraw,
+                                   dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
+                                   bgcolor, imageObserver);
+                Toolkit.getDefaultToolkit().sync();
+                sleep(info.flashTime);
+            }
+        }
+        return graphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
+                                  bgcolor, observer);
+    }
+
+    static void loadImage(Image img) {
+        imageLoadingIcon.loadImage(img);
+    }
+
+
+    /**
+     * Overrides <code>Graphics.copyArea</code>.
+     */
+    public void copyArea(int x, int y, int width, int height,
+                         int destX, int destY) {
+        if (debugLog()) {
+            info().log(toShortString() +
+                      " Copying area from: " +
+                      new Rectangle(x, y, width, height) +
+                      " to: " + new Point(destX, destY));
+        }
+        graphics.copyArea(x, y, width, height, destX, destY);
+    }
+
+    final void sleep(int mSecs) {
+        try {
+            Thread.sleep(mSecs);
+        } catch (Exception e) {
+        }
+    }
+
+    /**
+     * Overrides <code>Graphics.dispose</code>.
+     */
+    public void dispose() {
+        graphics.dispose();
+        graphics = null;
+    }
+
+    // ALERT!
+    /**
+     * Returns the drawingBuffer value.
+     *
+     * @return true if this object is drawing from a Buffer
+     */
+    public boolean isDrawingBuffer() {
+        return buffer != null;
+    }
+
+    String toShortString() {
+        StringBuffer buffer = new StringBuffer("Graphics" + (isDrawingBuffer() ? "<B>" : "") + "(" + graphicsID + "-" + debugOptions + ")");
+        return buffer.toString();
+    }
+
+    String pointToString(int x, int y) {
+        StringBuffer buffer = new StringBuffer("(" + x + ", " + y + ")");
+        return buffer.toString();
+    }
+
+    /** Enables/disables diagnostic information about every graphics
+      * operation. The value of <b>options</b> indicates how this information
+      * should be displayed. LOG_OPTION causes a text message to be printed.
+      * FLASH_OPTION causes the drawing to flash several times. BUFFERED_OPTION
+      * creates a new Frame that shows each operation on an
+      * offscreen buffer. The value of <b>options</b> is bitwise OR'd into
+      * the current value. To disable debugging use NONE_OPTION.
+      */
+    public void setDebugOptions(int options) {
+        if (options != 0) {
+            if (options == NONE_OPTION) {
+                if (debugOptions != 0) {
+                    System.err.println(toShortString() + " Disabling debug");
+                    debugOptions = 0;
+                }
+            } else {
+                if (debugOptions != options) {
+                    debugOptions |= options;
+                    if (debugLog()) {
+                        System.err.println(toShortString() + " Enabling debug");
+                    }
+                }
+            }
+        }
+    }
+
+    /** Returns the current debugging options for this DebugGraphics.
+      * @see #setDebugOptions
+      */
+    public int getDebugOptions() {
+        return debugOptions;
+    }
+
+    /** Static wrapper method for DebugGraphicsInfo.setDebugOptions(). Stores
+      * options on a per component basis.
+      */
+    static void setDebugOptions(JComponent component, int options) {
+        info().setDebugOptions(component, options);
+    }
+
+    /** Static wrapper method for DebugGraphicsInfo.getDebugOptions().
+      */
+    static int getDebugOptions(JComponent component) {
+        DebugGraphicsInfo debugGraphicsInfo = info();
+        if (debugGraphicsInfo == null) {
+            return 0;
+        } else {
+            return debugGraphicsInfo.getDebugOptions(component);
+        }
+    }
+
+    /** Returns non-zero if <b>component</b> should display with DebugGraphics,
+      * zero otherwise. Walks the JComponent's parent tree to determine if
+      * any debugging options have been set.
+      */
+    static int shouldComponentDebug(JComponent component) {
+        DebugGraphicsInfo info = info();
+        if (info == null) {
+            return 0;
+        } else {
+            Container container = (Container)component;
+            int debugOptions = 0;
+
+            while (container != null && (container instanceof JComponent)) {
+                debugOptions |= info.getDebugOptions((JComponent)container);
+                container = container.getParent();
+            }
+
+            return debugOptions;
+        }
+    }
+
+    /** Returns the number of JComponents that have debugging options turned
+      * on.
+      */
+    static int debugComponentCount() {
+        DebugGraphicsInfo debugGraphicsInfo = info();
+        if (debugGraphicsInfo != null &&
+                    debugGraphicsInfo.componentToDebug != null) {
+            return debugGraphicsInfo.componentToDebug.size();
+        } else {
+            return 0;
+        }
+    }
+
+    boolean debugLog() {
+        return (debugOptions & LOG_OPTION) == LOG_OPTION;
+    }
+
+    boolean debugFlash() {
+        return (debugOptions & FLASH_OPTION) == FLASH_OPTION;
+    }
+
+    boolean debugBuffered() {
+        return (debugOptions & BUFFERED_OPTION) == BUFFERED_OPTION;
+    }
+
+    /** Returns a DebugGraphics for use in buffering window.
+      */
+    private Graphics debugGraphics() {
+        DebugGraphics        debugGraphics;
+        DebugGraphicsInfo    info = info();
+        JFrame               debugFrame;
+
+        if (info.debugFrame == null) {
+            info.debugFrame = new JFrame();
+            info.debugFrame.setSize(500, 500);
+        }
+        debugFrame = info.debugFrame;
+        debugFrame.show();
+        debugGraphics = new DebugGraphics(debugFrame.getGraphics());
+        debugGraphics.setFont(getFont());
+        debugGraphics.setColor(getColor());
+        debugGraphics.translate(xOffset, yOffset);
+        debugGraphics.setClip(getClipBounds());
+        if (debugFlash()) {
+            debugGraphics.setDebugOptions(FLASH_OPTION);
+        }
+        return debugGraphics;
+    }
+
+    /** Returns DebugGraphicsInfo, or creates one if none exists.
+      */
+    static DebugGraphicsInfo info() {
+        DebugGraphicsInfo debugGraphicsInfo = (DebugGraphicsInfo)
+            SwingUtilities.appContextGet(debugGraphicsInfoKey);
+        if (debugGraphicsInfo == null) {
+            debugGraphicsInfo = new DebugGraphicsInfo();
+            SwingUtilities.appContextPut(debugGraphicsInfoKey,
+                                         debugGraphicsInfo);
+        }
+        return debugGraphicsInfo;
+    }
+    private static final Class debugGraphicsInfoKey = DebugGraphicsInfo.class;
+
+
+}