import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

/** DemoSize - demo of component sizes (after realization).<p>
*
* This demo is a follow on to <code>DemoSizeProperties</code>.
* Here, we shift our focus from the assumed size properties
* of components to their actual size when they appear in a window.
* <p>
*
* Usage:<p>
*
* <pre>
*     java DemoSize arg1
*
*     where 'arg1' is one of
*        f = use FlowLayout
*        g = use GridLayout
* </pre>
*
* If the demo is launched specifying "f" on the command line, the
* following output is generated:<p>
*
* <pre>
*     b1 size: 0 x 0
*     b2 size: 0 x 0
*     label size: 0 x 0
*     tf1 size: 0 x 0
*     tf2 size: 0 x 0
*     tf3 size: 0 x 0
*     ta size: 0 x 0
*     panel size: 0 x 0
*     -----
*     End of Constructor!
*     -----
*     b1 size: 95 x 27
*     b2 size: 49 x 27
*     label size: 29 x 17
*     tf1 size: 4 x 21
*     tf2 size: 33 x 21
*     tf3 size: 110 x 21
*     ta size: 70 x 85
*     panel size: 430 x 95
*     -----
* </pre>
*
* This output corresponds to the first screen snap below.
* The first group of size data is from the call to <code>dumpSizes</code>
* at the end of the constructor.  At this point, all sizes are "zero"
* because the application window is not yet realized.  When
* the window is realized, a component event occurs and
* the <code>componentResized</code> method executes.
* The <code>dumpSizes</code> method executes again from within this method.
* This generates
* the second group of size data.  As seen, all components are realized
* at their preferred size (see <code>DemoSizeProperties</code>).<p>
*
* Each time the application window is resized, another component event
* occurs, and a new set of size data is outputted, for example:<p>
*
* <pre>
*     b1 size: 95 x 27
*     b2 size: 49 x 27
*     label size: 29 x 17
*     tf1 size: 4 x 21
*     tf2 size: 33 x 21
*     tf3 size: 110 x 21
*     ta size: 70 x 85
*     panel size: 479 x 143
* </pre>
*
* As seen, all components except the panel remain at their preferred
* size.  Extra space is added around the components, as seen in 
* the second screen snap below and as reflected in the panel
* size data above (479 x 143).<p>
*
* To contrast the heurisics of different layout managers in sizing
* and resizing components, this demo can also use the
* <code>GridLayout</code> layout manager.  If "g" is used on
* the command line, the following output is generated:<p>
*
* <pre>
*     b1 size: 0 x 0
*     b2 size: 0 x 0
*     label size: 0 x 0
*     tf1 size: 0 x 0
*     tf2 size: 0 x 0
*     tf3 size: 0 x 0
*     ta size: 0 x 0
*     panel size: 0 x 0
*     -----
*     End of Constructor!
*     -----
*     b1 size: 110 x 85
*     b2 size: 110 x 85
*     label size: 110 x 85
*     tf1 size: 110 x 85
*     tf2 size: 110 x 85
*     tf3 size: 110 x 85
*     ta size: 110 x 85
*     panel size: 770 x 85
*     -----
* </pre>
*
* <code>GridLayout</code>
* sizes each component to fill a grid where each grid
* slot is the same size.  The largest of the preferred widths and heights
* dictates the overall size.  In this case, each component is sized
* to a width of 110 pixels and a height of 85 pixels, as determined
* by the preferred width of <code>tf3</code> (110) and the preferred height
* of <code>ta</code> (85).  The other size properties are ignored.
* As seen i the third screen snap below, the result is most unsavory.
* <p>
*
* Note: A simple way to prevent a component from expanding to the "grid
* size" when using <code>GridLayout</code> is to place the component in
* a <code>JPanel</code> first.  In this case, the <code>JPanel</code>
* will expand to the grid size, but the component will remain at its
* preferred size within the <code>JPanel</code>.<p>
*
* Screen snap (flow layout)...<br>
* <center><img src="DemoSize-1.gif"></center><p>
*
* Screen snap (flow layout - resized)...<br>
* <center><img src="DemoSize-2.gif"></center><p>
*
* Screen snap (grid layout)...<br>
* <center><img src="DemoSize-3.gif"></center><p>
*
* @see <a href="DemoSize.java">source code</a>
* @author Scott MacKenzie, 2002
*/
public class DemoSize
{
   public static void main(String[] args)
   {
      if (args.length != 1 || !(args[0].equals("f") || args[0].equals("g")))
      {
         usage();
         System.exit(0);
      }

      // use look and feel for my system (Win32)
      try {
         UIManager.setLookAndFeel(
            UIManager.getSystemLookAndFeelClassName());
      } catch (Exception e) {}

      DemoSizeFrame frame = new DemoSizeFrame(args[0]);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setTitle("DemoSize");
      frame.pack();
      frame.show();
   }

   private static void usage()
   {
      System.out.println("usage: java DemoSize arg1\n\n" +
         "where 'arg1' is one of\n" +
         "    f = use FlowLayout\n" +
         "    g = use GridLayout");
   }
}

class DemoSizeFrame extends JFrame implements ComponentListener
{
   JButton b1;
   JButton b2;
   JLabel label;
   JTextField tf1;
   JTextField tf2;
   JTextField tf3;
   JTextArea ta;
   JPanel panel;

   JComponent[] c = new JComponent[8];

   public DemoSizeFrame(String layoutArg)
   {
      // ----------------------------------
      // construct and configure components
      // ----------------------------------

      b1 = new JButton("Button One");
      b2 = new JButton("B2");
      label = new JLabel("Hello");
      tf1 = new JTextField();
      tf2 = new JTextField("Hello");
      tf3 = new JTextField("Hello", 10);
      ta = new JTextArea(5, 10);
      panel = new JPanel();

      b1.setName("b1");
      b2.setName("b2");
      label.setName("label");
      tf1.setName("tf1");
      tf2.setName("tf2");
      tf3.setName("tf3");
      ta.setName("ta");
      panel.setName("panel");

      c[0] = b1;
      c[1] = b2;
      c[2] = label;
      c[3] = tf1;
      c[4] = tf2;
      c[5] = tf3;
      c[6] = ta;
      c[7] = panel;

      // -----------------
      // install listeners
      // -----------------

      this.addComponentListener(this);

      // ------------------
      // arrange components
      // ------------------
      // Note: 'panel' instantiated above

      // set the layout manager, as per command line argument

      if (layoutArg.equals("f"))
         panel.setLayout(new FlowLayout());

      else if (layoutArg.equals("g"))
         panel.setLayout(new GridLayout(1, 7));

      panel.add(b1);
      panel.add(b2);
      panel.add(label);
      panel.add(tf1);
      panel.add(tf2);
      panel.add(tf3);
      panel.add(ta);
      this.setContentPane(panel);

      dumpSizes();

      System.out.println("End of Constructor!");
      System.out.println("-----");
   }

   // ----------------------------------
   // implement ComponentListener method
   // ----------------------------------

   public void componentHidden(ComponentEvent ce) {}
   public void componentMoved(ComponentEvent ce) {}
   public void componentShown(ComponentEvent ce) {}
   public void componentResized(ComponentEvent ce)
   {
      dumpSizes();
   }

   private void dumpSizes()
   {
      for (int i = 0; i < c.length; ++i)
      {
         String name = c[i].getName();
         Dimension d = c[i].getSize();   
         System.out.println(name + " size: " + d.width + " x " + d.height);
      }
      System.out.println("-----");
   }
}

