1. /*
  2. * @(#)GridLayout.java 1.35 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt;
  8. /**
  9. * The <code>GridLayout</code> class is a layout manager that
  10. * lays out a container's components in a rectangular grid.
  11. * The container is divided into equal-sized rectangles,
  12. * and one component is placed in each rectangle.
  13. * For example, the following is an applet that lays out six buttons
  14. * into three rows and two columns:
  15. * <p>
  16. * <hr><blockquote>
  17. * <pre>
  18. * import java.awt.*;
  19. * import java.applet.Applet;
  20. * public class ButtonGrid extends Applet {
  21. * public void init() {
  22. * setLayout(new GridLayout(3,2));
  23. * add(new Button("1"));
  24. * add(new Button("2"));
  25. * add(new Button("3"));
  26. * add(new Button("4"));
  27. * add(new Button("5"));
  28. * add(new Button("6"));
  29. * }
  30. * }
  31. * </pre></blockquote><hr>
  32. * <p>
  33. * If the container's <code>ComponentOrientation</code> property is horizontal
  34. * and left-to-right, the above example produces the output shown in Figure 1.
  35. * If the container's <code>ComponentOrientation</code> property is horizontal
  36. * and right-to-left, the example produces the output shown in Figure 2.
  37. * <p>
  38. * <center><table COLS=2 WIDTH=600 summary="layout">
  39. * <tr ALIGN=CENTER>
  40. * <td><img SRC="doc-files/GridLayout-1.gif"
  41. * alt="Shows 6 buttons in rows of 2. Row 1 shows buttons 1 then 2.
  42. * Row 2 shows buttons 3 then 4. Row 3 shows buttons 5 then 6.">
  43. * </td>
  44. *
  45. * <td ALIGN=CENTER><img SRC="doc-files/GridLayout-2.gif"
  46. * alt="Shows 6 buttons in rows of 2. Row 1 shows buttons 2 then 1.
  47. * Row 2 shows buttons 4 then 3. Row 3 shows buttons 6 then 5.">
  48. * </td>
  49. * </tr>
  50. *
  51. * <tr ALIGN=CENTER>
  52. * <td>Figure 1: Horizontal, Left-to-Right</td>
  53. *
  54. * <td>Figure 2: Horizontal, Right-to-Left</td>
  55. * </tr>
  56. * </table></center>
  57. * <p>
  58. * When both the number of rows and the number of columns have
  59. * been set to non-zero values, either by a constructor or
  60. * by the <tt>setRows</tt> and <tt>setColumns</tt> methods, the number of
  61. * columns specified is ignored. Instead, the number of
  62. * columns is determined from the specified number or rows
  63. * and the total number of components in the layout. So, for
  64. * example, if three rows and two columns have been specified
  65. * and nine components are added to the layout, they will
  66. * be displayed as three rows of three columns. Specifying
  67. * the number of columns affects the layout only when the
  68. * number of rows is set to zero.
  69. *
  70. * @version 1.35, 01/23/03
  71. * @author Arthur van Hoff
  72. * @since JDK1.0
  73. */
  74. public class GridLayout implements LayoutManager, java.io.Serializable {
  75. /**
  76. * This is the horizontal gap (in pixels) which specifies the space
  77. * between columns. They can be changed at any time.
  78. * This should be a non-negative integer.
  79. *
  80. * @serial
  81. * @see #getHgap()
  82. * @see #setHgap(int)
  83. */
  84. int hgap;
  85. /**
  86. * This is the vertical gap (in pixels) which specifies the space
  87. * between rows. They can be changed at any time.
  88. * This should be a non negative integer.
  89. *
  90. * @serial
  91. * @see #getVgap()
  92. * @see #setVgap(int)
  93. */
  94. int vgap;
  95. /**
  96. * This is the number of rows specified for the grid. The number
  97. * of rows can be changed at any time.
  98. * This should be a non negative integer, where '0' means
  99. * 'any number' meaning that the number of Rows in that
  100. * dimension depends on the other dimension.
  101. *
  102. * @serial
  103. * @see #getRows()
  104. * @see #setRows(int)
  105. */
  106. int rows;
  107. /**
  108. * This is the number of columns specified for the grid. The number
  109. * of columns can be changed at any time.
  110. * This should be a non negative integer, where '0' means
  111. * 'any number' meaning that the number of Columns in that
  112. * dimension depends on the other dimension.
  113. *
  114. * @serial
  115. * @see #getColumns()
  116. * @see #setColumns(int)
  117. */
  118. int cols;
  119. /**
  120. * Creates a grid layout with a default of one column per component,
  121. * in a single row.
  122. * @since JDK1.1
  123. */
  124. public GridLayout() {
  125. this(1, 0, 0, 0);
  126. }
  127. /**
  128. * Creates a grid layout with the specified number of rows and
  129. * columns. All components in the layout are given equal size.
  130. * <p>
  131. * One, but not both, of <code>rows</code> and <code>cols</code> can
  132. * be zero, which means that any number of objects can be placed in a
  133. * row or in a column.
  134. * @param rows the rows, with the value zero meaning
  135. * any number of rows.
  136. * @param cols the columns, with the value zero meaning
  137. * any number of columns.
  138. */
  139. public GridLayout(int rows, int cols) {
  140. this(rows, cols, 0, 0);
  141. }
  142. /**
  143. * Creates a grid layout with the specified number of rows and
  144. * columns. All components in the layout are given equal size.
  145. * <p>
  146. * In addition, the horizontal and vertical gaps are set to the
  147. * specified values. Horizontal gaps are placed at the left and
  148. * right edges, and between each of the columns. Vertical gaps are
  149. * placed at the top and bottom edges, and between each of the rows.
  150. * <p>
  151. * One, but not both, of <code>rows</code> and <code>cols</code> can
  152. * be zero, which means that any number of objects can be placed in a
  153. * row or in a column.
  154. * <p>
  155. * All <code>GridLayout</code> constructors defer to this one.
  156. * @param rows the rows, with the value zero meaning
  157. * any number of rows
  158. * @param cols the columns, with the value zero meaning
  159. * any number of columns
  160. * @param hgap the horizontal gap
  161. * @param vgap the vertical gap
  162. * @exception IllegalArgumentException if the value of both
  163. * <code>rows</code> and <code>cols</code> is
  164. * set to zero
  165. */
  166. public GridLayout(int rows, int cols, int hgap, int vgap) {
  167. if ((rows == 0) && (cols == 0)) {
  168. throw new IllegalArgumentException("rows and cols cannot both be zero");
  169. }
  170. this.rows = rows;
  171. this.cols = cols;
  172. this.hgap = hgap;
  173. this.vgap = vgap;
  174. }
  175. /**
  176. * Gets the number of rows in this layout.
  177. * @return the number of rows in this layout
  178. * @since JDK1.1
  179. */
  180. public int getRows() {
  181. return rows;
  182. }
  183. /**
  184. * Sets the number of rows in this layout to the specified value.
  185. * @param rows the number of rows in this layout
  186. * @exception IllegalArgumentException if the value of both
  187. * <code>rows</code> and <code>cols</code> is set to zero
  188. * @since JDK1.1
  189. */
  190. public void setRows(int rows) {
  191. if ((rows == 0) && (this.cols == 0)) {
  192. throw new IllegalArgumentException("rows and cols cannot both be zero");
  193. }
  194. this.rows = rows;
  195. }
  196. /**
  197. * Gets the number of columns in this layout.
  198. * @return the number of columns in this layout
  199. * @since JDK1.1
  200. */
  201. public int getColumns() {
  202. return cols;
  203. }
  204. /**
  205. * Sets the number of columns in this layout to the specified value.
  206. * Setting the number of columns has no affect on the layout
  207. * if the number of rows specified by a constructor or by
  208. * the <tt>setRows</tt> method is non-zero. In that case, the number
  209. * of columns displayed in the layout is determined by the total
  210. * number of components and the number of rows specified.
  211. * @param cols the number of columns in this layout
  212. * @exception IllegalArgumentException if the value of both
  213. * <code>rows</code> and <code>cols</code> is set to zero
  214. * @since JDK1.1
  215. */
  216. public void setColumns(int cols) {
  217. if ((cols == 0) && (this.rows == 0)) {
  218. throw new IllegalArgumentException("rows and cols cannot both be zero");
  219. }
  220. this.cols = cols;
  221. }
  222. /**
  223. * Gets the horizontal gap between components.
  224. * @return the horizontal gap between components
  225. * @since JDK1.1
  226. */
  227. public int getHgap() {
  228. return hgap;
  229. }
  230. /**
  231. * Sets the horizontal gap between components to the specified value.
  232. * @param hgap the horizontal gap between components
  233. * @since JDK1.1
  234. */
  235. public void setHgap(int hgap) {
  236. this.hgap = hgap;
  237. }
  238. /**
  239. * Gets the vertical gap between components.
  240. * @return the vertical gap between components
  241. * @since JDK1.1
  242. */
  243. public int getVgap() {
  244. return vgap;
  245. }
  246. /**
  247. * Sets the vertical gap between components to the specified value.
  248. * @param vgap the vertical gap between components
  249. * @since JDK1.1
  250. */
  251. public void setVgap(int vgap) {
  252. this.vgap = vgap;
  253. }
  254. /**
  255. * Adds the specified component with the specified name to the layout.
  256. * @param name the name of the component
  257. * @param comp the component to be added
  258. */
  259. public void addLayoutComponent(String name, Component comp) {
  260. }
  261. /**
  262. * Removes the specified component from the layout.
  263. * @param comp the component to be removed
  264. */
  265. public void removeLayoutComponent(Component comp) {
  266. }
  267. /**
  268. * Determines the preferred size of the container argument using
  269. * this grid layout.
  270. * <p>
  271. * The preferred width of a grid layout is the largest preferred
  272. * width of any of the components in the container times the number of
  273. * columns, plus the horizontal padding times the number of columns
  274. * plus one, plus the left and right insets of the target container.
  275. * <p>
  276. * The preferred height of a grid layout is the largest preferred
  277. * height of any of the components in the container times the number of
  278. * rows, plus the vertical padding times the number of rows plus one,
  279. * plus the top and bottom insets of the target container.
  280. *
  281. * @param parent the container in which to do the layout
  282. * @return the preferred dimensions to lay out the
  283. * subcomponents of the specified container
  284. * @see java.awt.GridLayout#minimumLayoutSize
  285. * @see java.awt.Container#getPreferredSize()
  286. */
  287. public Dimension preferredLayoutSize(Container parent) {
  288. synchronized (parent.getTreeLock()) {
  289. Insets insets = parent.getInsets();
  290. int ncomponents = parent.getComponentCount();
  291. int nrows = rows;
  292. int ncols = cols;
  293. if (nrows > 0) {
  294. ncols = (ncomponents + nrows - 1) / nrows;
  295. } else {
  296. nrows = (ncomponents + ncols - 1) / ncols;
  297. }
  298. int w = 0;
  299. int h = 0;
  300. for (int i = 0 ; i < ncomponents ; i++) {
  301. Component comp = parent.getComponent(i);
  302. Dimension d = comp.getPreferredSize();
  303. if (w < d.width) {
  304. w = d.width;
  305. }
  306. if (h < d.height) {
  307. h = d.height;
  308. }
  309. }
  310. return new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap,
  311. insets.top + insets.bottom + nrows*h + (nrows-1)*vgap);
  312. }
  313. }
  314. /**
  315. * Determines the minimum size of the container argument using this
  316. * grid layout.
  317. * <p>
  318. * The minimum width of a grid layout is the largest minimum width
  319. * of any of the components in the container times the number of columns,
  320. * plus the horizontal padding times the number of columns plus one,
  321. * plus the left and right insets of the target container.
  322. * <p>
  323. * The minimum height of a grid layout is the largest minimum height
  324. * of any of the components in the container times the number of rows,
  325. * plus the vertical padding times the number of rows plus one, plus
  326. * the top and bottom insets of the target container.
  327. *
  328. * @param parent the container in which to do the layout
  329. * @return the minimum dimensions needed to lay out the
  330. * subcomponents of the specified container
  331. * @see java.awt.GridLayout#preferredLayoutSize
  332. * @see java.awt.Container#doLayout
  333. */
  334. public Dimension minimumLayoutSize(Container parent) {
  335. synchronized (parent.getTreeLock()) {
  336. Insets insets = parent.getInsets();
  337. int ncomponents = parent.getComponentCount();
  338. int nrows = rows;
  339. int ncols = cols;
  340. if (nrows > 0) {
  341. ncols = (ncomponents + nrows - 1) / nrows;
  342. } else {
  343. nrows = (ncomponents + ncols - 1) / ncols;
  344. }
  345. int w = 0;
  346. int h = 0;
  347. for (int i = 0 ; i < ncomponents ; i++) {
  348. Component comp = parent.getComponent(i);
  349. Dimension d = comp.getMinimumSize();
  350. if (w < d.width) {
  351. w = d.width;
  352. }
  353. if (h < d.height) {
  354. h = d.height;
  355. }
  356. }
  357. return new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap,
  358. insets.top + insets.bottom + nrows*h + (nrows-1)*vgap);
  359. }
  360. }
  361. /**
  362. * Lays out the specified container using this layout.
  363. * <p>
  364. * This method reshapes the components in the specified target
  365. * container in order to satisfy the constraints of the
  366. * <code>GridLayout</code> object.
  367. * <p>
  368. * The grid layout manager determines the size of individual
  369. * components by dividing the free space in the container into
  370. * equal-sized portions according to the number of rows and columns
  371. * in the layout. The container's free space equals the container's
  372. * size minus any insets and any specified horizontal or vertical
  373. * gap. All components in a grid layout are given the same size.
  374. *
  375. * @param parent the container in which to do the layout
  376. * @see java.awt.Container
  377. * @see java.awt.Container#doLayout
  378. */
  379. public void layoutContainer(Container parent) {
  380. synchronized (parent.getTreeLock()) {
  381. Insets insets = parent.getInsets();
  382. int ncomponents = parent.getComponentCount();
  383. int nrows = rows;
  384. int ncols = cols;
  385. boolean ltr = parent.getComponentOrientation().isLeftToRight();
  386. if (ncomponents == 0) {
  387. return;
  388. }
  389. if (nrows > 0) {
  390. ncols = (ncomponents + nrows - 1) / nrows;
  391. } else {
  392. nrows = (ncomponents + ncols - 1) / ncols;
  393. }
  394. int w = parent.width - (insets.left + insets.right);
  395. int h = parent.height - (insets.top + insets.bottom);
  396. w = (w - (ncols - 1) * hgap) / ncols;
  397. h = (h - (nrows - 1) * vgap) / nrows;
  398. if (ltr) {
  399. for (int c = 0, x = insets.left ; c < ncols ; c++, x += w + hgap) {
  400. for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap) {
  401. int i = r * ncols + c;
  402. if (i < ncomponents) {
  403. parent.getComponent(i).setBounds(x, y, w, h);
  404. }
  405. }
  406. }
  407. } else {
  408. for (int c = 0, x = parent.width - insets.right - w; c < ncols ; c++, x -= w + hgap) {
  409. for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap) {
  410. int i = r * ncols + c;
  411. if (i < ncomponents) {
  412. parent.getComponent(i).setBounds(x, y, w, h);
  413. }
  414. }
  415. }
  416. }
  417. }
  418. }
  419. /**
  420. * Returns the string representation of this grid layout's values.
  421. * @return a string representation of this grid layout
  422. */
  423. public String toString() {
  424. return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap +
  425. ",rows=" + rows + ",cols=" + cols + "]";
  426. }
  427. }