//
// another example of the Java AWT, showing use of Graphics class
//      and double buffering to reduce flicker.
// see class definition and main method for details.  compare with
//      TestPattern, which has the same specification but can exhibit
//      annoying flickering.
//
// based on example in chapter 16 of _Exploring Java_, Niemeyer & Peck.
//
import java.awt.* ;
import java.awt.event.* ;

//
// a TestPatternDB object is a DrawingFrame that displays a "test
//      pattern" (a nested arrangement of basic shapes, as on p. 475
//      of _EJ_).  the innermost shape, a quarter-circle, rotates
//      15 degrees when the user clicks the mouse.
// the object also writes a message to standard output whenever its
//      update() or paint() method is called.
//
public class TestPatternDB extends DrawingFrame {

        int theta = 45 ;        // angle for arc in test pattern.
                                //      0 is 3 o'clock;
                                //       + moves counter-clockwise.

        Image offScreenImage ;
        Graphics offScreenGC ;

        TestPatternDB(int size) {

                super("TestPatternDB") ;
                setDrawingSize(new Dimension(size, size)) ;

                // respond to mouse clicks by rotating quarter-circle
                //      shape and requesting repaint.
                addMouseListener(new MouseAdapter() {
                        public void mousePressed(MouseEvent e) {
                                theta = (theta + 15) % 360 ;
                                ShowThreads.show("in mousePressed") ;
                                repaint() ;
                        }
                } ) ;

                show() ;
                ShowThreads.showAll("after show()") ;
                ShowThreads.showAll("after show() and delay", 10) ;
        }

        // override update method to use double buffering.
        public void update(Graphics g) {
                ShowThreads.show("in update") ;
                if (offScreenImage == null) {
                        // create off-screen image area and get its
                        //      graphics context.
                        offScreenImage = createImage(
                                getSize().width, getSize().height) ;
                        offScreenGC = offScreenImage.getGraphics() ;
                        // move origin to exclude frame and border.
                        translateDrawingArea(offScreenGC) ;
                }
                // draw pattern onto off-screen area.
                drawPattern(offScreenGC) ;
                // display it.
                g.drawImage(offScreenImage, 0, 0, this) ;
        }

        // override paint method to draw "test pattern".
        public void paint(Graphics g) {
                ShowThreads.show("in paint") ;

                // move origin to exclude frame and border.
                translateDrawingArea(g) ;

                // draw pattern onto screen.
                drawPattern(g) ;
        }

        // draw "test pattern" -- common code called by update() (to
        //      draw the pattern onto the off-screen buffer) and by
        //      paint() (to draw the pattern directly onto the screen).
        private void drawPattern(Graphics g) {

                Dimension d = getDrawingSize() ;
                int W = Math.min(d.width, d.height) ;
                int H = W ;

                int halfW = W/2 ;
                int halfH = W/2 ;

                int x = (W - halfW) / 2 ;
                int y = (H - halfH) / 2 ;

                Polygon poly = new Polygon(
                        new int[] { 0, halfW, W, halfW } ,
                        new int[] { halfH, 0, halfH, H }, 
                        4 ) ;

                // make background.
                g.setColor(Color.black) ;
                g.fillRect(0, 0, W, H) ;

                // make enclosed diagonally-set square.
                g.setColor(Color.yellow) ;
                g.fillPolygon(poly) ;

                // make enclosed half-sized square.
                g.setColor(Color.red) ;
                g.fillRect(x, y, halfW, halfH) ;

                // make enclosed circle.
                g.setColor(Color.green) ;
                g.fillOval(x, y, halfW, halfH) ;

                // make filled arc (quarter-circle).
                g.setColor(Color.blue) ;
                g.fillArc(x, y, halfW, halfH, theta, 90) ;

                // make diagonal line.
                g.setColor(Color.white) ;
                g.drawLine(x, y, x+halfW, y+halfH) ;
        }

        //
        // ---- main ---------------------------------------------------
        //
        // command-line argument (optional) is size of window.
        //
        public static void main(String[] args) {
                int size = 400 ;
                if (args.length > 0)
                        size = Integer.parseInt(args[0]) ;
                TestPatternDB t = new TestPatternDB(size) ;
        }
}