import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;

/** DemoPaintPanel - demonstrate painting graphics.<p>
*
* A custom inner class is defined for painting graphics:<p>
*
* <pre>
*     private class PaintPanel extends JPanel
* </pre>
*
* Extending <code>JPanel</code> is a logical choice for creating
* a custom component in which to paint graphics.  <code>JPanel</code>
* is a direct subclass of <code>JComponent</code>.  It's a relatively
* simple class with only four methods (besides those inherited from
* <code>JComponent</code>, <code>Container</code>,
* <code>Component</code>, and <code>Object</code>).  By default, a
* <code>JPanel</code> doesn't paint anything except its background.
* It serves as a general-purpose container in which to place things, and
* that's just what we need.<p>
*
* The <code>PaintPanel</code> class includes a constructor that
* sets the panel's background color (pink) and preferred size (150 x 150).
* Besides this, there is just one additional method:
*
* <pre>
*     public void paintComponent(Graphics g)
* </pre>
*
* The <code>paintComponent</code> method includes five lines that
* paint a blue ellipse:<p>
*
* <pre>
*     super.paintComponent(g);
*     Graphics2D g2 = (Graphics2D)g;
*     g2.setColor(Color.blue);
*     Ellipse2D.Double e = new Ellipse2D.Double(50, 35, 50, 80);
*     g2.draw(e);
* </pre>
*
* The first line paints the background; the next four lines
* paint the ellipse.<p>
*
* In the constructor for the application window a <code>PaintPanel</code>
* object is instantiated as expected:<p>
*
* <pre>
*     PaintPanel pp = new PaintPanel();
* </pre>
*
* The <code>PaintPanel</code> object is placed in another
* <code>JPanel</code> which becomes
* the content pane for the application window.  Nothing new here.
* <p>
*
* If you review the code for the main application window, you'll notice that 
* <code>paintComponent</code> is never invoked on the
* <code>PaintPanel</code> object!  This seems a bit peculiar, don't you
* think?  How is it that
* the blue ellipse appears in the panel when the application is run?
* This is explained as follows.<p>
*
* The principle method used by Swing to draw components is
* <code>paint</code>,
* defined in <code>JPanel's</code> superclass, <code>JComponent</code>.
* This method is called "automatically"
* whenever a component needs to be painted, for example when a component's
* state changes or when its enclosing window
* is realized or resized. 
* Applications never call <code>paint</code> directly:  It is called as
* part of the
* behind-the-scenes activity of a living, breathing Swing application.
* In fact, <code>paint</code> performs its task largely by calling 
* three
* other methods: <code>paintComponent</code>, <code>paintBorder</code>,
* and <code>paintChildren</code>, also defined in <code>JComponent</code>.
* <p>
*
* Our custom paint panel simply overrides <code>paintComponent</code>,
* providing graphics primitives to paint the ellipse.  The mystery
* is solved:  The
* <code>paintComponent</code> method
* executes "automatically" whenever our component
* needs to be painted.<p>
*
* An object of the <code>Graphics</code> class is passed as an
* argument to <code>paintComponent</code>.  This object is often
* referred to as the <i>graphics context</i> for painting.
* The <code>Graphics</code> object holds state information,
* such as the painting color and the font for painting text.  Numerous
* graphics primitives are defined in the <code>Graphics</code> class for
* rendering shapes, etc.  These are invoked on the
* <code>Graphics</code> object passed to <code>paintComponent</code>.
* It is common in Swing to cast the <code>Graphics</code> object into
* a <code>Graphics2D</code> object to gain access to additional
* and more powerful methods added since the early days
* of AWT.<p>
*
* See also Amy Fowler's article
* <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">
* Painting in AWT and Swing</a> and the lesson
* <a href="http://java.sun.com/docs/books/tutorial/uiswing/painting/index.html">
* Working with Graphics</a> in the Swing tutorial.<p>
*
* Screen snap...<br>
* <center><img src="DemoPaintPanel-1.gif"></center><p>
*
* @see <a href="DemoPaintPanel.java">source code</a>
* @author Scott MacKenzie, 2002
*/
public class DemoPaintPanel
{
   public static void main(String[] args)
   {
      // use look and feel for my system
      try {
         UIManager.setLookAndFeel(
            UIManager.getSystemLookAndFeelClassName());
      } catch (Exception e) {}

      DemoPaintPanelFrame frame = new DemoPaintPanelFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setTitle("DemoPaintPanel");
      frame.pack();
      frame.show();
   }
}

class DemoPaintPanelFrame extends JFrame
{
   public DemoPaintPanelFrame()
   {
      // ----------------------------------
      // construct and configure components
      // ----------------------------------

      PaintPanel pp = new PaintPanel();
      pp.setBorder(BorderFactory.createLineBorder(Color.gray));

      // ------------------
      // arrange components
      // ------------------

      JPanel p = new JPanel();
      p.add(pp);
      p.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

      this.setContentPane(p);
   }
  
   /** A simple class for painting an ellipse.
   */
   private class PaintPanel extends JPanel
   {
      PaintPanel()
      {
         this.setBackground(Color.pink);
         this.setPreferredSize(new Dimension(150, 150));
      }

      public void paintComponent(Graphics g)
      {
         // paint the background
         super.paintComponent(g);

         // use the newer primitives of Graphics2D
         Graphics2D g2 = (Graphics2D)g;
   
         // set painting color to 'blue'
         g2.setColor(Color.blue);
   
         // create an ellipse 
         Ellipse2D.Double e = new Ellipse2D.Double(50, 35, 50, 80);
   
         // draw the ellipse
         g2.draw(e);
      }
   }
}

