/[classpath]/classpath/java/awt/GridLayout.java
ViewVC logotype

Diff of /classpath/java/awt/GridLayout.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.3 by mark, Sun Jan 13 15:45:15 2002 UTC revision 1.4 by tromey, Wed Jan 16 05:18:52 2002 UTC
# Line 1  Line 1 
1  /* GridLayout.java -- Layout components in columns and rows  // GridLayout.java - Grid-based layout engine
2     Copyright (C) 1999 Free Software Foundation, Inc.  
3    /* Copyright (C) 1999, 2000, 2002  Free Software Foundation
4    
5  This file is part of GNU Classpath.  This file is part of GNU Classpath.
6    
# Line 27  executable file might be covered by the Line 28  executable file might be covered by the
28    
29  package java.awt;  package java.awt;
30    
31  /**  import java.io.Serializable;
   * This class layouts out components in a grid patterns.  Either the  
   * number of columns or the number of rows may be specified.  If both  
   * are specified, then the number of columns is ignored and is derived  
   * from the number of rows and the total number of components.  (For  
   * example, three rows and twelve components would be laid out in a  
   * 3x4 grid).  
   *  
   * @author Aaron M. Renn (arenn@urbanophile.com)  
   */  
 public class GridLayout implements LayoutManager, java.io.Serializable  
 {  
   
 /*  
  * Instance Variables  
  */  
   
 /**  
   * @serial The number of columns in the grid.  
   */  
 private int cols;  
   
 /**  
   * @serial The number of rows in the grid.  
   */  
 private int rows;  
   
 /**  
   * @serial The horizontal gap between columns  
   */  
 private int hgap;  
   
 /**  
   * @serial The vertical gap between rows  
   */  
 private int vgap;  
   
 /*************************************************************************/  
32    
33  /*  /** This class implements a grid-based layout scheme.  Components are
34   * Constructors   * all given the same size and are laid out from left to right and top
35     * to bottom.  A GridLayout is configured with a number of rows and a
36     * number of columns.  If both are specified, then the number of
37     * columns is ignored and is derived from the number of rows and the
38     * total number of components.  If either is zero then that dimension
39     * is computed based on the actual size of the container.  An
40     * exception is thrown if an attempt is made to set both the number of
41     * rows and the number of columns to 0.  This class also supports
42     * horizontal and vertical gaps; these are used as spacing between
43     * cells.
44     *
45     * @author Tom Tromey <tromey@redhat.com>
46     * @author Aaron M. Renn (arenn@urbanophile.com)
47   */   */
48    public class GridLayout implements LayoutManager, Serializable
 /**  
   * Initializes a new instance of <code>GridLayout</code> with one  
   * row and a horizontal gap of zero.  
   */  
 public  
 GridLayout()  
 {  
   this(1, 0, 0, 0);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Initializes a new instance of <code>GridLayout</code> with the specified  
   * row and column settings.  The horizontal and vertical gaps will be  
   * set to zero.  Note that the row and column settings cannot both be  
   * zero.  If both the row and column values are non-zero, the rows value  
   * takes precedence.  
   *  
   * @param rows The number of rows in the grid.  
   * @param cols The number of columns in the grid.  
   *  
   * @exception IllegalArgumentException If the row or column values are  
   * not valid.  
   */  
 public  
 GridLayout(int rows, int cols) throws IllegalArgumentException  
 {  
   this(rows, cols, 0, 0);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Initializes a new instance of <code>GridLayout</code> with the specified  
   * row, column, horizontal gap and vertical gap settings.    
   * Note that the row and column settings cannot both be  
   * zero.  If both the row and column values are non-zero, the rows value  
   * takes precedence.  
   *  
   * @param rows The number of rows in the grid.  
   * @param cols The number of columns in the grid.  
   * @param hgap The horizontal gap between columns.  
   * @param vgap The vertical gap between rows.  
   *  
   * @exception IllegalArgumentException If the row or column values are  
   * not valid.  
   */  
 public  
 GridLayout(int rows, int cols, int hgap, int vgap)  
            throws IllegalArgumentException  
 {  
   if ((rows < 0) ||  
       (cols < 0) ||  
       (hgap < 0) ||  
       (vgap < 0) ||  
       ((rows == 0) && (cols == 0)))  
     throw new IllegalArgumentException("Bad parameters");  
   
   this.rows = rows;  
   this.cols = cols;  
   this.hgap = hgap;  
   this.vgap = vgap;  
 }  
   
 /*************************************************************************/  
   
 /*  
  * Instance Variables  
  */  
   
 /**  
   * Returns the number of rows in the grid.  
   *  
   * @return The number of rows in the grid.  
   */  
 public int  
 getRows()  
49  {  {
50    return(rows);    /** Add a new component to the layout.  This particular implementation
51  }     * does nothing.
52       * @param name The name of the component to add.
53  /*************************************************************************/     * @param component The component to add.
54       */
55  /**    public void addLayoutComponent (String name, Component comp)
56    * Sets the number of rows in the grid to the specified value.    {
57    *      // Nothing.
58    * @param rows The new number of rows in the grid.    }
59    *  
60    * @exception IllegalArgumentException If both the row and column setttings    /** Return the number of columns in this layout.  */
61    * would be set to zero, or the specified value of the rows setting is    public int getColumns ()
62    * less than zero.    {
63    */      return cols;
64  public void    }
65  setRows(int rows)  
66  {    /** Return the horizontal gap.  */
67    if ((rows < 0) ||    public int getHgap ()
68        ((rows == 0) && (cols == 0)))    {
69      throw new IllegalArgumentException("Bad rows value");      return hgap;
70      }
71    this.rows = rows;  
72  }    /** Return the number of rows in this layout.  */
73      public int getRows ()
74  /*************************************************************************/    {
75        return rows;
76  /**    }
77    * Returns the number of columns in the grid.  
78    *    /** Return the vertical gap.  */
79    * @return The number of columns in the grid.    public int getVgap ()
80    */    {
81  public int      return vgap;
82  getColumns()    }
83  {  
84    return(cols);    /** Create a new <code>GridLayout</code> with one row and any number
85  }     * of columns.  Both gaps are set to 0.
86       */
87  /*************************************************************************/    public GridLayout ()
88      {
89        this (1, 0, 0, 0);
90      }
91    
92      /** Create a new <code>GridLayout</code> with the specified number
93       * of rows and columns.  Both gaps are set to 0.  Note that the row
94       * and column settings cannot both be zero.  If both the row and
95       * column values are non-zero, the rows value takes precedence.
96       * @param rows Number of rows
97       * @param cols Number of columns
98       * @exception IllegalArgumentException If rows and columns are both
99       *        0, or if either are negative
100       */
101      public GridLayout (int rows, int cols)
102      {
103        this (rows, cols, 0, 0);
104      }
105    
106      /** Create a new GridLayout with the specified number of rows and
107       * columns and the specified gaps.
108       * Note that the row and column settings cannot both be
109       * zero.  If both the row and column values are non-zero, the rows value
110       * takes precedence.
111       * @param rows Number of rows
112       * @param cols Number of columns
113       * @param hgap The horizontal gap
114       * @param vgap The vertical gap
115       * @exception IllegalArgumentException If rows and columns are both
116       *        0, if either are negative, or if either gap is negative
117       */
118      public GridLayout (int rows, int cols, int hgap, int vgap)
119      {
120        if (rows < 0)
121          throw new IllegalArgumentException ("number of rows cannot be negative");
122        if (cols < 0)
123          throw new IllegalArgumentException ("number of columns cannot be negative");
124        if (rows == 0 && cols == 0)
125          throw new IllegalArgumentException ("both rows and columns cannot be 0");
126        if (hgap < 0)
127          throw new IllegalArgumentException ("horizontal gap must be nonnegative");
128        if (vgap < 0)
129          throw new IllegalArgumentException ("vertical gap must be nonnegative");
130        this.rows = rows;
131        this.cols = cols;
132        this.hgap = hgap;
133        this.vgap = vgap;
134      }
135    
136      /** Lay out the container's components based on current settings.
137       * The free space in the container is divided evenly into the specified
138       * number of rows and columns in this object.
139       * @param parent The container to lay out
140       */
141      public void layoutContainer (Container parent)
142      {
143        int num = parent.ncomponents;
144        // This is more efficient than calling getComponents().
145        Component[] comps = parent.component;
146    
147        int real_rows = rows;
148        int real_cols = cols;
149        if (real_rows == 0)
150          real_rows = (num + real_cols - 1) / real_cols;
151        else
152          real_cols = (num + real_rows - 1) / real_rows;
153    
154        // We might have less than a single row.  In this case we expand
155        // to fill.
156        if (num < real_cols)
157          real_cols = num;
158    
159        Dimension d = parent.getSize ();
160        Insets ins = parent.getInsets ();
161    
162        // Compute width and height of each cell in the grid.
163        int tw = d.width - ins.left - ins.right;
164        tw = (tw - (real_rows - 1) * hgap) / real_rows;
165        int th = d.height - ins.top - ins.bottom;
166        th = (th - (real_cols - 1) * vgap) / real_cols;
167    
168        // If the cells are too small, still try to do something.
169        if (tw < 0)
170          tw = 1;
171        if (th < 0)
172          th = 1;
173    
174        int x = ins.left;
175        int y = ins.top;
176        int i = 0;
177        int recount = 0;
178    
179  /**      while (i < num)
   * Sets the number of columns in the grid to the specified value.  
   *  
   * @param cols The new number of columns in the grid.  
   *  
   * @exception IllegalArgumentException If both the row and column setttings  
   * would be set to zero, or the specified value of the columns setting is  
   * less than zero.  
   */  
 public void  
 setColumns(int cols) throws IllegalArgumentException  
 {  
   if ((cols < 0) ||  
       ((cols == 0) && (rows == 0)))  
     throw new IllegalArgumentException("Bad columns value");  
   
   this.cols = cols;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the horiztonal gap between columns.  
   *  
   * @return The horizontal gap between columns.  
   */  
 public int  
 getHgap()  
 {  
   return(hgap);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Sets the horiztonal gap between columns to the specified value.  
   *  
   * @param hgap The new horizontal gap value.  
   *  
   * @exception IllegalArgumentException If the hgap value is less than zero.  
   */  
 public void  
 setHgap(int hgap) throws IllegalArgumentException  
 {  
   if (hgap < 0)  
     throw new IllegalArgumentException("hgap is negative: " + hgap);  
   
   this.hgap = hgap;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the vertical gap between rows.  
   *  
   * @return The vertical gap between rows.  
   */  
 public int  
 getVgap()  
 {  
   return(vgap);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Sets the vertical gap between rows to the specified value.  
   *  
   * @param vgap The new vertical gap value.  
   *  
   * @exception IllegalArgumentException If the vgap value is less than zero.  
   */  
 public void  
 setVgap(int vgap) throws IllegalArgumentException  
 {  
   if (vgap < 0)  
     throw new IllegalArgumentException("vgap is negative: " + vgap);  
   
   this.vgap = vgap;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Adds the specified component to this layout with the given name.  
   *  
   * @param name The name of the component to add.  
   * @param component The component to add.  
   */  
 public void  
 addLayoutComponent(String name, Component component)  
 {  
   // Not needed in this class.  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Removes the specified component from this layout.  
   *  
   * @param component The component to remove.  
   */  
 public void  
 removeLayoutComponent(Component component)  
 {  
   // Not needed in this class.  
 }  
   
 /*************************************************************************/  
   
 private Dimension  
 calcLayoutSize(Container parent, boolean minimum)  
 {  
   int row_height = 0, col_width = 0, nrows, ncols;  
   
   Component[] clist = parent.getComponents();  
   if (clist.length > 0)  
     for(int i = 0; i < clist.length; i++)  
180        {        {
181           Dimension dim;          comps[i].setBounds (x, y, tw, th);
          if (minimum)  
            dim = clist[i].getMinimumSize();  
          else  
           dim = clist[i].getPreferredSize();  
   
          if (dim.width > col_width)  
            col_width = dim.width;  
182    
183           if (dim.height > row_height)          ++i;
184             row_height = dim.height;          ++recount;
185            if (recount == real_cols)
186              {
187                recount = 0;
188                y += vgap + th;
189                x = ins.left;
190              }
191            else
192              x += hgap + tw;
193        }        }
194      }
195    
196    int cnum = parent.getComponentCount();    /** Get the minimum layout size of the container.
197       * @param cont The parent container
198    if (rows > 0)     */
199      {    public Dimension minimumLayoutSize (Container cont)
200        nrows = rows;    {
201        ncols = cnum / nrows;      return getSize (cont, true);
202        if ((cnum % nrows) != 0)    }
203          ++ncols;  
204      }    /** Get the preferred layout size of the container.
205    else     * @param cont The parent container
206      {     */
207        ncols = cols;    public Dimension preferredLayoutSize (Container cont)
208        nrows = cnum / ncols;    {
209        if ((cnum % ncols) != 0)      return getSize (cont, false);
210          ++nrows;    }
211      }  
212      /** Remove the indicated component from this layout manager.
213    Insets ins = parent.getInsets();     * This particular implementation does nothing.
214       * @param comp The component to remove
215    int width = (ncols * col_width) + ((ncols + 1) * hgap) + ins.left +     */
216                ins.right;    public void removeLayoutComponent (Component comp)
217    int height = (nrows * row_height) + ((nrows + 1) * vgap) + ins.top +    {
218                 ins.bottom;      // Nothing.
219      }
220    return(new Dimension(width, height));  
221  }    /** Set the number of columns.
222       * @param newCols
223  /*************************************************************************/     * @exception IllegalArgumentException If the number of columns is
224       *     negative, or if the number of columns is zero and the number
225  /**     *     of rows is already 0.
226    * Calculates the minimum size of this layout for the specified container.     */
227    * This will calculate using the minimum size of the components in the    public void setColumns (int newCols)
228    * container, the horizontal and vertical padding of this layout, and    {
229    * the container inset values.      if (cols < 0)
230    *        throw new IllegalArgumentException ("number of columns cannot be negative");
231    * @param parent The container to calculate the minimum layout size for.      if (newCols == 0 && rows == 0)
232    */        throw new IllegalArgumentException ("number of rows is already 0");
233  public Dimension      this.cols = newCols;
234  minimumLayoutSize(Container parent)    }
235  {  
236    return(calcLayoutSize(parent, true));    /** Set the horizontal gap
237  }     * @param hgap The horizontal gap
238       * @exception IllegalArgumentException If the hgap value is less than zero.
239  /*************************************************************************/     */
240      public void setHgap (int hgap)
241      {
242        if (hgap < 0)
243          throw new IllegalArgumentException ("horizontal gap must be nonnegative");
244        this.hgap = hgap;
245      }
246    
247      /** Set the number of rows
248       * @param newRows
249       * @exception IllegalArgumentException If the number of rows is
250       *     negative, or if the number of rows is zero and the number
251       *     of columns is already 0.
252       */
253      public void setRows (int newRows)
254      {
255        if (rows < 0)
256          throw new IllegalArgumentException ("number of rows cannot be negative");
257        if (newRows == 0 && cols == 0)
258          throw new IllegalArgumentException ("number of columns is already 0");
259        this.rows = newRows;
260      }
261    
262      /** Set the vertical gap.
263       * @param vgap The vertical gap
264       * @exception IllegalArgumentException If the vgap value is less than zero.
265       */
266      public void setVgap (int vgap)
267      {
268        if (vgap < 0)
269          throw new IllegalArgumentException ("vertical gap must be nonnegative");
270        this.vgap = vgap;
271      }
272    
273      /** Return String description of this object.  */
274      public String toString ()
275      {
276        return ("[" + getClass ().getName ()
277                + ",hgap=" + hgap + ",vgap=" + vgap
278                + ",rows=" + rows + ",cols=" + cols
279                + "]");
280      }
281    
282      // This method is used to compute the various sizes.
283      private Dimension getSize (Container parent, boolean is_min)
284      {
285        int w = 0, h = 0, num = parent.ncomponents;
286        // This is more efficient than calling getComponents().
287        Component[] comps = parent.component;
288    
289  /**      for (int i = 0; i < num; ++i)
290    * Calculates the preferred size of this layout for the specified container.        {
291    * This will calculate using the preferred size of the components in the          Dimension d;
   * container, the horizontal and vertical padding of this layout, and  
   * the container inset values.  
   *  
   * @param parent The container to calculate the preferred layout size for.  
   */  
 public Dimension  
 preferredLayoutSize(Container parent)  
 {  
   return(calcLayoutSize(parent, false));  
 }  
   
 /*************************************************************************/  
292    
293  /**          if (is_min)
294    * Lays out the specified container using the constraints in this object.            d = comps[i].getMinimumSize ();
295    * The free space in the container is divided evenly into the specified          else
296    * number of rows and columns in this object.            d = comps[i].getPreferredSize ();
   *  
   * @param parent The container to layout.  
   */  
 public void  
 layoutContainer(Container parent)  
 {  
   Insets ins = parent.getInsets();  
   Dimension psize = parent.getSize();  
   int cnum = parent.getComponentCount();  
   if (cnum == 0)  
     return;  
   
   int nrows, ncols;  
   if (rows > 0)  
     {  
       if (cnum < rows)  
         nrows = cnum;  
       else  
         nrows = rows;  
   
       ncols = cnum / nrows;  
       if ((cnum % nrows) != 0)  
         ++ncols;  
     }  
   else  
     {  
       if (cnum < cols)  
         ncols = cnum;  
       else  
         ncols = cols;  
   
       nrows = cnum / ncols;  
       if ((cnum % ncols) != 0)  
         ++nrows;  
     }  
   
   int freew = psize.width - (ins.left + ins.right + ((ncols + 1) * hgap));  
   int freeh = psize.height - (ins.top + ins.bottom + ((nrows + 1) * vgap));  
   if ((freew < 0) || (freeh < 0))  
     return; // Give up  
   
   int col_width = freew / ncols;  
   int row_height = freew / nrows;  
   
   Component[] clist = parent.getComponents();  
   int cur_row = 1;  
   int cur_col = 1;  
   for (int i = 0; i < clist.length; i++)  
     {  
       // FIXME: What do we do about components that would be smaller  
       // than their minimum size.  
       int new_width, new_height, new_x, new_y;  
       
       Dimension maxsize = clist[i].getMaximumSize();  
       if (maxsize.width > col_width)  
         new_width = col_width;  
       else  
         new_width = maxsize.width;  
   
       if (maxsize.height > row_height)  
         new_height = row_height;  
       else  
         new_height = maxsize.height;  
   
       new_x = ins.left + (cur_col * col_width) + ((cur_col + 1) * hgap);  
       new_y = ins.top + (cur_row * row_height) + ((cur_row + 1) * vgap);  
   
       clist[i].setLocation(new_x, new_y);  
       clist[i].setSize(new_width, new_height);  
   
       ++cur_col;  
       if (cur_col == ncols)  
         {  
           ++cur_row;  
           cur_col = 1;  
         }  
     }  
 }  
297    
298  /*************************************************************************/          w = Math.max (d.width, w);
299            h = Math.max (d.height, h);
300          }
301    
302  /**      int real_rows = rows;
303    * Returns a string representation of this object.      int real_cols = cols;
304    *      if (real_rows == 0)
305    * @return A string representation of this object.        real_rows = (num + real_cols - 1) / real_cols;
306    */      else
307  public String        real_cols = (num + real_rows - 1) / real_rows;
308  toString()  
309  {      Insets ins = parent.getInsets ();
310    return(getClass().getName() + "(rows=" + getRows() + ",cols=" + getColumns() +      // We subtract out an extra gap here because the gaps are only
311           ",hgap=" + getHgap() + ",vgap=" + getVgap() + ")");      // between cells.
312        w = ins.left + ins.right + real_rows * (w + hgap) - hgap;
313        h = ins.top + ins.bottom + real_cols * (h + vgap) - vgap;
314        return new Dimension (w, h);
315      }
316    
317      /**
318       * @serial The number of columns in the grid.
319       */
320      private int cols;
321    
322      /**
323       * @serial The number of rows in the grid.
324       */
325      private int rows;
326    
327      /**
328       * @serial The horizontal gap between columns
329       */
330      private int hgap;
331    
332      /**
333       * @serial The vertical gap between rows
334       */
335      private int vgap;
336  }  }
   
 } // class GridLayout  
   

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26