1 /*
   2  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.swing;
  27 
  28 import java.awt.*;
  29 import java.awt.image.*;
  30 import java.text.AttributedCharacterIterator;
  31 
  32 /**
  33  * Graphics subclass supporting graphics debugging. Overrides most methods
  34  * from Graphics.  DebugGraphics objects are rarely created by hand.  They
  35  * are most frequently created automatically when a JComponent's
  36  * debugGraphicsOptions are changed using the setDebugGraphicsOptions()
  37  * method.
  38  * <p>
  39  * NOTE: You must turn off double buffering to use DebugGraphics:
  40  *       RepaintManager repaintManager = RepaintManager.currentManager(component);
  41  *       repaintManager.setDoubleBufferingEnabled(false);
  42  *
  43  * @see JComponent#setDebugGraphicsOptions
  44  * @see RepaintManager#currentManager
  45  * @see RepaintManager#setDoubleBufferingEnabled
  46  *
  47  * @author Dave Karlton
  48  * @since 1.2
  49  */
  50 public class DebugGraphics extends Graphics {
  51     Graphics                    graphics;
  52     Image                       buffer;
  53     int                         debugOptions;
  54     int                         graphicsID = graphicsCount++;
  55     int                         xOffset, yOffset;
  56     private static int          graphicsCount = 0;
  57     private static ImageIcon    imageLoadingIcon = new ImageIcon();
  58 
  59     /** Log graphics operations. */
  60     public static final int     LOG_OPTION   = 1 << 0;
  61     /** Flash graphics operations. */
  62     public static final int     FLASH_OPTION = 1 << 1;
  63     /** Show buffered operations in a separate <code>Frame</code>. */
  64     public static final int     BUFFERED_OPTION = 1 << 2;
  65     /** Don't debug graphics operations. */
  66     public static final int     NONE_OPTION = -1;
  67 
  68     static {
  69         JComponent.DEBUG_GRAPHICS_LOADED = true;
  70     }
  71 
  72     /**
  73      * Constructs a new debug graphics context that supports slowed
  74      * down drawing.
  75      */
  76     public DebugGraphics() {
  77         super();
  78         buffer = null;
  79         xOffset = yOffset = 0;
  80     }
  81 
  82     /**
  83      * Constructs a debug graphics context from an existing graphics
  84      * context that slows down drawing for the specified component.
  85      *
  86      * @param graphics  the Graphics context to slow down
  87      * @param component the JComponent to draw slowly
  88      */
  89     public DebugGraphics(Graphics graphics, JComponent component) {
  90         this(graphics);
  91         setDebugOptions(component.shouldDebugGraphics());
  92     }
  93 
  94     /**
  95      * Constructs a debug graphics context from an existing graphics
  96      * context that supports slowed down drawing.
  97      *
  98      * @param graphics  the Graphics context to slow down
  99      */
 100     public DebugGraphics(Graphics graphics) {
 101         this();
 102         this.graphics = graphics;
 103     }
 104 
 105     /**
 106      * Overrides <code>Graphics.create</code> to return a DebugGraphics object.
 107      */
 108     public Graphics create() {
 109         DebugGraphics debugGraphics;
 110 
 111         debugGraphics = new DebugGraphics();
 112         debugGraphics.graphics = graphics.create();
 113         debugGraphics.debugOptions = debugOptions;
 114         debugGraphics.buffer = buffer;
 115 
 116         return debugGraphics;
 117     }
 118 
 119     /**
 120      * Overrides <code>Graphics.create</code> to return a DebugGraphics object.
 121      */
 122     public Graphics create(int x, int y, int width, int height) {
 123         DebugGraphics debugGraphics;
 124 
 125         debugGraphics = new DebugGraphics();
 126         debugGraphics.graphics = graphics.create(x, y, width, height);
 127         debugGraphics.debugOptions = debugOptions;
 128         debugGraphics.buffer = buffer;
 129         debugGraphics.xOffset = xOffset + x;
 130         debugGraphics.yOffset = yOffset + y;
 131 
 132         return debugGraphics;
 133     }
 134 
 135 
 136     //------------------------------------------------
 137     //  NEW METHODS
 138     //------------------------------------------------
 139 
 140     /**
 141      * Sets the Color used to flash drawing operations.
 142      */
 143     public static void setFlashColor(Color flashColor) {
 144         info().flashColor = flashColor;
 145     }
 146 
 147     /**
 148      * Returns the Color used to flash drawing operations.
 149      * @see #setFlashColor
 150      */
 151     public static Color flashColor() {
 152         return info().flashColor;
 153     }
 154 
 155     /**
 156      * Sets the time delay of drawing operation flashing.
 157      */
 158     public static void setFlashTime(int flashTime) {
 159         info().flashTime = flashTime;
 160     }
 161 
 162     /**
 163      * Returns the time delay of drawing operation flashing.
 164      * @see #setFlashTime
 165      */
 166     public static int flashTime() {
 167         return info().flashTime;
 168     }
 169 
 170     /**
 171      * Sets the number of times that drawing operations will flash.
 172      */
 173     public static void setFlashCount(int flashCount) {
 174         info().flashCount = flashCount;
 175     }
 176 
 177     /** Returns the number of times that drawing operations will flash.
 178       * @see #setFlashCount
 179       */
 180     public static int flashCount() {
 181         return info().flashCount;
 182     }
 183 
 184     /** Sets the stream to which the DebugGraphics logs drawing operations.
 185       */
 186     public static void setLogStream(java.io.PrintStream stream) {
 187         info().stream = stream;
 188     }
 189 
 190     /** Returns the stream to which the DebugGraphics logs drawing operations.
 191       * @see #setLogStream
 192       */
 193     public static java.io.PrintStream logStream() {
 194         return info().stream;
 195     }
 196 
 197     /** Sets the Font used for text drawing operations.
 198       */
 199     public void setFont(Font aFont) {
 200         if (debugLog()) {
 201             info().log(toShortString() + " Setting font: " + aFont);
 202         }
 203         graphics.setFont(aFont);
 204     }
 205 
 206     /** Returns the Font used for text drawing operations.
 207       * @see #setFont
 208       */
 209     public Font getFont() {
 210         return graphics.getFont();
 211     }
 212 
 213     /** Sets the color to be used for drawing and filling lines and shapes.
 214       */
 215     public void setColor(Color aColor) {
 216         if (debugLog()) {
 217             info().log(toShortString() + " Setting color: " + aColor);
 218         }
 219         graphics.setColor(aColor);
 220     }
 221 
 222     /** Returns the Color used for text drawing operations.
 223       * @see #setColor
 224       */
 225     public Color getColor() {
 226         return graphics.getColor();
 227     }
 228 
 229 
 230     //-----------------------------------------------
 231     // OVERRIDDEN METHODS
 232     //------------------------------------------------
 233 
 234     /**
 235      * Overrides <code>Graphics.getFontMetrics</code>.
 236      */
 237     public FontMetrics getFontMetrics() {
 238         return graphics.getFontMetrics();
 239     }
 240 
 241     /**
 242      * Overrides <code>Graphics.getFontMetrics</code>.
 243      */
 244     public FontMetrics getFontMetrics(Font f) {
 245         return graphics.getFontMetrics(f);
 246     }
 247 
 248     /**
 249      * Overrides <code>Graphics.translate</code>.
 250      */
 251     public void translate(int x, int y) {
 252         if (debugLog()) {
 253             info().log(toShortString() +
 254                 " Translating by: " + new Point(x, y));
 255         }
 256         xOffset += x;
 257         yOffset += y;
 258         graphics.translate(x, y);
 259     }
 260 
 261     /**
 262      * Overrides <code>Graphics.setPaintMode</code>.
 263      */
 264     public void setPaintMode() {
 265         if (debugLog()) {
 266             info().log(toShortString() + " Setting paint mode");
 267         }
 268         graphics.setPaintMode();
 269     }
 270 
 271     /**
 272      * Overrides <code>Graphics.setXORMode</code>.
 273      */
 274     public void setXORMode(Color aColor) {
 275         if (debugLog()) {
 276             info().log(toShortString() + " Setting XOR mode: " + aColor);
 277         }
 278         graphics.setXORMode(aColor);
 279     }
 280 
 281     /**
 282      * Overrides <code>Graphics.getClipBounds</code>.
 283      */
 284     public Rectangle getClipBounds() {
 285         return graphics.getClipBounds();
 286     }
 287 
 288     /**
 289      * Overrides <code>Graphics.clipRect</code>.
 290      */
 291     public void clipRect(int x, int y, int width, int height) {
 292         graphics.clipRect(x, y, width, height);
 293         if (debugLog()) {
 294             info().log(toShortString() +
 295                 " Setting clipRect: " + (new Rectangle(x, y, width, height)) +
 296                 " New clipRect: " + graphics.getClip());
 297         }
 298     }
 299 
 300     /**
 301      * Overrides <code>Graphics.setClip</code>.
 302      */
 303     public void setClip(int x, int y, int width, int height) {
 304         graphics.setClip(x, y, width, height);
 305         if (debugLog()) {
 306             info().log(toShortString() +
 307                         " Setting new clipRect: " + graphics.getClip());
 308         }
 309     }
 310 
 311     /**
 312      * Overrides <code>Graphics.getClip</code>.
 313      */
 314     public Shape getClip() {
 315         return graphics.getClip();
 316     }
 317 
 318     /**
 319      * Overrides <code>Graphics.setClip</code>.
 320      */
 321     public void setClip(Shape clip) {
 322         graphics.setClip(clip);
 323         if (debugLog()) {
 324             info().log(toShortString() +
 325                        " Setting new clipRect: " +  graphics.getClip());
 326         }
 327     }
 328 
 329     /**
 330      * Overrides <code>Graphics.drawRect</code>.
 331      */
 332     public void drawRect(int x, int y, int width, int height) {
 333         DebugGraphicsInfo info = info();
 334 
 335         if (debugLog()) {
 336             info().log(toShortString() +
 337                       " Drawing rect: " +
 338                       new Rectangle(x, y, width, height));
 339         }
 340 
 341         if (isDrawingBuffer()) {
 342             if (debugBuffered()) {
 343                 Graphics debugGraphics = debugGraphics();
 344 
 345                 debugGraphics.drawRect(x, y, width, height);
 346                 debugGraphics.dispose();
 347             }
 348         } else if (debugFlash()) {
 349             Color oldColor = getColor();
 350             int i, count = (info.flashCount * 2) - 1;
 351 
 352             for (i = 0; i < count; i++) {
 353                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 354                 graphics.drawRect(x, y, width, height);
 355                 Toolkit.getDefaultToolkit().sync();
 356                 sleep(info.flashTime);
 357             }
 358             graphics.setColor(oldColor);
 359         }
 360         graphics.drawRect(x, y, width, height);
 361     }
 362 
 363     /**
 364      * Overrides <code>Graphics.fillRect</code>.
 365      */
 366     public void fillRect(int x, int y, int width, int height) {
 367         DebugGraphicsInfo info = info();
 368 
 369         if (debugLog()) {
 370             info().log(toShortString() +
 371                       " Filling rect: " +
 372                       new Rectangle(x, y, width, height));
 373         }
 374 
 375         if (isDrawingBuffer()) {
 376             if (debugBuffered()) {
 377                 Graphics debugGraphics = debugGraphics();
 378 
 379                 debugGraphics.fillRect(x, y, width, height);
 380                 debugGraphics.dispose();
 381             }
 382         } else if (debugFlash()) {
 383             Color oldColor = getColor();
 384             int i, count = (info.flashCount * 2) - 1;
 385 
 386             for (i = 0; i < count; i++) {
 387                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 388                 graphics.fillRect(x, y, width, height);
 389                 Toolkit.getDefaultToolkit().sync();
 390                 sleep(info.flashTime);
 391             }
 392             graphics.setColor(oldColor);
 393         }
 394         graphics.fillRect(x, y, width, height);
 395     }
 396 
 397     /**
 398      * Overrides <code>Graphics.clearRect</code>.
 399      */
 400     public void clearRect(int x, int y, int width, int height) {
 401         DebugGraphicsInfo info = info();
 402 
 403         if (debugLog()) {
 404             info().log(toShortString() +
 405                       " Clearing rect: " +
 406                       new Rectangle(x, y, width, height));
 407         }
 408 
 409         if (isDrawingBuffer()) {
 410             if (debugBuffered()) {
 411                 Graphics debugGraphics = debugGraphics();
 412 
 413                 debugGraphics.clearRect(x, y, width, height);
 414                 debugGraphics.dispose();
 415             }
 416         } else if (debugFlash()) {
 417             Color oldColor = getColor();
 418             int i, count = (info.flashCount * 2) - 1;
 419 
 420             for (i = 0; i < count; i++) {
 421                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 422                 graphics.clearRect(x, y, width, height);
 423                 Toolkit.getDefaultToolkit().sync();
 424                 sleep(info.flashTime);
 425             }
 426             graphics.setColor(oldColor);
 427         }
 428         graphics.clearRect(x, y, width, height);
 429     }
 430 
 431     /**
 432      * Overrides <code>Graphics.drawRoundRect</code>.
 433      */
 434     public void drawRoundRect(int x, int y, int width, int height,
 435                               int arcWidth, int arcHeight) {
 436         DebugGraphicsInfo info = info();
 437 
 438         if (debugLog()) {
 439             info().log(toShortString() +
 440                       " Drawing round rect: " +
 441                       new Rectangle(x, y, width, height) +
 442                       " arcWidth: " + arcWidth +
 443                       " archHeight: " + arcHeight);
 444         }
 445         if (isDrawingBuffer()) {
 446             if (debugBuffered()) {
 447                 Graphics debugGraphics = debugGraphics();
 448 
 449                 debugGraphics.drawRoundRect(x, y, width, height,
 450                                             arcWidth, arcHeight);
 451                 debugGraphics.dispose();
 452             }
 453         } else if (debugFlash()) {
 454             Color oldColor = getColor();
 455             int i, count = (info.flashCount * 2) - 1;
 456 
 457             for (i = 0; i < count; i++) {
 458                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 459                 graphics.drawRoundRect(x, y, width, height,
 460                                        arcWidth, arcHeight);
 461                 Toolkit.getDefaultToolkit().sync();
 462                 sleep(info.flashTime);
 463             }
 464             graphics.setColor(oldColor);
 465         }
 466         graphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
 467     }
 468 
 469     /**
 470      * Overrides <code>Graphics.fillRoundRect</code>.
 471      */
 472     public void fillRoundRect(int x, int y, int width, int height,
 473                               int arcWidth, int arcHeight) {
 474         DebugGraphicsInfo info = info();
 475 
 476         if (debugLog()) {
 477             info().log(toShortString() +
 478                       " Filling round rect: " +
 479                       new Rectangle(x, y, width, height) +
 480                       " arcWidth: " + arcWidth +
 481                       " archHeight: " + arcHeight);
 482         }
 483         if (isDrawingBuffer()) {
 484             if (debugBuffered()) {
 485                 Graphics debugGraphics = debugGraphics();
 486 
 487                 debugGraphics.fillRoundRect(x, y, width, height,
 488                                             arcWidth, arcHeight);
 489                 debugGraphics.dispose();
 490             }
 491         } else if (debugFlash()) {
 492             Color oldColor = getColor();
 493             int i, count = (info.flashCount * 2) - 1;
 494 
 495             for (i = 0; i < count; i++) {
 496                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 497                 graphics.fillRoundRect(x, y, width, height,
 498                                        arcWidth, arcHeight);
 499                 Toolkit.getDefaultToolkit().sync();
 500                 sleep(info.flashTime);
 501             }
 502             graphics.setColor(oldColor);
 503         }
 504         graphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
 505     }
 506 
 507     /**
 508      * Overrides <code>Graphics.drawLine</code>.
 509      */
 510     public void drawLine(int x1, int y1, int x2, int y2) {
 511         DebugGraphicsInfo info = info();
 512 
 513         if (debugLog()) {
 514             info().log(toShortString() +
 515                        " Drawing line: from " + pointToString(x1, y1) +
 516                        " to " +  pointToString(x2, y2));
 517         }
 518 
 519         if (isDrawingBuffer()) {
 520             if (debugBuffered()) {
 521                 Graphics debugGraphics = debugGraphics();
 522 
 523                 debugGraphics.drawLine(x1, y1, x2, y2);
 524                 debugGraphics.dispose();
 525             }
 526         } else if (debugFlash()) {
 527             Color oldColor = getColor();
 528             int i, count = (info.flashCount * 2) - 1;
 529 
 530             for (i = 0; i < count; i++) {
 531                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 532                 graphics.drawLine(x1, y1, x2, y2);
 533                 Toolkit.getDefaultToolkit().sync();
 534                 sleep(info.flashTime);
 535             }
 536             graphics.setColor(oldColor);
 537         }
 538         graphics.drawLine(x1, y1, x2, y2);
 539     }
 540 
 541     /**
 542      * Overrides <code>Graphics.draw3DRect</code>.
 543      */
 544     public void draw3DRect(int x, int y, int width, int height,
 545                            boolean raised) {
 546         DebugGraphicsInfo info = info();
 547 
 548         if (debugLog()) {
 549             info().log(toShortString() +
 550                        " Drawing 3D rect: " +
 551                        new Rectangle(x, y, width, height) +
 552                        " Raised bezel: " + raised);
 553         }
 554         if (isDrawingBuffer()) {
 555             if (debugBuffered()) {
 556                 Graphics debugGraphics = debugGraphics();
 557 
 558                 debugGraphics.draw3DRect(x, y, width, height, raised);
 559                 debugGraphics.dispose();
 560             }
 561         } else if (debugFlash()) {
 562             Color oldColor = getColor();
 563             int i, count = (info.flashCount * 2) - 1;
 564 
 565             for (i = 0; i < count; i++) {
 566                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 567                 graphics.draw3DRect(x, y, width, height, raised);
 568                 Toolkit.getDefaultToolkit().sync();
 569                 sleep(info.flashTime);
 570             }
 571             graphics.setColor(oldColor);
 572         }
 573         graphics.draw3DRect(x, y, width, height, raised);
 574     }
 575 
 576     /**
 577      * Overrides <code>Graphics.fill3DRect</code>.
 578      */
 579     public void fill3DRect(int x, int y, int width, int height,
 580                            boolean raised) {
 581         DebugGraphicsInfo info = info();
 582 
 583         if (debugLog()) {
 584             info().log(toShortString() +
 585                        " Filling 3D rect: " +
 586                        new Rectangle(x, y, width, height) +
 587                        " Raised bezel: " + raised);
 588         }
 589         if (isDrawingBuffer()) {
 590             if (debugBuffered()) {
 591                 Graphics debugGraphics = debugGraphics();
 592 
 593                 debugGraphics.fill3DRect(x, y, width, height, raised);
 594                 debugGraphics.dispose();
 595             }
 596         } else if (debugFlash()) {
 597             Color oldColor = getColor();
 598             int i, count = (info.flashCount * 2) - 1;
 599 
 600             for (i = 0; i < count; i++) {
 601                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 602                 graphics.fill3DRect(x, y, width, height, raised);
 603                 Toolkit.getDefaultToolkit().sync();
 604                 sleep(info.flashTime);
 605             }
 606             graphics.setColor(oldColor);
 607         }
 608         graphics.fill3DRect(x, y, width, height, raised);
 609     }
 610 
 611     /**
 612      * Overrides <code>Graphics.drawOval</code>.
 613      */
 614     public void drawOval(int x, int y, int width, int height) {
 615         DebugGraphicsInfo info = info();
 616 
 617         if (debugLog()) {
 618             info().log(toShortString() +
 619                       " Drawing oval: " +
 620                       new Rectangle(x, y, width, height));
 621         }
 622         if (isDrawingBuffer()) {
 623             if (debugBuffered()) {
 624                 Graphics debugGraphics = debugGraphics();
 625 
 626                 debugGraphics.drawOval(x, y, width, height);
 627                 debugGraphics.dispose();
 628             }
 629         } else if (debugFlash()) {
 630             Color oldColor = getColor();
 631             int i, count = (info.flashCount * 2) - 1;
 632 
 633             for (i = 0; i < count; i++) {
 634                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 635                 graphics.drawOval(x, y, width, height);
 636                 Toolkit.getDefaultToolkit().sync();
 637                 sleep(info.flashTime);
 638             }
 639             graphics.setColor(oldColor);
 640         }
 641         graphics.drawOval(x, y, width, height);
 642     }
 643 
 644     /**
 645      * Overrides <code>Graphics.fillOval</code>.
 646      */
 647     public void fillOval(int x, int y, int width, int height) {
 648         DebugGraphicsInfo info = info();
 649 
 650         if (debugLog()) {
 651             info().log(toShortString() +
 652                       " Filling oval: " +
 653                       new Rectangle(x, y, width, height));
 654         }
 655         if (isDrawingBuffer()) {
 656             if (debugBuffered()) {
 657                 Graphics debugGraphics = debugGraphics();
 658 
 659                 debugGraphics.fillOval(x, y, width, height);
 660                 debugGraphics.dispose();
 661             }
 662         } else if (debugFlash()) {
 663             Color oldColor = getColor();
 664             int i, count = (info.flashCount * 2) - 1;
 665 
 666             for (i = 0; i < count; i++) {
 667                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 668                 graphics.fillOval(x, y, width, height);
 669                 Toolkit.getDefaultToolkit().sync();
 670                 sleep(info.flashTime);
 671             }
 672             graphics.setColor(oldColor);
 673         }
 674         graphics.fillOval(x, y, width, height);
 675     }
 676 
 677     /**
 678      * Overrides <code>Graphics.drawArc</code>.
 679      */
 680     public void drawArc(int x, int y, int width, int height,
 681                         int startAngle, int arcAngle) {
 682         DebugGraphicsInfo info = info();
 683 
 684         if (debugLog()) {
 685             info().log(toShortString() +
 686                       " Drawing arc: " +
 687                       new Rectangle(x, y, width, height) +
 688                       " startAngle: " + startAngle +
 689                       " arcAngle: " + arcAngle);
 690         }
 691         if (isDrawingBuffer()) {
 692             if (debugBuffered()) {
 693                 Graphics debugGraphics = debugGraphics();
 694 
 695                 debugGraphics.drawArc(x, y, width, height,
 696                                       startAngle, arcAngle);
 697                 debugGraphics.dispose();
 698             }
 699         } else if (debugFlash()) {
 700             Color oldColor = getColor();
 701             int i, count = (info.flashCount * 2) - 1;
 702 
 703             for (i = 0; i < count; i++) {
 704                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 705                 graphics.drawArc(x, y, width, height, startAngle, arcAngle);
 706                 Toolkit.getDefaultToolkit().sync();
 707                 sleep(info.flashTime);
 708             }
 709             graphics.setColor(oldColor);
 710         }
 711         graphics.drawArc(x, y, width, height, startAngle, arcAngle);
 712     }
 713 
 714     /**
 715      * Overrides <code>Graphics.fillArc</code>.
 716      */
 717     public void fillArc(int x, int y, int width, int height,
 718                         int startAngle, int arcAngle) {
 719         DebugGraphicsInfo info = info();
 720 
 721         if (debugLog()) {
 722             info().log(toShortString() +
 723                       " Filling arc: " +
 724                       new Rectangle(x, y, width, height) +
 725                       " startAngle: " + startAngle +
 726                       " arcAngle: " + arcAngle);
 727         }
 728         if (isDrawingBuffer()) {
 729             if (debugBuffered()) {
 730                 Graphics debugGraphics = debugGraphics();
 731 
 732                 debugGraphics.fillArc(x, y, width, height,
 733                                       startAngle, arcAngle);
 734                 debugGraphics.dispose();
 735             }
 736         } else if (debugFlash()) {
 737             Color oldColor = getColor();
 738             int i, count = (info.flashCount * 2) - 1;
 739 
 740             for (i = 0; i < count; i++) {
 741                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 742                 graphics.fillArc(x, y, width, height, startAngle, arcAngle);
 743                 Toolkit.getDefaultToolkit().sync();
 744                 sleep(info.flashTime);
 745             }
 746             graphics.setColor(oldColor);
 747         }
 748         graphics.fillArc(x, y, width, height, startAngle, arcAngle);
 749     }
 750 
 751     /**
 752      * Overrides <code>Graphics.drawPolyline</code>.
 753      */
 754     public void drawPolyline(int xPoints[], int yPoints[], int nPoints) {
 755         DebugGraphicsInfo info = info();
 756 
 757         if (debugLog()) {
 758             info().log(toShortString() +
 759                       " Drawing polyline: " +
 760                       " nPoints: " + nPoints +
 761                       " X's: " + xPoints +
 762                       " Y's: " + yPoints);
 763         }
 764         if (isDrawingBuffer()) {
 765             if (debugBuffered()) {
 766                 Graphics debugGraphics = debugGraphics();
 767 
 768                 debugGraphics.drawPolyline(xPoints, yPoints, nPoints);
 769                 debugGraphics.dispose();
 770             }
 771         } else if (debugFlash()) {
 772             Color oldColor = getColor();
 773             int i, count = (info.flashCount * 2) - 1;
 774 
 775             for (i = 0; i < count; i++) {
 776                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 777                 graphics.drawPolyline(xPoints, yPoints, nPoints);
 778                 Toolkit.getDefaultToolkit().sync();
 779                 sleep(info.flashTime);
 780             }
 781             graphics.setColor(oldColor);
 782         }
 783         graphics.drawPolyline(xPoints, yPoints, nPoints);
 784     }
 785 
 786     /**
 787      * Overrides <code>Graphics.drawPolygon</code>.
 788      */
 789     public void drawPolygon(int xPoints[], int yPoints[], int nPoints) {
 790         DebugGraphicsInfo info = info();
 791 
 792         if (debugLog()) {
 793             info().log(toShortString() +
 794                       " Drawing polygon: " +
 795                       " nPoints: " + nPoints +
 796                       " X's: " + xPoints +
 797                       " Y's: " + yPoints);
 798         }
 799         if (isDrawingBuffer()) {
 800             if (debugBuffered()) {
 801                 Graphics debugGraphics = debugGraphics();
 802 
 803                 debugGraphics.drawPolygon(xPoints, yPoints, nPoints);
 804                 debugGraphics.dispose();
 805             }
 806         } else if (debugFlash()) {
 807             Color oldColor = getColor();
 808             int i, count = (info.flashCount * 2) - 1;
 809 
 810             for (i = 0; i < count; i++) {
 811                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 812                 graphics.drawPolygon(xPoints, yPoints, nPoints);
 813                 Toolkit.getDefaultToolkit().sync();
 814                 sleep(info.flashTime);
 815             }
 816             graphics.setColor(oldColor);
 817         }
 818         graphics.drawPolygon(xPoints, yPoints, nPoints);
 819     }
 820 
 821     /**
 822      * Overrides <code>Graphics.fillPolygon</code>.
 823      */
 824     public void fillPolygon(int xPoints[], int yPoints[], int nPoints) {
 825         DebugGraphicsInfo info = info();
 826 
 827         if (debugLog()) {
 828             info().log(toShortString() +
 829                       " Filling polygon: " +
 830                       " nPoints: " + nPoints +
 831                       " X's: " + xPoints +
 832                       " Y's: " + yPoints);
 833         }
 834         if (isDrawingBuffer()) {
 835             if (debugBuffered()) {
 836                 Graphics debugGraphics = debugGraphics();
 837 
 838                 debugGraphics.fillPolygon(xPoints, yPoints, nPoints);
 839                 debugGraphics.dispose();
 840             }
 841         } else if (debugFlash()) {
 842             Color oldColor = getColor();
 843             int i, count = (info.flashCount * 2) - 1;
 844 
 845             for (i = 0; i < count; i++) {
 846                 graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
 847                 graphics.fillPolygon(xPoints, yPoints, nPoints);
 848                 Toolkit.getDefaultToolkit().sync();
 849                 sleep(info.flashTime);
 850             }
 851             graphics.setColor(oldColor);
 852         }
 853         graphics.fillPolygon(xPoints, yPoints, nPoints);
 854     }
 855 
 856     /**
 857      * Overrides <code>Graphics.drawString</code>.
 858      */
 859     public void drawString(String aString, int x, int y) {
 860         DebugGraphicsInfo info = info();
 861 
 862         if (debugLog()) {
 863             info().log(toShortString() +
 864                        " Drawing string: \"" + aString +
 865                        "\" at: " + new Point(x, y));
 866         }
 867 
 868         if (isDrawingBuffer()) {
 869             if (debugBuffered()) {
 870                 Graphics debugGraphics = debugGraphics();
 871 
 872                 debugGraphics.drawString(aString, x, y);
 873                 debugGraphics.dispose();
 874             }
 875         } else if (debugFlash()) {
 876             Color oldColor = getColor();
 877             int i, count = (info.flashCount * 2) - 1;
 878 
 879             for (i = 0; i < count; i++) {
 880                 graphics.setColor((i % 2) == 0 ? info.flashColor
 881                                   : oldColor);
 882                 graphics.drawString(aString, x, y);
 883                 Toolkit.getDefaultToolkit().sync();
 884                 sleep(info.flashTime);
 885             }
 886             graphics.setColor(oldColor);
 887         }
 888         graphics.drawString(aString, x, y);
 889     }
 890 
 891     /**
 892      * Overrides <code>Graphics.drawString</code>.
 893      */
 894     public void drawString(AttributedCharacterIterator iterator, int x, int y) {
 895         DebugGraphicsInfo info = info();
 896 
 897         if (debugLog()) {
 898             info().log(toShortString() +
 899                        " Drawing text: \"" + iterator +
 900                        "\" at: " + new Point(x, y));
 901         }
 902 
 903         if (isDrawingBuffer()) {
 904             if (debugBuffered()) {
 905                 Graphics debugGraphics = debugGraphics();
 906 
 907                 debugGraphics.drawString(iterator, x, y);
 908                 debugGraphics.dispose();
 909             }
 910         } else if (debugFlash()) {
 911             Color oldColor = getColor();
 912             int i, count = (info.flashCount * 2) - 1;
 913 
 914             for (i = 0; i < count; i++) {
 915                 graphics.setColor((i % 2) == 0 ? info.flashColor
 916                                   : oldColor);
 917                 graphics.drawString(iterator, x, y);
 918                 Toolkit.getDefaultToolkit().sync();
 919                 sleep(info.flashTime);
 920             }
 921             graphics.setColor(oldColor);
 922         }
 923         graphics.drawString(iterator, x, y);
 924     }
 925 
 926     /**
 927      * Overrides <code>Graphics.drawBytes</code>.
 928      */
 929     public void drawBytes(byte data[], int offset, int length, int x, int y) {
 930         DebugGraphicsInfo info = info();
 931 
 932         Font font = graphics.getFont();
 933 
 934         if (debugLog()) {
 935             info().log(toShortString() +
 936                        " Drawing bytes at: " + new Point(x, y));
 937         }
 938 
 939         if (isDrawingBuffer()) {
 940             if (debugBuffered()) {
 941                 Graphics debugGraphics = debugGraphics();
 942 
 943                 debugGraphics.drawBytes(data, offset, length, x, y);
 944                 debugGraphics.dispose();
 945             }
 946         } else if (debugFlash()) {
 947             Color oldColor = getColor();
 948             int i, count = (info.flashCount * 2) - 1;
 949 
 950             for (i = 0; i < count; i++) {
 951                 graphics.setColor((i % 2) == 0 ? info.flashColor
 952                                   : oldColor);
 953                 graphics.drawBytes(data, offset, length, x, y);
 954                 Toolkit.getDefaultToolkit().sync();
 955                 sleep(info.flashTime);
 956             }
 957             graphics.setColor(oldColor);
 958         }
 959         graphics.drawBytes(data, offset, length, x, y);
 960     }
 961 
 962     /**
 963      * Overrides <code>Graphics.drawChars</code>.
 964      */
 965     public void drawChars(char data[], int offset, int length, int x, int y) {
 966         DebugGraphicsInfo info = info();
 967 
 968         Font font = graphics.getFont();
 969 
 970         if (debugLog()) {
 971             info().log(toShortString() +
 972                        " Drawing chars at " +  new Point(x, y));
 973         }
 974 
 975         if (isDrawingBuffer()) {
 976             if (debugBuffered()) {
 977                 Graphics debugGraphics = debugGraphics();
 978 
 979                 debugGraphics.drawChars(data, offset, length, x, y);
 980                 debugGraphics.dispose();
 981             }
 982         } else if (debugFlash()) {
 983             Color oldColor = getColor();
 984             int i, count = (info.flashCount * 2) - 1;
 985 
 986             for (i = 0; i < count; i++) {
 987                 graphics.setColor((i % 2) == 0 ? info.flashColor
 988                                   : oldColor);
 989                 graphics.drawChars(data, offset, length, x, y);
 990                 Toolkit.getDefaultToolkit().sync();
 991                 sleep(info.flashTime);
 992             }
 993             graphics.setColor(oldColor);
 994         }
 995         graphics.drawChars(data, offset, length, x, y);
 996     }
 997 
 998     /**
 999      * Overrides <code>Graphics.drawImage</code>.
1000      */
1001     public boolean drawImage(Image img, int x, int y,
1002                              ImageObserver observer) {
1003         DebugGraphicsInfo info = info();
1004 
1005         if (debugLog()) {
1006             info.log(toShortString() +
1007                      " Drawing image: " + img +
1008                      " at: " + new Point(x, y));
1009         }
1010 
1011         if (isDrawingBuffer()) {
1012             if (debugBuffered()) {
1013                 Graphics debugGraphics = debugGraphics();
1014 
1015                 debugGraphics.drawImage(img, x, y, observer);
1016                 debugGraphics.dispose();
1017             }
1018         } else if (debugFlash()) {
1019             int i, count = (info.flashCount * 2) - 1;
1020             ImageProducer oldProducer = img.getSource();
1021             ImageProducer newProducer
1022                 = new FilteredImageSource(oldProducer,
1023                                 new DebugGraphicsFilter(info.flashColor));
1024             Image newImage
1025                 = Toolkit.getDefaultToolkit().createImage(newProducer);
1026             DebugGraphicsObserver imageObserver
1027                 = new DebugGraphicsObserver();
1028 
1029             Image imageToDraw;
1030             for (i = 0; i < count; i++) {
1031                 imageToDraw = (i % 2) == 0 ? newImage : img;
1032                 loadImage(imageToDraw);
1033                 graphics.drawImage(imageToDraw, x, y,
1034                                    imageObserver);
1035                 Toolkit.getDefaultToolkit().sync();
1036                 sleep(info.flashTime);
1037             }
1038         }
1039         return graphics.drawImage(img, x, y, observer);
1040     }
1041 
1042     /**
1043      * Overrides <code>Graphics.drawImage</code>.
1044      */
1045     public boolean drawImage(Image img, int x, int y, int width, int height,
1046                              ImageObserver observer) {
1047         DebugGraphicsInfo info = info();
1048 
1049         if (debugLog()) {
1050             info.log(toShortString() +
1051                      " Drawing image: " + img +
1052                      " at: " + new Rectangle(x, y, width, height));
1053         }
1054 
1055         if (isDrawingBuffer()) {
1056             if (debugBuffered()) {
1057                 Graphics debugGraphics = debugGraphics();
1058 
1059                 debugGraphics.drawImage(img, x, y, width, height, observer);
1060                 debugGraphics.dispose();
1061             }
1062         } else if (debugFlash()) {
1063             int i, count = (info.flashCount * 2) - 1;
1064             ImageProducer oldProducer = img.getSource();
1065             ImageProducer newProducer
1066                 = new FilteredImageSource(oldProducer,
1067                                 new DebugGraphicsFilter(info.flashColor));
1068             Image newImage
1069                 = Toolkit.getDefaultToolkit().createImage(newProducer);
1070             DebugGraphicsObserver imageObserver
1071                 = new DebugGraphicsObserver();
1072 
1073             Image imageToDraw;
1074             for (i = 0; i < count; i++) {
1075                 imageToDraw = (i % 2) == 0 ? newImage : img;
1076                 loadImage(imageToDraw);
1077                 graphics.drawImage(imageToDraw, x, y,
1078                                    width, height, imageObserver);
1079                 Toolkit.getDefaultToolkit().sync();
1080                 sleep(info.flashTime);
1081             }
1082         }
1083         return graphics.drawImage(img, x, y, width, height, observer);
1084     }
1085 
1086     /**
1087      * Overrides <code>Graphics.drawImage</code>.
1088      */
1089     public boolean drawImage(Image img, int x, int y,
1090                              Color bgcolor,
1091                              ImageObserver observer) {
1092         DebugGraphicsInfo info = info();
1093 
1094         if (debugLog()) {
1095             info.log(toShortString() +
1096                      " Drawing image: " + img +
1097                      " at: " + new Point(x, y) +
1098                      ", bgcolor: " + bgcolor);
1099         }
1100 
1101         if (isDrawingBuffer()) {
1102             if (debugBuffered()) {
1103                 Graphics debugGraphics = debugGraphics();
1104 
1105                 debugGraphics.drawImage(img, x, y, bgcolor, observer);
1106                 debugGraphics.dispose();
1107             }
1108         } else if (debugFlash()) {
1109             int i, count = (info.flashCount * 2) - 1;
1110             ImageProducer oldProducer = img.getSource();
1111             ImageProducer newProducer
1112                 = new FilteredImageSource(oldProducer,
1113                                 new DebugGraphicsFilter(info.flashColor));
1114             Image newImage
1115                 = Toolkit.getDefaultToolkit().createImage(newProducer);
1116             DebugGraphicsObserver imageObserver
1117                 = new DebugGraphicsObserver();
1118 
1119             Image imageToDraw;
1120             for (i = 0; i < count; i++) {
1121                 imageToDraw = (i % 2) == 0 ? newImage : img;
1122                 loadImage(imageToDraw);
1123                 graphics.drawImage(imageToDraw, x, y,
1124                                    bgcolor, imageObserver);
1125                 Toolkit.getDefaultToolkit().sync();
1126                 sleep(info.flashTime);
1127             }
1128         }
1129         return graphics.drawImage(img, x, y, bgcolor, observer);
1130     }
1131 
1132     /**
1133      * Overrides <code>Graphics.drawImage</code>.
1134      */
1135     public boolean drawImage(Image img, int x, int y,int width, int height,
1136                              Color bgcolor,
1137                              ImageObserver observer) {
1138         DebugGraphicsInfo info = info();
1139 
1140         if (debugLog()) {
1141             info.log(toShortString() +
1142                      " Drawing image: " + img +
1143                      " at: " + new Rectangle(x, y, width, height) +
1144                      ", bgcolor: " + bgcolor);
1145         }
1146 
1147         if (isDrawingBuffer()) {
1148             if (debugBuffered()) {
1149                 Graphics debugGraphics = debugGraphics();
1150 
1151                 debugGraphics.drawImage(img, x, y, width, height,
1152                                         bgcolor, observer);
1153                 debugGraphics.dispose();
1154             }
1155         } else if (debugFlash()) {
1156             int i, count = (info.flashCount * 2) - 1;
1157             ImageProducer oldProducer = img.getSource();
1158             ImageProducer newProducer
1159                 = new FilteredImageSource(oldProducer,
1160                                 new DebugGraphicsFilter(info.flashColor));
1161             Image newImage
1162                 = Toolkit.getDefaultToolkit().createImage(newProducer);
1163             DebugGraphicsObserver imageObserver
1164                 = new DebugGraphicsObserver();
1165 
1166             Image imageToDraw;
1167             for (i = 0; i < count; i++) {
1168                 imageToDraw = (i % 2) == 0 ? newImage : img;
1169                 loadImage(imageToDraw);
1170                 graphics.drawImage(imageToDraw, x, y,
1171                                    width, height, bgcolor, imageObserver);
1172                 Toolkit.getDefaultToolkit().sync();
1173                 sleep(info.flashTime);
1174             }
1175         }
1176         return graphics.drawImage(img, x, y, width, height, bgcolor, observer);
1177     }
1178 
1179     /**
1180      * Overrides <code>Graphics.drawImage</code>.
1181      */
1182     public boolean drawImage(Image img,
1183                              int dx1, int dy1, int dx2, int dy2,
1184                              int sx1, int sy1, int sx2, int sy2,
1185                              ImageObserver observer) {
1186         DebugGraphicsInfo info = info();
1187 
1188         if (debugLog()) {
1189             info.log(toShortString() +
1190                      " Drawing image: " + img +
1191                      " destination: " + new Rectangle(dx1, dy1, dx2, dy2) +
1192                      " source: " + new Rectangle(sx1, sy1, sx2, sy2));
1193         }
1194 
1195         if (isDrawingBuffer()) {
1196             if (debugBuffered()) {
1197                 Graphics debugGraphics = debugGraphics();
1198 
1199                 debugGraphics.drawImage(img, dx1, dy1, dx2, dy2,
1200                                         sx1, sy1, sx2, sy2, observer);
1201                 debugGraphics.dispose();
1202             }
1203         } else if (debugFlash()) {
1204             int i, count = (info.flashCount * 2) - 1;
1205             ImageProducer oldProducer = img.getSource();
1206             ImageProducer newProducer
1207                 = new FilteredImageSource(oldProducer,
1208                                 new DebugGraphicsFilter(info.flashColor));
1209             Image newImage
1210                 = Toolkit.getDefaultToolkit().createImage(newProducer);
1211             DebugGraphicsObserver imageObserver
1212                 = new DebugGraphicsObserver();
1213 
1214             Image imageToDraw;
1215             for (i = 0; i < count; i++) {
1216                 imageToDraw = (i % 2) == 0 ? newImage : img;
1217                 loadImage(imageToDraw);
1218                 graphics.drawImage(imageToDraw,
1219                                    dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
1220                                    imageObserver);
1221                 Toolkit.getDefaultToolkit().sync();
1222                 sleep(info.flashTime);
1223             }
1224         }
1225         return graphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
1226                                   observer);
1227     }
1228 
1229     /**
1230      * Overrides <code>Graphics.drawImage</code>.
1231      */
1232     public boolean drawImage(Image img,
1233                              int dx1, int dy1, int dx2, int dy2,
1234                              int sx1, int sy1, int sx2, int sy2,
1235                              Color bgcolor,
1236                              ImageObserver observer) {
1237         DebugGraphicsInfo info = info();
1238 
1239         if (debugLog()) {
1240             info.log(toShortString() +
1241                      " Drawing image: " + img +
1242                      " destination: " + new Rectangle(dx1, dy1, dx2, dy2) +
1243                      " source: " + new Rectangle(sx1, sy1, sx2, sy2) +
1244                      ", bgcolor: " + bgcolor);
1245         }
1246 
1247         if (isDrawingBuffer()) {
1248             if (debugBuffered()) {
1249                 Graphics debugGraphics = debugGraphics();
1250 
1251                 debugGraphics.drawImage(img, dx1, dy1, dx2, dy2,
1252                                         sx1, sy1, sx2, sy2, bgcolor, observer);
1253                 debugGraphics.dispose();
1254             }
1255         } else if (debugFlash()) {
1256             int i, count = (info.flashCount * 2) - 1;
1257             ImageProducer oldProducer = img.getSource();
1258             ImageProducer newProducer
1259                 = new FilteredImageSource(oldProducer,
1260                                 new DebugGraphicsFilter(info.flashColor));
1261             Image newImage
1262                 = Toolkit.getDefaultToolkit().createImage(newProducer);
1263             DebugGraphicsObserver imageObserver
1264                 = new DebugGraphicsObserver();
1265 
1266             Image imageToDraw;
1267             for (i = 0; i < count; i++) {
1268                 imageToDraw = (i % 2) == 0 ? newImage : img;
1269                 loadImage(imageToDraw);
1270                 graphics.drawImage(imageToDraw,
1271                                    dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
1272                                    bgcolor, imageObserver);
1273                 Toolkit.getDefaultToolkit().sync();
1274                 sleep(info.flashTime);
1275             }
1276         }
1277         return graphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
1278                                   bgcolor, observer);
1279     }
1280 
1281     static void loadImage(Image img) {
1282         imageLoadingIcon.loadImage(img);
1283     }
1284 
1285 
1286     /**
1287      * Overrides <code>Graphics.copyArea</code>.
1288      */
1289     public void copyArea(int x, int y, int width, int height,
1290                          int destX, int destY) {
1291         if (debugLog()) {
1292             info().log(toShortString() +
1293                       " Copying area from: " +
1294                       new Rectangle(x, y, width, height) +
1295                       " to: " + new Point(destX, destY));
1296         }
1297         graphics.copyArea(x, y, width, height, destX, destY);
1298     }
1299 
1300     final void sleep(int mSecs) {
1301         try {
1302             Thread.sleep(mSecs);
1303         } catch (Exception e) {
1304         }
1305     }
1306 
1307     /**
1308      * Overrides <code>Graphics.dispose</code>.
1309      */
1310     public void dispose() {
1311         graphics.dispose();
1312         graphics = null;
1313     }
1314 
1315     // ALERT!
1316     /**
1317      * Returns the drawingBuffer value.
1318      *
1319      * @return true if this object is drawing from a Buffer
1320      */
1321     public boolean isDrawingBuffer() {
1322         return buffer != null;
1323     }
1324 
1325     String toShortString() {
1326         return "Graphics" + (isDrawingBuffer() ? "<B>" : "") + "(" + graphicsID + "-" + debugOptions + ")";
1327     }
1328 
1329     String pointToString(int x, int y) {
1330         return "(" + x + ", " + y + ")";
1331     }
1332 
1333     /** Enables/disables diagnostic information about every graphics
1334       * operation. The value of <b>options</b> indicates how this information
1335       * should be displayed. LOG_OPTION causes a text message to be printed.
1336       * FLASH_OPTION causes the drawing to flash several times. BUFFERED_OPTION
1337       * creates a new Frame that shows each operation on an
1338       * offscreen buffer. The value of <b>options</b> is bitwise OR'd into
1339       * the current value. To disable debugging use NONE_OPTION.
1340       */
1341     public void setDebugOptions(int options) {
1342         if (options != 0) {
1343             if (options == NONE_OPTION) {
1344                 if (debugOptions != 0) {
1345                     System.err.println(toShortString() + " Disabling debug");
1346                     debugOptions = 0;
1347                 }
1348             } else {
1349                 if (debugOptions != options) {
1350                     debugOptions |= options;
1351                     if (debugLog()) {
1352                         System.err.println(toShortString() + " Enabling debug");
1353                     }
1354                 }
1355             }
1356         }
1357     }
1358 
1359     /** Returns the current debugging options for this DebugGraphics.
1360       * @see #setDebugOptions
1361       */
1362     public int getDebugOptions() {
1363         return debugOptions;
1364     }
1365 
1366     /** Static wrapper method for DebugGraphicsInfo.setDebugOptions(). Stores
1367       * options on a per component basis.
1368       */
1369     static void setDebugOptions(JComponent component, int options) {
1370         info().setDebugOptions(component, options);
1371     }
1372 
1373     /** Static wrapper method for DebugGraphicsInfo.getDebugOptions().
1374       */
1375     static int getDebugOptions(JComponent component) {
1376         DebugGraphicsInfo debugGraphicsInfo = info();
1377         if (debugGraphicsInfo == null) {
1378             return 0;
1379         } else {
1380             return debugGraphicsInfo.getDebugOptions(component);
1381         }
1382     }
1383 
1384     /** Returns non-zero if <b>component</b> should display with DebugGraphics,
1385       * zero otherwise. Walks the JComponent's parent tree to determine if
1386       * any debugging options have been set.
1387       */
1388     static int shouldComponentDebug(JComponent component) {
1389         DebugGraphicsInfo info = info();
1390         if (info == null) {
1391             return 0;
1392         } else {
1393             Container container = (Container)component;
1394             int debugOptions = 0;
1395 
1396             while (container != null && (container instanceof JComponent)) {
1397                 debugOptions |= info.getDebugOptions((JComponent)container);
1398                 container = container.getParent();
1399             }
1400 
1401             return debugOptions;
1402         }
1403     }
1404 
1405     /** Returns the number of JComponents that have debugging options turned
1406       * on.
1407       */
1408     static int debugComponentCount() {
1409         DebugGraphicsInfo debugGraphicsInfo = info();
1410         if (debugGraphicsInfo != null &&
1411                     debugGraphicsInfo.componentToDebug != null) {
1412             return debugGraphicsInfo.componentToDebug.size();
1413         } else {
1414             return 0;
1415         }
1416     }
1417 
1418     boolean debugLog() {
1419         return (debugOptions & LOG_OPTION) == LOG_OPTION;
1420     }
1421 
1422     boolean debugFlash() {
1423         return (debugOptions & FLASH_OPTION) == FLASH_OPTION;
1424     }
1425 
1426     boolean debugBuffered() {
1427         return (debugOptions & BUFFERED_OPTION) == BUFFERED_OPTION;
1428     }
1429 
1430     /** Returns a DebugGraphics for use in buffering window.
1431       */
1432     private Graphics debugGraphics() {
1433         DebugGraphics        debugGraphics;
1434         DebugGraphicsInfo    info = info();
1435         JFrame               debugFrame;
1436 
1437         if (info.debugFrame == null) {
1438             info.debugFrame = new JFrame();
1439             info.debugFrame.setSize(500, 500);
1440         }
1441         debugFrame = info.debugFrame;
1442         debugFrame.show();
1443         debugGraphics = new DebugGraphics(debugFrame.getGraphics());
1444         debugGraphics.setFont(getFont());
1445         debugGraphics.setColor(getColor());
1446         debugGraphics.translate(xOffset, yOffset);
1447         debugGraphics.setClip(getClipBounds());
1448         if (debugFlash()) {
1449             debugGraphics.setDebugOptions(FLASH_OPTION);
1450         }
1451         return debugGraphics;
1452     }
1453 
1454     /** Returns DebugGraphicsInfo, or creates one if none exists.
1455       */
1456     static DebugGraphicsInfo info() {
1457         DebugGraphicsInfo debugGraphicsInfo = (DebugGraphicsInfo)
1458             SwingUtilities.appContextGet(debugGraphicsInfoKey);
1459         if (debugGraphicsInfo == null) {
1460             debugGraphicsInfo = new DebugGraphicsInfo();
1461             SwingUtilities.appContextPut(debugGraphicsInfoKey,
1462                                          debugGraphicsInfo);
1463         }
1464         return debugGraphicsInfo;
1465     }
1466     private static final Class debugGraphicsInfoKey = DebugGraphicsInfo.class;
1467 
1468 
1469 }