OverlayLayout.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /* OverlayLayout.java -- A layout manager
  2. Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package javax.swing;
  32. import java.awt.AWTError;
  33. import java.awt.Component;
  34. import java.awt.Container;
  35. import java.awt.Dimension;
  36. import java.awt.Insets;
  37. import java.awt.LayoutManager2;
  38. import java.io.Serializable;
  39. /**
  40. * A layout manager that lays out the components of a container one over
  41. * another.
  42. *
  43. * The components take as much space as is available in the container, but not
  44. * more than specified by their maximum size.
  45. *
  46. * The overall layout is mainly affected by the components
  47. * <code>alignmentX</code> and <code>alignmentY</code> properties. All
  48. * components are aligned, so that their alignment points (for either
  49. * direction) are placed in one line (the baseline for this direction).
  50. *
  51. * For example: An X alignment of 0.0 means that the component's alignment
  52. * point is at it's left edge, an X alignment of 0.5 means that the alignment
  53. * point is in the middle, an X alignment of 1.0 means, the aligment point is
  54. * at the right edge. So if you have three components, the first with 0.0, the
  55. * second with 0.5 and the third with 1.0, then they are laid out like this:
  56. *
  57. * <pre>
  58. * +-------+
  59. * | 1 |
  60. * +-------+
  61. * +-------+
  62. * | 2 |
  63. * +-------+
  64. * +---------+
  65. * | 3 +
  66. * +---------+
  67. * </pre>
  68. * The above picture shows the X alignment between the components. An Y
  69. * alignment like shown above cannot be achieved with this layout manager. The
  70. * components are place on top of each other, with the X alignment shown above.
  71. *
  72. * @author Roman Kennke (kennke@aicas.com)
  73. * @author Andrew Selkirk
  74. */
  75. public class OverlayLayout implements LayoutManager2, Serializable
  76. {
  77. private static final long serialVersionUID = 18082829169631543L;
  78. /**
  79. * The container to be laid out.
  80. */
  81. private Container target;
  82. /**
  83. * The size requirements of the containers children for the X direction.
  84. */
  85. private SizeRequirements[] xChildren;
  86. /**
  87. * The size requirements of the containers children for the Y direction.
  88. */
  89. private SizeRequirements[] yChildren;
  90. /**
  91. * The size requirements of the container to be laid out for the X direction.
  92. */
  93. private SizeRequirements xTotal;
  94. /**
  95. * The size requirements of the container to be laid out for the Y direction.
  96. */
  97. private SizeRequirements yTotal;
  98. /**
  99. * The offsets of the child components in the X direction.
  100. */
  101. private int[] offsetsX;
  102. /**
  103. * The offsets of the child components in the Y direction.
  104. */
  105. private int[] offsetsY;
  106. /**
  107. * The spans of the child components in the X direction.
  108. */
  109. private int[] spansX;
  110. /**
  111. * The spans of the child components in the Y direction.
  112. */
  113. private int[] spansY;
  114. /**
  115. * Creates a new OverlayLayout for the specified container.
  116. *
  117. * @param target the container to be laid out
  118. */
  119. public OverlayLayout(Container target)
  120. {
  121. this.target = target;
  122. }
  123. /**
  124. * Notifies the layout manager that the layout has become invalid. It throws
  125. * away cached layout information and recomputes it the next time it is
  126. * requested.
  127. *
  128. * @param target not used here
  129. */
  130. public void invalidateLayout(Container target)
  131. {
  132. xChildren = null;
  133. yChildren = null;
  134. xTotal = null;
  135. yTotal = null;
  136. offsetsX = null;
  137. offsetsY = null;
  138. spansX = null;
  139. spansY = null;
  140. }
  141. /**
  142. * This method is not used in this layout manager.
  143. *
  144. * @param string not used here
  145. * @param component not used here
  146. */
  147. public void addLayoutComponent(String string, Component component)
  148. {
  149. // Nothing to do here.
  150. }
  151. /**
  152. * This method is not used in this layout manager.
  153. *
  154. * @param component not used here
  155. * @param constraints not used here
  156. */
  157. public void addLayoutComponent(Component component, Object constraints)
  158. {
  159. // Nothing to do here.
  160. }
  161. /**
  162. * This method is not used in this layout manager.
  163. *
  164. * @param component not used here
  165. */
  166. public void removeLayoutComponent(Component component)
  167. {
  168. // Nothing to do here.
  169. }
  170. /**
  171. * Returns the preferred size of the container that is laid out. This is
  172. * computed by the children's preferred sizes, taking their alignments into
  173. * account.
  174. *
  175. * @param target not used here
  176. *
  177. * @return the preferred size of the container that is laid out
  178. */
  179. public Dimension preferredLayoutSize(Container target)
  180. {
  181. if (target != this.target)
  182. throw new AWTError("OverlayLayout can't be shared");
  183. checkTotalRequirements();
  184. return new Dimension(xTotal.preferred, yTotal.preferred);
  185. }
  186. /**
  187. * Returns the minimum size of the container that is laid out. This is
  188. * computed by the children's minimum sizes, taking their alignments into
  189. * account.
  190. *
  191. * @param target not used here
  192. *
  193. * @return the minimum size of the container that is laid out
  194. */
  195. public Dimension minimumLayoutSize(Container target)
  196. {
  197. if (target != this.target)
  198. throw new AWTError("OverlayLayout can't be shared");
  199. checkTotalRequirements();
  200. return new Dimension(xTotal.minimum, yTotal.minimum);
  201. }
  202. /**
  203. * Returns the maximum size of the container that is laid out. This is
  204. * computed by the children's maximum sizes, taking their alignments into
  205. * account.
  206. *
  207. * @param target not used here
  208. *
  209. * @return the maximum size of the container that is laid out
  210. */
  211. public Dimension maximumLayoutSize(Container target)
  212. {
  213. if (target != this.target)
  214. throw new AWTError("OverlayLayout can't be shared");
  215. checkTotalRequirements();
  216. return new Dimension(xTotal.maximum, yTotal.maximum);
  217. }
  218. /**
  219. * Returns the X alignment of the container that is laid out. This is
  220. * computed by the children's preferred sizes, taking their alignments into
  221. * account.
  222. *
  223. * @param target not used here
  224. *
  225. * @return the X alignment of the container that is laid out
  226. */
  227. public float getLayoutAlignmentX(Container target)
  228. {
  229. if (target != this.target)
  230. throw new AWTError("OverlayLayout can't be shared");
  231. checkTotalRequirements();
  232. return xTotal.alignment;
  233. }
  234. /**
  235. * Returns the Y alignment of the container that is laid out. This is
  236. * computed by the children's preferred sizes, taking their alignments into
  237. * account.
  238. *
  239. * @param target not used here
  240. *
  241. * @return the X alignment of the container that is laid out
  242. */
  243. public float getLayoutAlignmentY(Container target)
  244. {
  245. if (target != this.target)
  246. throw new AWTError("OverlayLayout can't be shared");
  247. checkTotalRequirements();
  248. return yTotal.alignment;
  249. }
  250. /**
  251. * Lays out the container and it's children.
  252. *
  253. * The children are laid out one over another.
  254. *
  255. * The components take as much space as is available in the container, but
  256. * not more than specified by their maximum size.
  257. *
  258. * The overall layout is mainly affected by the components
  259. * <code>alignmentX</code> and <code>alignmentY</code> properties. All
  260. * components are aligned, so that their alignment points (for either
  261. * direction) are placed in one line (the baseline for this direction).
  262. *
  263. * For example: An X alignment of 0.0 means that the component's alignment
  264. * point is at it's left edge, an X alignment of 0.5 means that the alignment
  265. * point is in the middle, an X alignment of 1.0 means, the aligment point is
  266. * at the right edge. So if you have three components, the first with 0.0,
  267. * the second with 0.5 and the third with 1.0, then they are laid out like
  268. * this:
  269. *
  270. * <pre>
  271. * +-------+
  272. * | 1 |
  273. * +-------+
  274. * +-------+
  275. * | 2 |
  276. * +-------+
  277. * +---------+
  278. * | 3 +
  279. * +---------+
  280. * </pre>
  281. * The above picture shows the X alignment between the components. An Y
  282. * alignment like shown above cannot be achieved with this layout manager.
  283. * The components are place on top of each other, with the X alignment shown
  284. * above.
  285. *
  286. * @param target not used here
  287. */
  288. public void layoutContainer(Container target)
  289. {
  290. if (target != this.target)
  291. throw new AWTError("OverlayLayout can't be shared");
  292. checkLayout();
  293. Component[] children = target.getComponents();
  294. for (int i = 0; i < children.length; i++)
  295. children[i].setBounds(offsetsX[i], offsetsY[i], spansX[i], spansY[i]);
  296. }
  297. /**
  298. * Makes sure that the xChildren and yChildren fields are correctly set up.
  299. * A call to {@link #invalidateLayout(Container)} sets these fields to null,
  300. * so they have to be set up again.
  301. */
  302. private void checkRequirements()
  303. {
  304. if (xChildren == null || yChildren == null)
  305. {
  306. Component[] children = target.getComponents();
  307. xChildren = new SizeRequirements[children.length];
  308. yChildren = new SizeRequirements[children.length];
  309. for (int i = 0; i < children.length; i++)
  310. {
  311. if (! children[i].isVisible())
  312. {
  313. xChildren[i] = new SizeRequirements();
  314. yChildren[i] = new SizeRequirements();
  315. }
  316. else
  317. {
  318. xChildren[i] =
  319. new SizeRequirements(children[i].getMinimumSize().width,
  320. children[i].getPreferredSize().width,
  321. children[i].getMaximumSize().width,
  322. children[i].getAlignmentX());
  323. yChildren[i] =
  324. new SizeRequirements(children[i].getMinimumSize().height,
  325. children[i].getPreferredSize().height,
  326. children[i].getMaximumSize().height,
  327. children[i].getAlignmentY());
  328. }
  329. }
  330. }
  331. }
  332. /**
  333. * Makes sure that the xTotal and yTotal fields are set up correctly. A call
  334. * to {@link #invalidateLayout} sets these fields to null and they have to be
  335. * recomputed.
  336. */
  337. private void checkTotalRequirements()
  338. {
  339. if (xTotal == null || yTotal == null)
  340. {
  341. checkRequirements();
  342. xTotal = SizeRequirements.getAlignedSizeRequirements(xChildren);
  343. yTotal = SizeRequirements.getAlignedSizeRequirements(yChildren);
  344. }
  345. }
  346. /**
  347. * Makes sure that the offsetsX, offsetsY, spansX and spansY fields are set
  348. * up correctly. A call to {@link #invalidateLayout} sets these fields
  349. * to null and they have to be recomputed.
  350. */
  351. private void checkLayout()
  352. {
  353. if (offsetsX == null || offsetsY == null || spansX == null
  354. || spansY == null)
  355. {
  356. checkRequirements();
  357. checkTotalRequirements();
  358. int len = target.getComponents().length;
  359. offsetsX = new int[len];
  360. offsetsY = new int[len];
  361. spansX = new int[len];
  362. spansY = new int[len];
  363. Insets in = target.getInsets();
  364. int width = target.getWidth() - in.left - in.right;
  365. int height = target.getHeight() - in.top - in.bottom;
  366. SizeRequirements.calculateAlignedPositions(width, xTotal,
  367. xChildren, offsetsX, spansX);
  368. SizeRequirements.calculateAlignedPositions(height, yTotal,
  369. yChildren, offsetsY, spansY);
  370. }
  371. }
  372. }