SwingTest03.java

package com.bozoid.cis370.hw03;

import java.awt.*;
import javax.swing.*;
import java.awt.geom.*; // for Shape2D
import java.awt.font.*; // for Font
import java.util.Random;


/**
CIS370-011 homework #3.

@author Walt Leipold
*/
public class SwingTest03 extends JFrame
{
    /**
    Display a window full of random shapes.
    */
    public static void main(String argv[])
    {
        SwingTest03 f = new SwingTest03();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.show();
    }


    /**
    Create a JFrame, 3/4 of screen size and centered, and
    display a set of random shapes.
    */
    public SwingTest03()
    {
        Toolkit kit = Toolkit.getDefaultToolkit();
        Dimension ss = kit.getScreenSize();

        // Window is 3/4 of screen size, centered.
        setSize(3*ss.width/4,3*ss.height/4);
        setLocation(ss.width/8,ss.height/8);

        setTitle("CISC370-011 homework #3");

        SwingPanel03 sp = new SwingPanel03(NSHAPES);
        Container contentPane = getContentPane();
        contentPane.add(sp);
    }


    private static final int NSHAPES = 12;
}


/**
A JPanel which displays a random set of 2D shapes.
*/
class SwingPanel03 extends JPanel
{
    public SwingPanel03(int nshapes)
    {
        this.nshapes = nshapes;
    }


    public void paintComponent(Graphics g)
    {
        System.out.println("paintComponent()...");

        super.paintComponent(g);

        // The first time this panel is instantiated, create an 
        // array of random shapes.
        if (shapes == null) {
            double xmin = 0.0;
            double ymin = 0.0;
            double xmax = (double)getWidth();
            double ymax = (double)getHeight();
            shapes = new ShapeEntry[nshapes];
            for (int i=0; i<shapes.length; i++) {
                shapes[i] = new ShapeEntry(i,xmin,ymin,xmax,ymax);
                System.out.println(shapes[i]);
                }
            }

        setBackground(Color.WHITE);
        for (int i=0; i<shapes.length; i++)
            shapes[i].paintMe(g);
    }


    /**
    A randomly-generated shape.
    */
    private class ShapeEntry
    {
        /**
        Create a randomly-generated ShapeEntry whose name includes 
        the specified integer, whose minimum dimensions are at least 
        10 pixels and at most 3/4 of the window dimensions, and at 
        least half of which is within the specified bounds.

        @param shapeNum 'shape number', used for label
        @param xmin low x-coordinate of window
        @param ymin low y-coordinate of window
        @param xmax high x-coordinate of window
        @param ymax high y-coordinate of window
        */
        public ShapeEntry(int shapeNum,
            double xmin,double ymin,
            double xmax,double ymax)
        {

            // Window sizes.
            double xwin = xmax - xmin;
            double ywin = ymax - ymin;
            // Size between 10 pixels and 3/4 of window height.
            double w = 10.0 + r.nextDouble() * (0.75*xwin - 10.0);
            double h = 10.0 + r.nextDouble() * (0.75*ywin - 10.0);
            // Location random (but at least half of shape on window).
            double x = xmin + -w/2.0 + r.nextDouble()*xwin;
            double y = ymin + -h/2.0 + r.nextDouble()*ywin;

            int flag = r.nextInt(4);
            if (flag == 0) {
                // Ellipse2D
                name = "Ellipse2D " + shapeNum;
                shape = new Ellipse2D.Double(x,y,w,h);
                }
            else if (flag == 1) {
                // RoundedRectangle2D
                double arcw = r.nextDouble()*w/10.0;
                double arch = r.nextDouble()*h/10.0;
                name = "RoundRectangle2D " + shapeNum;
                shape = new RoundRectangle2D.Double(x,y,w,h,
                    arcw,arch);
                }
            else if (flag == 2) {
                // Rectangle2D
                name = "Rectangle2D " + shapeNum;
                shape = new Rectangle2D.Double(x,y,w,h);
                }
            else {
                // Line2D
                name = "Line2D " + shapeNum;
                shape = new Line2D.Double(x,y,x+w,y+h);
                }
            center = 
                new Point2D.Double(x+w/2.0,y+h/2.0);
            color = new Color(
                r.nextInt(256),
                r.nextInt(256),
                r.nextInt(256));
            compColor = new Color(
                (color.getRed()+128)%256,
                (color.getGreen()+128)%256,
                (color.getBlue()+128)%256);
        }

        /**
        Draw this <code>ShapeEntry</code>.

        @param g a <code>Graphics</code> object on which to draw
        */
        public void paintMe(Graphics g)
        {
            Rectangle2D bounds;
            LineMetrics fmetrics;
            FontRenderContext fcontext;
 
            Graphics2D g2 = (Graphics2D)g;
            g2.setFont(f);
            fcontext = g2.getFontRenderContext();

             // Draw (or fill) the shape.
            g2.setPaint(color);
            if (shape instanceof Line2D)
                g2.draw(shape);
            else
                g2.fill(shape);

            // Label the shape (in a contrasting color).
            g2.setPaint(compColor);
            bounds = f.getStringBounds(name,fcontext);
            fmetrics = f.getLineMetrics(name,fcontext);
            double cx = center.getX();
            double cy = center.getY();
            double x = cx - bounds.getWidth()/2.0;
            double y = cy - bounds.getHeight()/2.0;
            // 'y' is the top of the String bounding box.
            // Move down to the baseline before drawing.
            y -= bounds.getY() + (double)fmetrics.getLeading();
            g2.drawString(name,(int)x,(int)y);
        }

        public String toString()
        {
            Rectangle bounds = shape.getBounds();
            return "ShapeEntry[" + 
                "name=" + name + "," +
                "color=" + color + "," +
                "bounds=(" + 
                    "x=" + bounds.x + "," +
                    "y=" + bounds.y + "," +
                    "w=" + bounds.width + "," +
                    "h=" + bounds.height + ")" +
                "]";
        }

        Shape shape = null;
        Color color = null;
        Color compColor = null;
        String name = null;
        Point2D center = null;
        private Font f = new Font("Monospaced",Font.PLAIN,12);
    }


    int nshapes = 0;
    private static Random r = new Random();
    private ShapeEntry shapes[] = null;
}