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