import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

/** DemoSizeProperties - demo of component size properties.<p>
*
* All Swing components are subclasses of <code>JComponent</code>.
* When a <code>JComponent</code> object is instantiated, it takes on, or
* assumes, three size properties: <i>preferred size</i>,
* <i>minimum size</i>, and <i>maximum size</i>.
* These properties are used subsequently in determining
* the actual size of the component during painting, in consideration of
* other factors such as the panel size, window size, or the
* heuristics of the layout manager.<p>
*
* In some cases, a component appears
* at its preferred size, while in other cases it appears
* at a different size.  The reasons for these differences are
* often obscure and
* difficult to understand.  This is in part due to Java's evolution
* from AWT to Swing, where old rules are "sometimes" suplanted by new ones,
* or to convoluted interactions between component sizing and positioning.
* As well, the way heurisitics filter through the containment hierarchy is
* often difficult to understand (e.g., <code>JComponent</code>
* is a subclass of <code>Container</code>).
* Consequently, grappling with problems in layout,
* sizing, and positioning is one of the most
* difficult challenges in building
* a Swing application.  This demo is an examination of
* one of the underlying issues, the size properties of
* <code>JComponent</code> objects.<p>
*
* We begin with the following declarations and initializations:<p>
*
* <pre>
*      JButton b1 = new JButton("Button One");
*      JButton b2 = new JButton("B2");
*      JLabel label = new JLabel("Hello");
*      JTextField tf1 = new JTextField();
*      JTextField tf2 = new JTextField("Hello");
*      JTextField tf3 = new JTextField("Hello", 10);
*      JTextArea ta = new JTextArea(5, 10);
* </pre>
*
* The components are then placed in a <code>JPanel</code>
* which is used as the content pane for the application window.  Note:
* The default layout manager for <code>JPanel</code>
* is <code>FlowLayout</code>.<p>
*
* Finally, the preferred size, minimum size, and maximum size properties
* assumed by each component (including the panel)
* are printed on the console as <i>width</i> x <i>height</i>.  The units
* are pixels.
* The output appears as follows:<p>
*
* <pre>
*     b1 preferred size: 95 x 27
*     b1 minimum size:   95 x 27
*     b1 maximum size:   95 x 27
*     -----
*     b2 preferred size: 49 x 27
*     b2 minimum size:   49 x 27
*     b2 maximum size:   49 x 27
*     -----
*     label preferred size: 29 x 17
*     label minimum size:   29 x 17
*     label maximum size:   29 x 17
*     -----
*     tf1 preferred size: 4 x 21
*     tf1 minimum size:   4 x 21
*     tf1 maximum size:   2147483647 x 2147483647
*     -----
*     tf2 preferred size: 33 x 21
*     tf2 minimum size:   4 x 21
*     tf2 maximum size:   2147483647 x 2147483647
*     -----
*     tf3 preferred size: 110 x 21
*     tf3 minimum size:   4 x 21
*     tf3 maximum size:   2147483647 x 2147483647
*     -----
*     ta preferred size: 70 x 85
*     ta minimum size:   0 x 17
*     ta maximum size:   2147483647 x 2147483647
*     -----
*     panel preferred size: 430 x 95
*     panel minimum size:   225 x 37
*     panel maximum size:   32767 x 32767
*     -----
* </pre>
*
* Note in the screen snap below that all components appear
* at their preferred size.<p>
*
* In most cases, the size properties are dictated by a few simple rules,
* such as the size requirements of the component's contents and
* the desired empty space around the contents.  The <code>JTextField</code>
* components, for example, have a preferred and minimum height of 21 pixels.
* This is
* enough vertical
* space for the text (determined by the font family and size)
* and a few pixels of room above and below.  The
* minimum width of the <code>JTextField</code> components is 4 pixels. This
* provides only the desired room to the left and right of an empty
* text string.  The maximum sizes of the <code>JTextField</code>
* components is <code>Integer.MAX_VALUE</code>, a simple indication 
* that these components can expand on an as-needed basis
* as text is added.<p>
*
* The panel assumes whatever size is necessary to contain
* the components, based on the heuristics of the layout manager.
* The <code>FlowLayout</code> layout manager
* positions components 5 pixels apart by default.  Consequently,
* the panel assumes a preferred width of 430 pixels:<p>
*
* <pre>
*     430 = 5 + 95 + 5 + 49 + 5 + 29 + 5 + 4 + 5 + 33 + 5 + 15 + 5 + 70 + 5 
* </pre>
*
* There are three
* additional size properties for each component -- booleans --
* indicating whether or not each size property has been explicitly set,
* or is simply the default, or "assumed", setting.
* In all cases in this demo, these are "false".  Explicitly setting component
* size properties is demonstrated in <code>DemoSizeControl</code>.<p>
*
* Screen snap...<br>
* <center><img src="DemoSizeProperties-1.gif"></center><p>
*
* @see <a href="DemoSizeProperties.java">source code</a>
* @author Scott MacKenzie, 2002
*/
public class DemoSizeProperties
{
   public static void main(String[] args)
   {
      // use look and feel for my system (Win32)
      try {
         UIManager.setLookAndFeel(
            UIManager.getSystemLookAndFeelClassName());
      } catch (Exception e) {}

      DemoSizePropertiesFrame frame = new DemoSizePropertiesFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setTitle("DemoSizeProperties");
      frame.pack();
      frame.show();
   }
}

class DemoSizePropertiesFrame extends JFrame
{
   public DemoSizePropertiesFrame()
   {
      // ----------------------------------
      // construct and configure components
      // ----------------------------------

      JButton b1 = new JButton("Button One");
      JButton b2 = new JButton("B2");
      JLabel label = new JLabel("Hello");
      JTextField tf1 = new JTextField();
      JTextField tf2 = new JTextField("Hello");
      JTextField tf3 = new JTextField("Hello", 10);
      JTextArea ta = new JTextArea(5, 10);

      b1.setName("b1");
      b2.setName("b2");
      label.setName("label");
      tf1.setName("tf1");
      tf2.setName("tf2");
      tf3.setName("tf3");
      ta.setName("ta");

      // -----------------
      // layout components
      // -----------------

      JPanel panel = new JPanel(); // default is FlowLayout
      panel.setName("panel");

      panel.add(b1);
      panel.add(b2);
      panel.add(label);
      panel.add(tf1);
      panel.add(tf2);
      panel.add(tf3);
      panel.add(ta);
      this.setContentPane(panel);

      // print the size properties on the console

      JComponent[] c = { b1, b2, label, tf1, tf2, tf3, ta, panel };
      dumpSizeProperties(c);
   }

   private void dumpSizeProperties(JComponent[] c)
   {
      for (int i = 0; i < c.length; ++i)
      {
         String name = c[i].getName();
         Dimension d1 = c[i].getPreferredSize();
         Dimension d2 = c[i].getMinimumSize();
         Dimension d3 = c[i].getMaximumSize();
   
         System.out.println(
            name + " preferred size: " + d1.width + " x " + d1.height + "\n" +
            name + " minimum size:   " + d2.width + " x " + d2.height + "\n" +
            name + " maximum size:   " + d3.width + " x " + d3.height + "\n" +
            "-----");
      }
   }
}

