jdk/src/share/classes/java/awt/GridLayout.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 1995-2006 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package java.awt;
       
    27 
       
    28 /**
       
    29  * The <code>GridLayout</code> class is a layout manager that
       
    30  * lays out a container's components in a rectangular grid.
       
    31  * The container is divided into equal-sized rectangles,
       
    32  * and one component is placed in each rectangle.
       
    33  * For example, the following is an applet that lays out six buttons
       
    34  * into three rows and two columns:
       
    35  * <p>
       
    36  * <hr><blockquote>
       
    37  * <pre>
       
    38  * import java.awt.*;
       
    39  * import java.applet.Applet;
       
    40  * public class ButtonGrid extends Applet {
       
    41  *     public void init() {
       
    42  *         setLayout(new GridLayout(3,2));
       
    43  *         add(new Button("1"));
       
    44  *         add(new Button("2"));
       
    45  *         add(new Button("3"));
       
    46  *         add(new Button("4"));
       
    47  *         add(new Button("5"));
       
    48  *         add(new Button("6"));
       
    49  *     }
       
    50  * }
       
    51  * </pre></blockquote><hr>
       
    52  * <p>
       
    53  * If the container's <code>ComponentOrientation</code> property is horizontal
       
    54  * and left-to-right, the above example produces the output shown in Figure 1.
       
    55  * If the container's <code>ComponentOrientation</code> property is horizontal
       
    56  * and right-to-left, the example produces the output shown in Figure 2.
       
    57  * <p>
       
    58  * <center><table COLS=2 WIDTH=600 summary="layout">
       
    59  * <tr ALIGN=CENTER>
       
    60  * <td><img SRC="doc-files/GridLayout-1.gif"
       
    61  *      alt="Shows 6 buttons in rows of 2. Row 1 shows buttons 1 then 2.
       
    62  * Row 2 shows buttons 3 then 4. Row 3 shows buttons 5 then 6.">
       
    63  * </td>
       
    64  *
       
    65  * <td ALIGN=CENTER><img SRC="doc-files/GridLayout-2.gif"
       
    66  *                   alt="Shows 6 buttons in rows of 2. Row 1 shows buttons 2 then 1.
       
    67  * Row 2 shows buttons 4 then 3. Row 3 shows buttons 6 then 5.">
       
    68  * </td>
       
    69  * </tr>
       
    70  *
       
    71  * <tr ALIGN=CENTER>
       
    72  * <td>Figure 1: Horizontal, Left-to-Right</td>
       
    73  *
       
    74  * <td>Figure 2: Horizontal, Right-to-Left</td>
       
    75  * </tr>
       
    76  * </table></center>
       
    77  * <p>
       
    78  * When both the number of rows and the number of columns have
       
    79  * been set to non-zero values, either by a constructor or
       
    80  * by the <tt>setRows</tt> and <tt>setColumns</tt> methods, the number of
       
    81  * columns specified is ignored.  Instead, the number of
       
    82  * columns is determined from the specified number of rows
       
    83  * and the total number of components in the layout. So, for
       
    84  * example, if three rows and two columns have been specified
       
    85  * and nine components are added to the layout, they will
       
    86  * be displayed as three rows of three columns.  Specifying
       
    87  * the number of columns affects the layout only when the
       
    88  * number of rows is set to zero.
       
    89  *
       
    90  * @author  Arthur van Hoff
       
    91  * @since   JDK1.0
       
    92  */
       
    93 public class GridLayout implements LayoutManager, java.io.Serializable {
       
    94     /*
       
    95      * serialVersionUID
       
    96      */
       
    97     private static final long serialVersionUID = -7411804673224730901L;
       
    98 
       
    99     /**
       
   100      * This is the horizontal gap (in pixels) which specifies the space
       
   101      * between columns.  They can be changed at any time.
       
   102      * This should be a non-negative integer.
       
   103      *
       
   104      * @serial
       
   105      * @see #getHgap()
       
   106      * @see #setHgap(int)
       
   107      */
       
   108     int hgap;
       
   109     /**
       
   110      * This is the vertical gap (in pixels) which specifies the space
       
   111      * between rows.  They can be changed at any time.
       
   112      * This should be a non negative integer.
       
   113      *
       
   114      * @serial
       
   115      * @see #getVgap()
       
   116      * @see #setVgap(int)
       
   117      */
       
   118     int vgap;
       
   119     /**
       
   120      * This is the number of rows specified for the grid.  The number
       
   121      * of rows can be changed at any time.
       
   122      * This should be a non negative integer, where '0' means
       
   123      * 'any number' meaning that the number of Rows in that
       
   124      * dimension depends on the other dimension.
       
   125      *
       
   126      * @serial
       
   127      * @see #getRows()
       
   128      * @see #setRows(int)
       
   129      */
       
   130     int rows;
       
   131     /**
       
   132      * This is the number of columns specified for the grid.  The number
       
   133      * of columns can be changed at any time.
       
   134      * This should be a non negative integer, where '0' means
       
   135      * 'any number' meaning that the number of Columns in that
       
   136      * dimension depends on the other dimension.
       
   137      *
       
   138      * @serial
       
   139      * @see #getColumns()
       
   140      * @see #setColumns(int)
       
   141      */
       
   142     int cols;
       
   143 
       
   144     /**
       
   145      * Creates a grid layout with a default of one column per component,
       
   146      * in a single row.
       
   147      * @since JDK1.1
       
   148      */
       
   149     public GridLayout() {
       
   150         this(1, 0, 0, 0);
       
   151     }
       
   152 
       
   153     /**
       
   154      * Creates a grid layout with the specified number of rows and
       
   155      * columns. All components in the layout are given equal size.
       
   156      * <p>
       
   157      * One, but not both, of <code>rows</code> and <code>cols</code> can
       
   158      * be zero, which means that any number of objects can be placed in a
       
   159      * row or in a column.
       
   160      * @param     rows   the rows, with the value zero meaning
       
   161      *                   any number of rows.
       
   162      * @param     cols   the columns, with the value zero meaning
       
   163      *                   any number of columns.
       
   164      */
       
   165     public GridLayout(int rows, int cols) {
       
   166         this(rows, cols, 0, 0);
       
   167     }
       
   168 
       
   169     /**
       
   170      * Creates a grid layout with the specified number of rows and
       
   171      * columns. All components in the layout are given equal size.
       
   172      * <p>
       
   173      * In addition, the horizontal and vertical gaps are set to the
       
   174      * specified values. Horizontal gaps are placed between each
       
   175      * of the columns. Vertical gaps are placed between each of
       
   176      * the rows.
       
   177      * <p>
       
   178      * One, but not both, of <code>rows</code> and <code>cols</code> can
       
   179      * be zero, which means that any number of objects can be placed in a
       
   180      * row or in a column.
       
   181      * <p>
       
   182      * All <code>GridLayout</code> constructors defer to this one.
       
   183      * @param     rows   the rows, with the value zero meaning
       
   184      *                   any number of rows
       
   185      * @param     cols   the columns, with the value zero meaning
       
   186      *                   any number of columns
       
   187      * @param     hgap   the horizontal gap
       
   188      * @param     vgap   the vertical gap
       
   189      * @exception   IllegalArgumentException  if the value of both
       
   190      *                  <code>rows</code> and <code>cols</code> is
       
   191      *                  set to zero
       
   192      */
       
   193     public GridLayout(int rows, int cols, int hgap, int vgap) {
       
   194         if ((rows == 0) && (cols == 0)) {
       
   195             throw new IllegalArgumentException("rows and cols cannot both be zero");
       
   196         }
       
   197         this.rows = rows;
       
   198         this.cols = cols;
       
   199         this.hgap = hgap;
       
   200         this.vgap = vgap;
       
   201     }
       
   202 
       
   203     /**
       
   204      * Gets the number of rows in this layout.
       
   205      * @return    the number of rows in this layout
       
   206      * @since     JDK1.1
       
   207      */
       
   208     public int getRows() {
       
   209         return rows;
       
   210     }
       
   211 
       
   212     /**
       
   213      * Sets the number of rows in this layout to the specified value.
       
   214      * @param        rows   the number of rows in this layout
       
   215      * @exception    IllegalArgumentException  if the value of both
       
   216      *               <code>rows</code> and <code>cols</code> is set to zero
       
   217      * @since        JDK1.1
       
   218      */
       
   219     public void setRows(int rows) {
       
   220         if ((rows == 0) && (this.cols == 0)) {
       
   221             throw new IllegalArgumentException("rows and cols cannot both be zero");
       
   222         }
       
   223         this.rows = rows;
       
   224     }
       
   225 
       
   226     /**
       
   227      * Gets the number of columns in this layout.
       
   228      * @return     the number of columns in this layout
       
   229      * @since      JDK1.1
       
   230      */
       
   231     public int getColumns() {
       
   232         return cols;
       
   233     }
       
   234 
       
   235     /**
       
   236      * Sets the number of columns in this layout to the specified value.
       
   237      * Setting the number of columns has no affect on the layout
       
   238      * if the number of rows specified by a constructor or by
       
   239      * the <tt>setRows</tt> method is non-zero. In that case, the number
       
   240      * of columns displayed in the layout is determined by the total
       
   241      * number of components and the number of rows specified.
       
   242      * @param        cols   the number of columns in this layout
       
   243      * @exception    IllegalArgumentException  if the value of both
       
   244      *               <code>rows</code> and <code>cols</code> is set to zero
       
   245      * @since        JDK1.1
       
   246      */
       
   247     public void setColumns(int cols) {
       
   248         if ((cols == 0) && (this.rows == 0)) {
       
   249             throw new IllegalArgumentException("rows and cols cannot both be zero");
       
   250         }
       
   251         this.cols = cols;
       
   252     }
       
   253 
       
   254     /**
       
   255      * Gets the horizontal gap between components.
       
   256      * @return       the horizontal gap between components
       
   257      * @since        JDK1.1
       
   258      */
       
   259     public int getHgap() {
       
   260         return hgap;
       
   261     }
       
   262 
       
   263     /**
       
   264      * Sets the horizontal gap between components to the specified value.
       
   265      * @param        hgap   the horizontal gap between components
       
   266      * @since        JDK1.1
       
   267      */
       
   268     public void setHgap(int hgap) {
       
   269         this.hgap = hgap;
       
   270     }
       
   271 
       
   272     /**
       
   273      * Gets the vertical gap between components.
       
   274      * @return       the vertical gap between components
       
   275      * @since        JDK1.1
       
   276      */
       
   277     public int getVgap() {
       
   278         return vgap;
       
   279     }
       
   280 
       
   281     /**
       
   282      * Sets the vertical gap between components to the specified value.
       
   283      * @param         vgap  the vertical gap between components
       
   284      * @since        JDK1.1
       
   285      */
       
   286     public void setVgap(int vgap) {
       
   287         this.vgap = vgap;
       
   288     }
       
   289 
       
   290     /**
       
   291      * Adds the specified component with the specified name to the layout.
       
   292      * @param name the name of the component
       
   293      * @param comp the component to be added
       
   294      */
       
   295     public void addLayoutComponent(String name, Component comp) {
       
   296     }
       
   297 
       
   298     /**
       
   299      * Removes the specified component from the layout.
       
   300      * @param comp the component to be removed
       
   301      */
       
   302     public void removeLayoutComponent(Component comp) {
       
   303     }
       
   304 
       
   305     /**
       
   306      * Determines the preferred size of the container argument using
       
   307      * this grid layout.
       
   308      * <p>
       
   309      * The preferred width of a grid layout is the largest preferred
       
   310      * width of all of the components in the container times the number of
       
   311      * columns, plus the horizontal padding times the number of columns
       
   312      * minus one, plus the left and right insets of the target container.
       
   313      * <p>
       
   314      * The preferred height of a grid layout is the largest preferred
       
   315      * height of all of the components in the container times the number of
       
   316      * rows, plus the vertical padding times the number of rows minus one,
       
   317      * plus the top and bottom insets of the target container.
       
   318      *
       
   319      * @param     parent   the container in which to do the layout
       
   320      * @return    the preferred dimensions to lay out the
       
   321      *                      subcomponents of the specified container
       
   322      * @see       java.awt.GridLayout#minimumLayoutSize
       
   323      * @see       java.awt.Container#getPreferredSize()
       
   324      */
       
   325     public Dimension preferredLayoutSize(Container parent) {
       
   326       synchronized (parent.getTreeLock()) {
       
   327         Insets insets = parent.getInsets();
       
   328         int ncomponents = parent.getComponentCount();
       
   329         int nrows = rows;
       
   330         int ncols = cols;
       
   331 
       
   332         if (nrows > 0) {
       
   333             ncols = (ncomponents + nrows - 1) / nrows;
       
   334         } else {
       
   335             nrows = (ncomponents + ncols - 1) / ncols;
       
   336         }
       
   337         int w = 0;
       
   338         int h = 0;
       
   339         for (int i = 0 ; i < ncomponents ; i++) {
       
   340             Component comp = parent.getComponent(i);
       
   341             Dimension d = comp.getPreferredSize();
       
   342             if (w < d.width) {
       
   343                 w = d.width;
       
   344             }
       
   345             if (h < d.height) {
       
   346                 h = d.height;
       
   347             }
       
   348         }
       
   349         return new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap,
       
   350                              insets.top + insets.bottom + nrows*h + (nrows-1)*vgap);
       
   351       }
       
   352     }
       
   353 
       
   354     /**
       
   355      * Determines the minimum size of the container argument using this
       
   356      * grid layout.
       
   357      * <p>
       
   358      * The minimum width of a grid layout is the largest minimum width
       
   359      * of all of the components in the container times the number of columns,
       
   360      * plus the horizontal padding times the number of columns minus one,
       
   361      * plus the left and right insets of the target container.
       
   362      * <p>
       
   363      * The minimum height of a grid layout is the largest minimum height
       
   364      * of all of the components in the container times the number of rows,
       
   365      * plus the vertical padding times the number of rows minus one, plus
       
   366      * the top and bottom insets of the target container.
       
   367      *
       
   368      * @param       parent   the container in which to do the layout
       
   369      * @return      the minimum dimensions needed to lay out the
       
   370      *                      subcomponents of the specified container
       
   371      * @see         java.awt.GridLayout#preferredLayoutSize
       
   372      * @see         java.awt.Container#doLayout
       
   373      */
       
   374     public Dimension minimumLayoutSize(Container parent) {
       
   375       synchronized (parent.getTreeLock()) {
       
   376         Insets insets = parent.getInsets();
       
   377         int ncomponents = parent.getComponentCount();
       
   378         int nrows = rows;
       
   379         int ncols = cols;
       
   380 
       
   381         if (nrows > 0) {
       
   382             ncols = (ncomponents + nrows - 1) / nrows;
       
   383         } else {
       
   384             nrows = (ncomponents + ncols - 1) / ncols;
       
   385         }
       
   386         int w = 0;
       
   387         int h = 0;
       
   388         for (int i = 0 ; i < ncomponents ; i++) {
       
   389             Component comp = parent.getComponent(i);
       
   390             Dimension d = comp.getMinimumSize();
       
   391             if (w < d.width) {
       
   392                 w = d.width;
       
   393             }
       
   394             if (h < d.height) {
       
   395                 h = d.height;
       
   396             }
       
   397         }
       
   398         return new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap,
       
   399                              insets.top + insets.bottom + nrows*h + (nrows-1)*vgap);
       
   400       }
       
   401     }
       
   402 
       
   403     /**
       
   404      * Lays out the specified container using this layout.
       
   405      * <p>
       
   406      * This method reshapes the components in the specified target
       
   407      * container in order to satisfy the constraints of the
       
   408      * <code>GridLayout</code> object.
       
   409      * <p>
       
   410      * The grid layout manager determines the size of individual
       
   411      * components by dividing the free space in the container into
       
   412      * equal-sized portions according to the number of rows and columns
       
   413      * in the layout. The container's free space equals the container's
       
   414      * size minus any insets and any specified horizontal or vertical
       
   415      * gap. All components in a grid layout are given the same size.
       
   416      *
       
   417      * @param      parent   the container in which to do the layout
       
   418      * @see        java.awt.Container
       
   419      * @see        java.awt.Container#doLayout
       
   420      */
       
   421     public void layoutContainer(Container parent) {
       
   422       synchronized (parent.getTreeLock()) {
       
   423         Insets insets = parent.getInsets();
       
   424         int ncomponents = parent.getComponentCount();
       
   425         int nrows = rows;
       
   426         int ncols = cols;
       
   427         boolean ltr = parent.getComponentOrientation().isLeftToRight();
       
   428 
       
   429         if (ncomponents == 0) {
       
   430             return;
       
   431         }
       
   432         if (nrows > 0) {
       
   433             ncols = (ncomponents + nrows - 1) / nrows;
       
   434         } else {
       
   435             nrows = (ncomponents + ncols - 1) / ncols;
       
   436         }
       
   437         // 4370316. To position components in the center we should:
       
   438         // 1. get an amount of extra space within Container
       
   439         // 2. incorporate half of that value to the left/top position
       
   440         // Note that we use trancating division for widthOnComponent
       
   441         // The reminder goes to extraWidthAvailable
       
   442         int totalGapsWidth = (ncols - 1) * hgap;
       
   443         int widthWOInsets = parent.width - (insets.left + insets.right);
       
   444         int widthOnComponent = (widthWOInsets - totalGapsWidth) / ncols;
       
   445         int extraWidthAvailable = (widthWOInsets - (widthOnComponent * ncols + totalGapsWidth)) / 2;
       
   446 
       
   447         int totalGapsHeight = (nrows - 1) * vgap;
       
   448         int heightWOInsets = parent.height - (insets.top + insets.bottom);
       
   449         int heightOnComponent = (heightWOInsets - totalGapsHeight) / nrows;
       
   450         int extraHeightAvailable = (heightWOInsets - (heightOnComponent * nrows + totalGapsHeight)) / 2;
       
   451         if (ltr) {
       
   452             for (int c = 0, x = insets.left + extraWidthAvailable; c < ncols ; c++, x += widthOnComponent + hgap) {
       
   453                 for (int r = 0, y = insets.top + extraHeightAvailable; r < nrows ; r++, y += heightOnComponent + vgap) {
       
   454                     int i = r * ncols + c;
       
   455                     if (i < ncomponents) {
       
   456                         parent.getComponent(i).setBounds(x, y, widthOnComponent, heightOnComponent);
       
   457                     }
       
   458                 }
       
   459             }
       
   460         } else {
       
   461             for (int c = 0, x = (parent.width - insets.right - widthOnComponent) - extraWidthAvailable; c < ncols ; c++, x -= widthOnComponent + hgap) {
       
   462                 for (int r = 0, y = insets.top + extraHeightAvailable; r < nrows ; r++, y += heightOnComponent + vgap) {
       
   463                     int i = r * ncols + c;
       
   464                     if (i < ncomponents) {
       
   465                         parent.getComponent(i).setBounds(x, y, widthOnComponent, heightOnComponent);
       
   466                     }
       
   467                 }
       
   468             }
       
   469         }
       
   470       }
       
   471     }
       
   472 
       
   473     /**
       
   474      * Returns the string representation of this grid layout's values.
       
   475      * @return     a string representation of this grid layout
       
   476      */
       
   477     public String toString() {
       
   478         return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap +
       
   479                                        ",rows=" + rows + ",cols=" + cols + "]";
       
   480     }
       
   481 }