1 /* DebugGraphics.java --
2 Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
40 import java
.awt
.Color
;
42 import java
.awt
.FontMetrics
;
43 import java
.awt
.Graphics
;
44 import java
.awt
.Image
;
45 import java
.awt
.Point
;
46 import java
.awt
.Rectangle
;
47 import java
.awt
.Shape
;
48 import java
.awt
.image
.ImageObserver
;
49 import java
.io
.PrintStream
;
50 import java
.text
.AttributedCharacterIterator
;
54 * An extension of {@link Graphics} that can be used for debugging
55 * custom Swing widgets. <code>DebugGraphics</code> has the ability to
56 * draw slowly and can log drawing actions.
58 * @author Andrew Selkirk
60 public class DebugGraphics
extends Graphics
65 public static final int LOG_OPTION
= 1;
70 public static final int FLASH_OPTION
= 2;
75 public static final int BUFFERED_OPTION
= 4;
80 public static final int NONE_OPTION
= -1;
82 static Color debugFlashColor
= Color
.RED
;
83 static int debugFlashCount
= 10;
84 static int debugFlashTime
= 1000;
85 static PrintStream debugLogStream
= System
.out
;
88 * Counts the created DebugGraphics objects. This is used by the
91 static int counter
= 0;
124 * Creates a <code>DebugGraphics</code> object.
126 public DebugGraphics()
132 * Creates a <code>DebugGraphics</code> object.
134 * @param graphics The <code>Graphics</code> object to wrap
135 * @param component TODO
137 public DebugGraphics(Graphics graphics
, JComponent component
)
140 // FIXME: What shall we do with component ?
144 * Creates a <code>DebugGraphics</code> object.
146 * @param graphics The <code>Graphics</code> object to wrap
148 public DebugGraphics(Graphics graphics
)
151 this.graphics
= graphics
;
155 * Sets the color to draw stuff with.
157 * @param color The color
159 public void setColor(Color color
)
161 if ((debugOptions
& LOG_OPTION
) != 0)
162 logStream().println(prefix() + " Setting color: " + color
);
164 graphics
.setColor(color
);
168 * Creates a overrides <code>Graphics.create</code> to create a
169 * <code>DebugGraphics</code> object.
171 * @return a new <code>DebugGraphics</code> object.
173 public Graphics
create()
175 DebugGraphics copy
= new DebugGraphics(graphics
.create());
176 copy
.debugOptions
= debugOptions
;
181 * Creates a overrides <code>Graphics.create</code> to create a
182 * <code>DebugGraphics</code> object.
184 * @param x the x coordinate
185 * @param y the y coordinate
186 * @param width the width
187 * @param height the height
189 * @return a new <code>DebugGraphics</code> object.
191 public Graphics
create(int x
, int y
, int width
, int height
)
193 DebugGraphics copy
= new DebugGraphics(graphics
.create(x
, y
, width
,
195 copy
.debugOptions
= debugOptions
;
204 public static Color
flashColor()
206 return debugFlashColor
;
212 * @param color the color to use for flashing
214 public static void setFlashColor(Color color
)
216 debugFlashColor
= color
;
222 * @return The time in milliseconds
224 public static int flashTime()
226 return debugFlashTime
;
232 * @param time The time in milliseconds
234 public static void setFlashTime(int time
)
236 debugFlashTime
= time
;
242 * @return The number of flashes
244 public static int flashCount()
246 return debugFlashCount
;
252 * @param count The number of flashes
254 public static void setFlashCount(int count
)
256 debugFlashCount
= count
;
262 * @return The <code>PrintStream</code> to write logging messages to
264 public static PrintStream
logStream()
266 return debugLogStream
;
272 * @param stream The currently set <code>PrintStream</code>.
274 public static void setLogStream(PrintStream stream
)
276 debugLogStream
= stream
;
284 public Font
getFont()
286 return graphics
.getFont();
292 * @param font The font to use for drawing text
294 public void setFont(Font font
)
296 if ((debugOptions
& LOG_OPTION
) != 0)
297 logStream().println(prefix() + " Setting font: " + font
);
299 graphics
.setFont(font
);
303 * Returns the color used for drawing.
307 public Color
getColor()
309 return graphics
.getColor();
313 * Returns the font metrics of the current font.
315 * @return a <code>FontMetrics</code> object
317 public FontMetrics
getFontMetrics()
319 return graphics
.getFontMetrics();
323 * Returns the font metrics for a given font.
325 * @param font the font to get the metrics for
327 * @return a <code>FontMetrics</code> object
329 public FontMetrics
getFontMetrics(Font font
)
331 return graphics
.getFontMetrics(font
);
337 * @param x the x coordinate
338 * @param y the y coordinate
340 public void translate(int x
, int y
)
342 if ((debugOptions
& LOG_OPTION
) != 0)
343 logStream().println(prefix() + " Translating by: " + new Point(x
, y
));
345 graphics
.translate(x
, y
);
351 public void setPaintMode()
353 if ((debugOptions
& LOG_OPTION
) != 0)
354 logStream().println(prefix() + " Setting paint mode");
356 graphics
.setPaintMode();
362 * @param color the color
364 public void setXORMode(Color color
)
366 if ((debugOptions
& LOG_OPTION
) != 0)
367 logStream().println(prefix() + " Setting XOR mode: " + color
);
369 graphics
.setXORMode(color
);
377 public Rectangle
getClipBounds()
379 return graphics
.getClipBounds();
383 * Intersects the current clip region with the given region.
385 * @param x The x-position of the region
386 * @param y The y-position of the region
387 * @param width The width of the region
388 * @param height The height of the region
390 public void clipRect(int x
, int y
, int width
, int height
)
392 if ((debugOptions
& LOG_OPTION
) != 0)
394 logStream().print(prefix() + " Setting clipRect: "
395 + new Rectangle(x
, y
, width
, height
));
398 graphics
.clipRect(x
, y
, width
, height
);
400 if ((debugOptions
& LOG_OPTION
) != 0)
401 logStream().println(" Netting clipRect: " + graphics
.getClipBounds());
405 * Sets the clipping region.
407 * @param x The x-position of the region
408 * @param y The y-position of the region
409 * @param width The width of the region
410 * @param height The height of the region
412 public void setClip(int x
, int y
, int width
, int height
)
414 if ((debugOptions
& LOG_OPTION
) != 0)
416 logStream().println(prefix() + " Setting new clipRect: "
417 + new Rectangle(x
, y
, width
, height
));
420 graphics
.setClip(x
, y
, width
, height
);
424 * Returns the current clipping region.
428 public Shape
getClip()
430 return graphics
.getClip();
434 * Sets the current clipping region
436 * @param shape The clippin region
438 public void setClip(Shape shape
)
440 if ((debugOptions
& LOG_OPTION
) != 0)
441 logStream().println(prefix() + " Setting new clipRect: " + shape
);
443 graphics
.setClip(shape
);
446 private void sleep(int milliseconds
)
450 Thread
.sleep(milliseconds
);
452 catch (InterruptedException e
)
461 * @param x The x-position of the rectangle
462 * @param y The y-position of the rectangle
463 * @param width The width of the rectangle
464 * @param height The height of the rectangle
466 public void drawRect(int x
, int y
, int width
, int height
)
468 if ((debugOptions
& LOG_OPTION
) != 0)
470 logStream().println(prefix() + " Drawing rect: "
471 + new Rectangle(x
, y
, width
, height
));
474 if ((debugOptions
& FLASH_OPTION
) != 0)
476 Color color
= graphics
.getColor();
477 for (int index
= 0; index
< (debugFlashCount
- 1); ++index
)
479 graphics
.setColor(color
);
480 graphics
.drawRect(x
, y
, width
, height
);
481 sleep(debugFlashTime
);
482 graphics
.setColor(debugFlashColor
);
483 graphics
.drawRect(x
, y
, width
, height
);
484 sleep(debugFlashTime
);
486 graphics
.setColor(color
);
489 graphics
.drawRect(x
, y
, width
, height
);
493 * Draws a filled rectangle.
495 * @param x The x-position of the rectangle
496 * @param y The y-position of the rectangle
497 * @param width The width of the rectangle
498 * @param height The height of the rectangle
500 public void fillRect(int x
, int y
, int width
, int height
)
502 if ((debugOptions
& LOG_OPTION
) != 0)
504 logStream().println(prefix() + " Filling rect: "
505 + new Rectangle(x
, y
, width
, height
));
508 if ((debugOptions
& FLASH_OPTION
) != 0)
510 Color color
= graphics
.getColor();
511 for (int index
= 0; index
< (debugFlashCount
- 1); ++index
)
513 graphics
.setColor(color
);
514 graphics
.fillRect(x
, y
, width
, height
);
515 sleep(debugFlashTime
);
516 graphics
.setColor(debugFlashColor
);
517 graphics
.fillRect(x
, y
, width
, height
);
518 sleep(debugFlashTime
);
520 graphics
.setColor(color
);
523 graphics
.fillRect(x
, y
, width
, height
);
529 * @param x The x-position of the rectangle
530 * @param y The y-position of the rectangle
531 * @param width The width of the rectangle
532 * @param height The height of the rectangle
534 public void clearRect(int x
, int y
, int width
, int height
)
536 if ((debugOptions
& LOG_OPTION
) != 0)
538 logStream().println(prefix() + " Clearing rect: "
539 + new Rectangle(x
, y
, width
, height
));
542 graphics
.clearRect(x
, y
, width
, height
);
548 * @param x The x-position of the rectangle
549 * @param y The y-position of the rectangle
550 * @param width The width of the rectangle
551 * @param height The height of the rectangle
552 * @param arcWidth TODO
553 * @param arcHeight TODO
555 public void drawRoundRect(int x
, int y
, int width
, int height
,
556 int arcWidth
, int arcHeight
)
558 if ((debugOptions
& LOG_OPTION
) != 0)
560 logStream().println(prefix() + " Drawing round rect: "
561 + new Rectangle(x
, y
, width
, height
)
562 + " arcWidth: " + arcWidth
563 + " arcHeight: " + arcHeight
);
566 graphics
.drawRoundRect(x
, y
, width
, height
, arcWidth
, arcHeight
);
572 * @param x The x-position of the rectangle
573 * @param y The y-position of the rectangle
574 * @param width The width of the rectangle
575 * @param height The height of the rectangle
576 * @param arcWidth TODO
577 * @param arcHeight TODO
579 public void fillRoundRect(int x
, int y
, int width
, int height
,
580 int arcWidth
, int arcHeight
)
582 if ((debugOptions
& LOG_OPTION
) != 0)
584 logStream().println(prefix() + " Filling round rect: "
585 + new Rectangle(x
, y
, width
, height
)
586 + " arcWidth: " + arcWidth
587 + " arcHeight: " + arcHeight
);
590 graphics
.fillRoundRect(x
, y
, width
, height
, arcWidth
, arcHeight
);
596 * @param x1 The x-position of the start
597 * @param y1 The y-position of the start
598 * @param x2 The x-position of the end
599 * @param y2 The y-position of the end
601 public void drawLine(int x1
, int y1
, int x2
, int y2
)
603 if ((debugOptions
& LOG_OPTION
) != 0)
605 logStream().println(prefix() + " Drawing line: from (" + x1
+ ", "
606 + y1
+ ") to (" + x2
+ ", " + y2
+ ")");
609 graphics
.drawLine(x1
, y1
, x2
, y2
);
615 * @param x The x-position of the rectangle
616 * @param y The y-position of the rectangle
617 * @param width The width of the rectangle
618 * @param height The height of the rectangle
621 public void draw3DRect(int x
, int y
, int width
, int height
, boolean raised
)
623 if ((debugOptions
& LOG_OPTION
) != 0)
625 logStream().println(prefix() + " Drawing 3D rect: "
626 + new Rectangle(x
, y
, width
, height
)
627 + "Raised bezel: " + raised
);
630 graphics
.draw3DRect(x
, y
, width
, height
, raised
);
636 * @param x The x-position of the rectangle
637 * @param y The y-position of the rectangle
638 * @param width The width of the rectangle
639 * @param height The height of the rectangle
642 public void fill3DRect(int x
, int y
, int width
, int height
, boolean raised
)
644 if ((debugOptions
& LOG_OPTION
) != 0)
646 logStream().println(prefix() + " Filling 3D rect: "
647 + new Rectangle(x
, y
, width
, height
)
648 + "Raised bezel: " + raised
);
651 graphics
.fill3DRect(x
, y
, width
, height
, raised
);
657 * @param x the x coordinate
658 * @param y the y coordiante
659 * @param width the width
660 * @param height the height
662 public void drawOval(int x
, int y
, int width
, int height
)
664 if ((debugOptions
& LOG_OPTION
) != 0)
666 logStream().println(prefix() + " Drawing oval: "
667 + new Rectangle(x
, y
, width
, height
));
670 graphics
.drawOval(x
, y
, width
, height
);
676 * @param x the x coordinate
677 * @param y the y coordinate
678 * @param width the width
679 * @param height the height
681 public void fillOval(int x
, int y
, int width
, int height
)
683 if ((debugOptions
& LOG_OPTION
) != 0)
685 logStream().println(prefix() + " Filling oval: "
686 + new Rectangle(x
, y
, width
, height
));
689 graphics
.fillOval(x
, y
, width
, height
);
695 * @param x the x coordinate
696 * @param y the y coordinate
697 * @param width the width
698 * @param height the height
699 * @param startAngle TODO
700 * @param arcAngle TODO
702 public void drawArc(int x
, int y
, int width
, int height
,
703 int startAngle
, int arcAngle
)
705 if ((debugOptions
& LOG_OPTION
) != 0)
707 logStream().println(prefix() + " Drawing arc: "
708 + new Rectangle(x
, y
, width
, height
)
709 + " startAngle: " + startAngle
710 + " arcAngle: " + arcAngle
);
713 graphics
.drawArc(x
, y
, width
, height
, startAngle
, arcAngle
);
719 * @param x the coordinate
720 * @param y the y coordinate
721 * @param width the width
722 * @param height the height
723 * @param startAngle TODO
724 * @param arcAngle TODO
726 public void fillArc(int x
, int y
, int width
, int height
,
727 int startAngle
, int arcAngle
)
729 if ((debugOptions
& LOG_OPTION
) != 0)
731 logStream().println(prefix() + " Filling arc: "
732 + new Rectangle(x
, y
, width
, height
)
733 + " startAngle: " + startAngle
734 + " arcAngle: " + arcAngle
);
737 graphics
.fillArc(x
, y
, width
, height
, startAngle
, arcAngle
);
743 * @param xpoints TODO
744 * @param ypoints TODO
745 * @param npoints TODO
747 public void drawPolyline(int[] xpoints
, int[] ypoints
, int npoints
)
749 if ((debugOptions
& LOG_OPTION
) != 0)
751 logStream().println(prefix() + " Drawing polyline: nPoints: " + npoints
752 + " X's: " + xpoints
+ " Y's: " + ypoints
);
755 graphics
.drawPolyline(xpoints
, ypoints
, npoints
);
761 * @param xpoints TODO
762 * @param ypoints TODO
763 * @param npoints TODO
765 public void drawPolygon(int[] xpoints
, int[] ypoints
, int npoints
)
767 if ((debugOptions
& LOG_OPTION
) != 0)
769 logStream().println(prefix() + " Drawing polygon: nPoints: " + npoints
770 + " X's: " + xpoints
+ " Y's: " + ypoints
);
773 graphics
.drawPolygon(xpoints
, ypoints
, npoints
);
779 * @param xpoints TODO
780 * @param ypoints TODO
781 * @param npoints TODO
783 public void fillPolygon(int[] xpoints
, int[] ypoints
, int npoints
)
785 if ((debugOptions
& LOG_OPTION
) != 0)
787 logStream().println(prefix() + " Drawing polygon: nPoints: " + npoints
788 + " X's: " + xpoints
+ " Y's: " + ypoints
);
791 graphics
.fillPolygon(xpoints
, ypoints
, npoints
);
797 * @param string the string
798 * @param x the x coordinate
799 * @param y the y coordinate
801 public void drawString(String string
, int x
, int y
)
803 if ((debugOptions
& LOG_OPTION
) != 0)
805 logStream().println(prefix() + " Drawing string: \"" + string
806 + "\" at: " + new Point(x
, y
));
809 graphics
.drawString(string
, x
, y
);
815 * @param iterator TODO
816 * @param x the x coordinate
817 * @param y the y coordinate
819 public void drawString(AttributedCharacterIterator iterator
,
822 if ((debugOptions
& LOG_OPTION
) != 0)
824 logStream().println(prefix() + " Drawing string: \"" + iterator
825 + "\" at: " + new Point(x
, y
));
828 graphics
.drawString(iterator
, x
, y
);
837 * @param x the x coordinate
838 * @param y the y coordinate
840 public void drawBytes(byte[] data
, int offset
, int length
,
843 if ((debugOptions
& LOG_OPTION
) != 0)
844 logStream().println(prefix() + " Drawing bytes at: " + new Point(x
, y
));
846 graphics
.drawBytes(data
, offset
, length
, x
, y
);
852 * @param data array of characters to draw
853 * @param offset offset in array
854 * @param length number of characters in array to draw
855 * @param x x-position
856 * @param y y-position
858 public void drawChars(char[] data
, int offset
, int length
,
861 if ((debugOptions
& LOG_OPTION
) != 0)
862 logStream().println(prefix() + " Drawing chars at: " + new Point(x
, y
));
864 if ((debugOptions
& FLASH_OPTION
) != 0)
866 Color color
= graphics
.getColor();
867 for (int index
= 0; index
< (debugFlashCount
- 1); ++index
)
869 graphics
.setColor(color
);
870 graphics
.drawChars(data
, offset
, length
, x
, y
);
871 sleep(debugFlashTime
);
872 graphics
.setColor(debugFlashColor
);
873 graphics
.drawChars(data
, offset
, length
, x
, y
);
874 sleep(debugFlashTime
);
876 graphics
.setColor(color
);
879 graphics
.drawChars(data
, offset
, length
, x
, y
);
885 * @param image The image to draw
886 * @param x The x position
887 * @param y The y position
888 * @param observer The image observer
891 public boolean drawImage(Image image
, int x
, int y
,
892 ImageObserver observer
)
894 if ((debugOptions
& LOG_OPTION
) != 0)
896 logStream().println(prefix() + " Drawing image: " + image
+ " at: "
900 return graphics
.drawImage(image
, x
, y
, observer
);
906 * @param image The image to draw
907 * @param x The x position
908 * @param y The y position
909 * @param width The width of the area to draw the image
910 * @param height The height of the area to draw the image
911 * @param observer The image observer
915 public boolean drawImage(Image image
, int x
, int y
, int width
,
916 int height
, ImageObserver observer
)
918 if ((debugOptions
& LOG_OPTION
) != 0)
920 logStream().println(prefix() + " Drawing image: " + image
921 + " at: " + new Rectangle(x
, y
, width
, height
));
924 return graphics
.drawImage(image
, x
, y
, width
, height
, observer
);
930 * @param image The image to draw
931 * @param x The x position
932 * @param y The y position
933 * @param background The color for the background in the opaque regions
935 * @param observer The image observer
939 public boolean drawImage(Image image
, int x
, int y
,
940 Color background
, ImageObserver observer
)
942 if ((debugOptions
& LOG_OPTION
) != 0)
944 logStream().println(prefix() + " Drawing image: " + image
945 + " at: " + new Point(x
, y
)
946 + ", bgcolor: " + background
);
949 return graphics
.drawImage(image
, x
, y
, background
, observer
);
955 * @param image The image to draw
956 * @param x The x position
957 * @param y The y position
958 * @param width The width of the area to draw the image
959 * @param height The height of the area to draw the image
960 * @param background The color for the background in the opaque regions
962 * @param observer The image observer
966 public boolean drawImage(Image image
, int x
, int y
, int width
, int height
,
967 Color background
, ImageObserver observer
)
969 if ((debugOptions
& LOG_OPTION
) != 0)
971 logStream().println(prefix() + " Drawing image: " + image
972 + " at: " + new Rectangle(x
, y
, width
, height
)
973 + ", bgcolor: " + background
);
976 return graphics
.drawImage(image
, x
, y
, width
, height
, background
, observer
);
982 * @param image The image to draw
991 * @param observer The image observer
995 public boolean drawImage(Image image
, int dx1
, int dy1
,
996 int dx2
, int dy2
, int sx1
, int sy1
, int sx2
, int sy2
,
997 ImageObserver observer
)
999 if ((debugOptions
& LOG_OPTION
) != 0)
1001 logStream().println(prefix() + " Drawing image: " + image
1002 + " destination: " + new Rectangle(dx1
, dy1
, dx2
, dy2
)
1003 + " source: " + new Rectangle(sx1
, sy1
, sx2
, sy2
));
1006 return graphics
.drawImage(image
, dx1
, dy1
, dx2
, dy2
, sx1
, sy1
, sx2
, sy2
, observer
);
1012 * @param image The image to draw
1021 * @param background The color for the background in the opaque regions
1023 * @param observer The image observer
1027 public boolean drawImage(Image image
, int dx1
, int dy1
,
1028 int dx2
, int dy2
, int sx1
, int sy1
, int sx2
, int sy2
,
1029 Color background
, ImageObserver observer
)
1031 if ((debugOptions
& LOG_OPTION
) != 0)
1033 logStream().println(prefix() + " Drawing image: " + image
1034 + " destination: " + new Rectangle(dx1
, dy1
, dx2
, dy2
)
1035 + " source: " + new Rectangle(sx1
, sy1
, sx2
, sy2
)
1036 + ", bgcolor: " + background
);
1039 return graphics
.drawImage(image
, dx1
, dy1
, dx2
, dy2
, sx1
, sy1
, sx2
, sy2
, background
, observer
);
1045 * @param x The x position of the source area
1046 * @param y The y position of the source area
1047 * @param width The width of the area
1048 * @param height The height of the area
1049 * @param destx The x position of the destination area
1050 * @param desty The y posiiton of the destination area
1052 public void copyArea(int x
, int y
, int width
, int height
,
1053 int destx
, int desty
)
1055 if ((debugOptions
& LOG_OPTION
) != 0)
1057 logStream().println(prefix() + " Copying area from: "
1058 + new Rectangle(x
, y
, width
, height
)
1059 + " to: " + new Point(destx
, desty
));
1062 graphics
.copyArea(x
, y
, width
, height
, destx
, desty
);
1066 * Releases all system resources that this <code>Graphics</code> is using.
1068 public void dispose()
1079 public boolean isDrawingBuffer()
1081 return false; // TODO
1087 * @param options the debug options
1089 public void setDebugOptions(int options
)
1091 debugOptions
= options
;
1092 if ((debugOptions
& LOG_OPTION
) != 0)
1093 if (options
== NONE_OPTION
)
1094 logStream().println(prefix() + "Disabling debug");
1096 logStream().println(prefix() + "Enabling debug");
1102 * @return the debug options
1104 public int getDebugOptions()
1106 return debugOptions
;
1110 * Creates and returns the prefix that should be prepended to all logging
1111 * messages. The prefix is made up like this:
1113 * <code>Graphics(<counter>-1)</code> where counter is an integer number
1114 * saying how many DebugGraphics objects have been created so far. The second
1115 * number always seem to be 1 on Sun's JDK, this has to be investigated a
1118 * @return the prefix that should be prepended to all logging
1121 private String
prefix()
1123 return "Graphics(" + counter
+ "-1)";