home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / jfc.bin / BoxLayout.java < prev    next >
Text File  |  1998-02-26  |  12KB  |  382 lines

  1. /*
  2.  * @(#)BoxLayout.java    1.14 98/02/06
  3.  *
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  *
  19.  */
  20.  
  21.  
  22. package com.sun.java.swing;
  23.  
  24. import java.awt.*;
  25. import java.io.Serializable;
  26. import java.io.PrintStream;
  27.  
  28. /**
  29.  * A layout manager that places each of its managed components
  30.  * from left to right 
  31.  * or from top to bottom.
  32.  * When you create a BoxLayout,
  33.  * you specify whether its major axis is the X axis
  34.  * (which means left to right placement) 
  35.  * or Y axis (top to bottom placement).
  36.  * Components are arranged from left to right (or top to bottom),
  37.  * in the same order as they were added to the container.
  38.  *
  39.  * <p>
  40.  *
  41.  * [A figure should go here.] <!-- XXX -->
  42.  *
  43.  * <p>
  44.  *
  45.  * Instead of using BoxLayout directly,
  46.  * many programs use the Box class.
  47.  * The Box class provides a lightweight container
  48.  * that uses a BoxLayout.
  49.  * Box also provides handy methods
  50.  * to help you use BoxLayout well.
  51.  * 
  52.  * <p>
  53.  *
  54.  * BoxLayout attempts to arrange components
  55.  * at their preferred widths (for left to right layout)
  56.  * or heights (for top to bottom layout).
  57.  * For a left to right layout,
  58.  * if not all the components are the same height,
  59.  * BoxLayout attempts to make all the components 
  60.  * as high as the highest component.
  61.  * If that's not possible for a particular component, 
  62.  * then BoxLayout aligns that component vertically,
  63.  * according to the component's Y alignment.
  64.  * By default, a component has an Y alignment of 0.5,
  65.  * which means that the vertical center of the component
  66.  * should have the same Y coordinate as 
  67.  * the vertical centers of other components with 0.5 Y alignment.
  68.  * 
  69.  * <p>
  70.  *
  71.  * [A figure and description should go here.] <!-- XXX -->
  72.  *
  73.  * <p>
  74.  *
  75.  * Similarly, for a vertical layout,
  76.  * BoxLayout attempts to make all components in the column
  77.  * as wide as the widest component;
  78.  * if that fails, it aligns them horizontally
  79.  * according to their X alignments.
  80.  * <p>
  81.  * Warning: serialized objects of this class will not be compatible with
  82.  *
  83.  * @see Box
  84.  * @see Component#getAlignmentX
  85.  * @see Component#getAlignmentY
  86.  *
  87.  * @author   Timothy Prinzing
  88.  * @version  1.14 02/06/98
  89.  */
  90. public class BoxLayout implements LayoutManager2, Serializable {
  91.  
  92.     /**
  93.      * Specifies that components should be laid out left to right.
  94.      */
  95.     public static final int X_AXIS = 0;
  96.     
  97.     /**
  98.      * Specifies that components should be laid out top to buttom.
  99.      */
  100.     public static final int Y_AXIS = 1;
  101.  
  102.     /**
  103.      * Creates a layout manager that will lay out components either 
  104.      * left to right or
  105.      * top to bottom,
  106.      * as specified in the <code>axis</code> parameter.  
  107.      *
  108.      * @param target  the container that needs to be laid out
  109.      * @param axis  the axis to lay out components along.
  110.      *              For left-to-right layout, 
  111.      *              specify <code>BoxLayout.X_AXIS</code>;
  112.      *              for top-to-bottom layout, 
  113.      *              specify <code>BoxLayout.Y_AXIS</code>
  114.      *
  115.      * @exception AWTError  if the value of <code>axis</code> is invalid 
  116.      */
  117.     public BoxLayout(Container target, int axis) {
  118.     if (axis != X_AXIS && axis != Y_AXIS) {
  119.         throw new AWTError("Invalid axis");
  120.     }
  121.     this.axis = axis;
  122.     this.target = target;
  123.     }
  124.  
  125.     /**
  126.      * Constructs a BoxLayout that 
  127.      * produces debugging messages.
  128.      *
  129.      * @param target  the container that needs to be laid out
  130.      * @param axis  the axis to lay out components along; can be either
  131.      *              <code>BoxLayout.X_AXIS</code>
  132.      *              or <code>BoxLayout.Y_AXIS</code>
  133.      * @param dbg  the stream to which debugging messages should be sent
  134.      */
  135.     BoxLayout(Container target, int axis, PrintStream dbg) {
  136.     this(target, axis);
  137.     this.dbg = dbg;
  138.     }
  139.  
  140.     /**
  141.      * Indicates that a child has changed its layout related information,
  142.      * and thus any cached calculations should be flushed.
  143.      *
  144.      * @param target  the affected container
  145.      *
  146.      * @exception AWTError  if the target isn't the container specified to the
  147.      *                      BoxLayout constructor
  148.      */
  149.     public void invalidateLayout(Container target) {
  150.     checkContainer(target);
  151.     xChildren = null;
  152.     yChildren = null;
  153.     xTotal = null;
  154.     yTotal = null;
  155.     }
  156.  
  157.     /**
  158.      * Not used by this class.
  159.      */
  160.     public void addLayoutComponent(String name, Component comp) {
  161.     }
  162.  
  163.     /**
  164.      * Not used by this class.
  165.      */
  166.     public void removeLayoutComponent(Component comp) {
  167.     }
  168.  
  169.     /**
  170.      * Not used by this class.
  171.      */
  172.     public void addLayoutComponent(Component comp, Object constraints) {
  173.     }
  174.  
  175.     /**
  176.      * Returns the preferred dimensions for this layout, given the components
  177.      * in the specified target container.
  178.      *
  179.      * @param target  the container that needs to be laid out
  180.      *
  181.      * @exception AWTError  if the target isn't the container specified to the
  182.      *                      BoxLayout constructor
  183.      * @see Container
  184.      * @see #minimumLayoutSize
  185.      * @see #maximumLayoutSize
  186.      */
  187.     public Dimension preferredLayoutSize(Container target) {
  188.     checkContainer(target);
  189.     checkRequests();
  190.  
  191.     Dimension size = new Dimension(xTotal.preferred, yTotal.preferred);
  192.     Insets insets = target.getInsets();
  193.     size.width = (int) Math.min((long) size.width + (long) insets.left + (long) insets.right, Integer.MAX_VALUE);
  194.     size.height = (int) Math.min((long) size.height + (long) insets.top + (long) insets.bottom, Integer.MAX_VALUE);
  195.     return size;
  196.     }
  197.  
  198.     /**
  199.      * Returns the minimum dimensions needed to layout the components
  200.      * contained in the specified target container.
  201.      *
  202.      * @param target  the container that needs to be laid out 
  203.      *
  204.      * @exception AWTError  if the target isn't the container specified to the
  205.      *                      BoxLayout constructor
  206.      * @see #preferredLayoutSize
  207.      * @see #maximumLayoutSize
  208.      */
  209.     public Dimension minimumLayoutSize(Container target) {
  210.     checkContainer(target);
  211.     checkRequests();
  212.  
  213.     Dimension size = new Dimension(xTotal.minimum, yTotal.minimum);
  214.     Insets insets = target.getInsets();
  215.     size.width = (int) Math.min((long) + size.width + (long) insets.left + (long) insets.right, Integer.MAX_VALUE);
  216.     size.height = (int) Math.min((long) + size.height + (long) insets.top + (long) insets.bottom, Integer.MAX_VALUE);
  217.     return size;
  218.     }
  219.  
  220.     /**
  221.      * Returns the minimum dimensions needed to lay out the components
  222.      * contained in the specified target container.
  223.      *
  224.      * @param target  the container that needs to be laid out 
  225.      *
  226.      * @exception AWTError  if the target isn't the container specified to the
  227.      *                      BoxLayout constructor
  228.      * @see #preferredLayoutSize
  229.      * @see #minimumLayoutSize
  230.      */
  231.     public Dimension maximumLayoutSize(Container target) {
  232.     checkContainer(target);
  233.     checkRequests();
  234.  
  235.     Dimension size = new Dimension(xTotal.maximum, yTotal.maximum);
  236.     Insets insets = target.getInsets();
  237.     size.width = (int) Math.min((long) size.width + (long) insets.left + (long) insets.right, Integer.MAX_VALUE);
  238.     size.height = (int) Math.min((long) size.height + (long) insets.top + (long) insets.bottom, Integer.MAX_VALUE);
  239.     return size;
  240.     }
  241.  
  242.     /**
  243.      * Returns the alignment along the X axis for the container.
  244.      * If the box is horizontal, the default
  245.      * alignment will be returned. Otherwise, the alignment needed
  246.      * to place the children along the X axis will be returned.
  247.      *
  248.      * @param target  the container that needs to be laid out 
  249.      *
  250.      * @exception AWTError  if the target isn't the container specified to the
  251.      *                      BoxLayout constructor
  252.      */
  253.     public float getLayoutAlignmentX(Container target) {
  254.     checkContainer(target);
  255.     checkRequests();
  256.     return xTotal.alignment;
  257.     }
  258.  
  259.     /**
  260.      * Returns the alignment along the Y axis for the container.
  261.      * If the box is vertical, the default
  262.      * alignment will be returned. Otherwise, the alignment needed
  263.      * to place the children along the Y axis will be returned.
  264.      *
  265.      * @param target  the container that needs to be laid out 
  266.      *
  267.      * @exception AWTError  if the target isn't the container specified to the
  268.      *                      BoxLayout constructor
  269.      */
  270.     public float getLayoutAlignmentY(Container target) {
  271.     checkContainer(target);
  272.     checkRequests();
  273.     return yTotal.alignment;
  274.     }
  275.  
  276.     /**
  277.      * Called by the AWT <!-- XXX CHECK! --> when the specified container
  278.      * needs to be laid out.
  279.      *
  280.      * @param target  the container to lay out
  281.      *
  282.      * @exception AWTError  if the target isn't the container specified to the
  283.      *                      BoxLayout constructor
  284.      */
  285.     public void layoutContainer(Container target) {
  286.     checkContainer(target);
  287.     checkRequests();
  288.     
  289.     int nChildren = target.getComponentCount();
  290.     int[] xOffsets = new int[nChildren];
  291.     int[] xSpans = new int[nChildren];
  292.     int[] yOffsets = new int[nChildren];
  293.     int[] ySpans = new int[nChildren];
  294.  
  295.     // determine the child placements
  296.     Dimension alloc = target.getSize();
  297.     Insets in = target.getInsets();
  298.     alloc.width -= in.left + in.right;
  299.     alloc.height -= in.top + in.bottom;
  300.     if (axis == X_AXIS) {
  301.         SizeRequirements.calculateTiledPositions(alloc.width, xTotal,
  302.                              xChildren, xOffsets,
  303.                              xSpans);
  304.         SizeRequirements.calculateAlignedPositions(alloc.height, yTotal,
  305.                                yChildren, yOffsets,
  306.                                ySpans);
  307.     } else {
  308.         SizeRequirements.calculateAlignedPositions(alloc.width, xTotal,
  309.                                    xChildren, xOffsets,
  310.                                xSpans);
  311.         SizeRequirements.calculateTiledPositions(alloc.height, yTotal,
  312.                                 yChildren, yOffsets,
  313.                              ySpans);
  314.     }
  315.  
  316.     // flush changes to the container
  317.     for (int i = 0; i < nChildren; i++) {
  318.         Component c = target.getComponent(i);
  319.         c.setBounds((int) Math.min((long) in.left + (long) xOffsets[i], Integer.MAX_VALUE),
  320.             (int) Math.min((long) in.top + (long) yOffsets[i], Integer.MAX_VALUE),
  321.             xSpans[i], ySpans[i]);
  322.  
  323.     }
  324.     if (dbg != null) {
  325.         for (int i = 0; i < nChildren; i++) {
  326.         Component c = target.getComponent(i);
  327.         dbg.println(c.toString());
  328.         dbg.println("X: " + xChildren[i]);
  329.         dbg.println("Y: " + yChildren[i]);
  330.         }
  331.     }
  332.         
  333.     }
  334.  
  335.     void checkContainer(Container target) {
  336.     if (this.target != target) {
  337.         throw new AWTError("BoxLayout can't be shared");
  338.     }
  339.     }
  340.     
  341.     void checkRequests() {
  342.     if (xChildren == null || yChildren == null) {
  343.         // The requests have been invalidated... recalculate
  344.         // the request information.
  345.         int n = target.getComponentCount();
  346.         xChildren = new SizeRequirements[n];
  347.         yChildren = new SizeRequirements[n];
  348.         for (int i = 0; i < n; i++) {
  349.         Component c = target.getComponent(i);
  350.         Dimension min = c.getMinimumSize();
  351.         Dimension typ = c.getPreferredSize();
  352.         Dimension max = c.getMaximumSize();
  353.         xChildren[i] = new SizeRequirements(min.width, typ.width, 
  354.                             max.width, 
  355.                             c.getAlignmentX());
  356.         yChildren[i] = new SizeRequirements(min.height, typ.height, 
  357.                             max.height, 
  358.                             c.getAlignmentY());
  359.         }
  360.         
  361.         if (axis == X_AXIS) {
  362.         xTotal = SizeRequirements.getTiledSizeRequirements(xChildren);
  363.         yTotal = SizeRequirements.getAlignedSizeRequirements(yChildren);
  364.         } else {
  365.         xTotal = SizeRequirements.getAlignedSizeRequirements(xChildren);
  366.         yTotal = SizeRequirements.getTiledSizeRequirements(yChildren);
  367.         }
  368.     }
  369.     }
  370.         
  371.     private int axis;
  372.     private Container target;
  373.  
  374.     private transient SizeRequirements[] xChildren;
  375.     private transient SizeRequirements[] yChildren;
  376.     private transient SizeRequirements xTotal;
  377.     private transient SizeRequirements yTotal;
  378.     
  379.     private transient PrintStream dbg;
  380. }
  381.  
  382.