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