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