BorderLayout.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. /* BorderLayout.java -- A layout manager class
  2. Copyright (C) 1999, 2002 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., 59 Temple Place, Suite 330, Boston, MA
  15. 02111-1307 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 java.awt;
  32. /**
  33. * This class implements a layout manager that positions components
  34. * in certain sectors of the parent container.
  35. *
  36. * @author Aaron M. Renn (arenn@urbanophile.com)
  37. * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
  38. */
  39. public class BorderLayout implements LayoutManager2, java.io.Serializable
  40. {
  41. /*
  42. * Static Variables
  43. */
  44. /**
  45. * Constant indicating the top of the container
  46. */
  47. public static final String NORTH = "North";
  48. /**
  49. * Constant indicating the bottom of the container
  50. */
  51. public static final String SOUTH = "South";
  52. /**
  53. * Constant indicating the right side of the container
  54. */
  55. public static final String EAST = "East";
  56. /**
  57. * Constant indicating the left side of the container
  58. */
  59. public static final String WEST = "West";
  60. /**
  61. * Constant indicating the center of the container
  62. */
  63. public static final String CENTER = "Center";
  64. /**
  65. * The constant indicating the position before the first line of the
  66. * layout. The exact position depends on the writing system: For a
  67. * top-to-bottom orientation, it is the same as {@link #NORTH}, for
  68. * a bottom-to-top orientation, it is the same as {@link #SOUTH}.
  69. *
  70. * <p>This constant is an older name for {@link #PAGE_START} which
  71. * has exactly the same value.
  72. *
  73. * @since 1.2
  74. */
  75. public static final String BEFORE_FIRST_LINE = "First";
  76. /**
  77. * The constant indicating the position after the last line of the
  78. * layout. The exact position depends on the writing system: For a
  79. * top-to-bottom orientation, it is the same as {@link #SOUTH}, for
  80. * a bottom-to-top orientation, it is the same as {@link #NORTH}.
  81. *
  82. * <p>This constant is an older name for {@link #PAGE_END} which
  83. * has exactly the same value.
  84. *
  85. * @since 1.2
  86. */
  87. public static final String AFTER_LAST_LINE = "Last";
  88. /**
  89. * The constant indicating the position before the first item of the
  90. * layout. The exact position depends on the writing system: For a
  91. * left-to-right orientation, it is the same as {@link #WEST}, for
  92. * a right-to-left orientation, it is the same as {@link #EAST}.
  93. *
  94. * <p>This constant is an older name for {@link #LINE_START} which
  95. * has exactly the same value.
  96. *
  97. * @since 1.2
  98. */
  99. public static final String BEFORE_LINE_BEGINS = "Before";
  100. /**
  101. * The constant indicating the position after the last item of the
  102. * layout. The exact position depends on the writing system: For a
  103. * left-to-right orientation, it is the same as {@link #EAST}, for
  104. * a right-to-left orientation, it is the same as {@link #WEST}.
  105. *
  106. * <p>This constant is an older name for {@link #LINE_END} which
  107. * has exactly the same value.
  108. *
  109. * @since 1.2
  110. */
  111. public static final String AFTER_LINE_ENDS = "After";
  112. /**
  113. * The constant indicating the position before the first line of the
  114. * layout. The exact position depends on the writing system: For a
  115. * top-to-bottom orientation, it is the same as {@link #NORTH}, for
  116. * a bottom-to-top orientation, it is the same as {@link #SOUTH}.
  117. *
  118. * @since 1.4
  119. */
  120. public static final String PAGE_START = BEFORE_FIRST_LINE;
  121. /**
  122. * The constant indicating the position after the last line of the
  123. * layout. The exact position depends on the writing system: For a
  124. * top-to-bottom orientation, it is the same as {@link #SOUTH}, for
  125. * a bottom-to-top orientation, it is the same as {@link #NORTH}.
  126. *
  127. * @since 1.4
  128. */
  129. public static final String PAGE_END = AFTER_LAST_LINE;
  130. /**
  131. * The constant indicating the position before the first item of the
  132. * layout. The exact position depends on the writing system: For a
  133. * left-to-right orientation, it is the same as {@link #WEST}, for
  134. * a right-to-left orientation, it is the same as {@link #EAST}.
  135. *
  136. * @since 1.4
  137. */
  138. public static final String LINE_START = BEFORE_LINE_BEGINS;
  139. /**
  140. * The constant indicating the position after the last item of the
  141. * layout. The exact position depends on the writing system: For a
  142. * left-to-right orientation, it is the same as {@link #EAST}, for
  143. * a right-to-left orientation, it is the same as {@link #WEST}.
  144. *
  145. * @since 1.4
  146. */
  147. public static final String LINE_END = AFTER_LINE_ENDS;
  148. // Serialization constant
  149. private static final long serialVersionUID = -8658291919501921765L;
  150. /*************************************************************************/
  151. /*
  152. * Instance Variables
  153. */
  154. /**
  155. * @serial
  156. */
  157. private Component north;
  158. /**
  159. * @serial
  160. */
  161. private Component south;
  162. /**
  163. * @serial
  164. */
  165. private Component east;
  166. /**
  167. * @serial
  168. */
  169. private Component west;
  170. /**
  171. * @serial
  172. */
  173. private Component center;
  174. /**
  175. * @serial
  176. */
  177. private Component firstLine;
  178. /**
  179. * @serial
  180. */
  181. private Component lastLine;
  182. /**
  183. * @serial
  184. */
  185. private Component firstItem;
  186. /**
  187. * @serial
  188. */
  189. private Component lastItem;
  190. /**
  191. * @serial The horizontal gap between components
  192. */
  193. private int hgap;
  194. /**
  195. * @serial The vertical gap between components
  196. */
  197. private int vgap;
  198. /*************************************************************************/
  199. /*
  200. * Constructors
  201. */
  202. /**
  203. * Initializes a new instance of <code>BorderLayout</code> with no
  204. * horiztonal or vertical gaps between components.
  205. */
  206. public
  207. BorderLayout()
  208. {
  209. this(0,0);
  210. }
  211. /*************************************************************************/
  212. /**
  213. * Initializes a new instance of <code>BorderLayout</code> with the
  214. * specified horiztonal and vertical gaps between components.
  215. *
  216. * @param hgap The horizontal gap between components.
  217. * @param vgap The vertical gap between components.
  218. */
  219. public
  220. BorderLayout(int hgap, int vgap)
  221. {
  222. this.hgap = hgap;
  223. this.vgap = vgap;
  224. }
  225. /*************************************************************************/
  226. /*
  227. * Instance Variables
  228. */
  229. /**
  230. * Returns the horitzontal gap value.
  231. *
  232. * @return The horitzontal gap value.
  233. */
  234. public int
  235. getHgap()
  236. {
  237. return(hgap);
  238. }
  239. /*************************************************************************/
  240. /**
  241. * Sets the horizontal gap to the specified value.
  242. *
  243. * @param hgap The new horizontal gap.
  244. */
  245. public void
  246. setHgap(int hgap)
  247. {
  248. this.hgap = hgap;
  249. }
  250. /*************************************************************************/
  251. /**
  252. * Returns the vertical gap value.
  253. *
  254. * @return The vertical gap value.
  255. */
  256. public int
  257. getVgap()
  258. {
  259. return(vgap);
  260. }
  261. /*************************************************************************/
  262. /**
  263. * Sets the vertical gap to the specified value.
  264. *
  265. * @param vgap The new vertical gap value.
  266. */
  267. public void
  268. setVgap(int vgap)
  269. {
  270. this.vgap = vgap;
  271. }
  272. /*************************************************************************/
  273. /**
  274. * Adds a component to the layout in the specified constraint position,
  275. * which must be one of the string constants defined in this class.
  276. *
  277. * @param component The component to add.
  278. * @param constraints The constraint string.
  279. *
  280. * @exception IllegalArgumentException If the constraint object is not
  281. * a string, or is not one of the specified constants in this class.
  282. */
  283. public void
  284. addLayoutComponent(Component component, Object constraints)
  285. {
  286. if (constraints != null && ! (constraints instanceof String))
  287. throw new IllegalArgumentException("Constraint must be a string");
  288. String str = (String)constraints;
  289. if (str == null || str.equals(CENTER))
  290. center = component;
  291. else if (str.equals(NORTH))
  292. north = component;
  293. else if (str.equals(SOUTH))
  294. south = component;
  295. else if (str.equals(EAST))
  296. east = component;
  297. else if (str.equals(WEST))
  298. west = component;
  299. else if (str.equals(BEFORE_FIRST_LINE))
  300. firstLine = component;
  301. else if (str.equals(AFTER_LAST_LINE))
  302. lastLine = component;
  303. else if (str.equals(BEFORE_LINE_BEGINS))
  304. firstItem = component;
  305. else if (str.equals(AFTER_LINE_ENDS))
  306. lastItem = component;
  307. else
  308. throw new IllegalArgumentException("Constraint value not valid: " + str);
  309. }
  310. /*************************************************************************/
  311. /**
  312. * Adds a component to the layout in the specified constraint position,
  313. * which must be one of the string constants defined in this class.
  314. *
  315. * @param constraints The constraint string.
  316. * @param component The component to add.
  317. *
  318. * @exception IllegalArgumentException If the constraint object is not
  319. * one of the specified constants in this class.
  320. *
  321. * @deprecated This method is deprecated in favor of
  322. * <code>addLayoutComponent(Component, Object)</code>.
  323. */
  324. public void
  325. addLayoutComponent(String constraints, Component component)
  326. {
  327. addLayoutComponent(component, constraints);
  328. }
  329. /*************************************************************************/
  330. /**
  331. * Removes the specified component from the layout.
  332. *
  333. * @param component The component to remove from the layout.
  334. */
  335. public void
  336. removeLayoutComponent(Component component)
  337. {
  338. if (north == component)
  339. north = null;
  340. if (south == component)
  341. south = null;
  342. if (east == component)
  343. east = null;
  344. if (west == component)
  345. west = null;
  346. if (center == component)
  347. center = null;
  348. if (firstItem == component)
  349. firstItem = null;
  350. if (lastItem == component)
  351. lastItem = null;
  352. if (firstLine == component)
  353. firstLine = null;
  354. if (lastLine == component)
  355. lastLine = null;
  356. }
  357. /*************************************************************************/
  358. /**
  359. * Returns the minimum size of the specified container using this layout.
  360. *
  361. * @param target The container to calculate the minimum size for.
  362. *
  363. * @return The minimum size of the container
  364. */
  365. public Dimension
  366. minimumLayoutSize(Container target)
  367. {
  368. return calcSize(target, MIN);
  369. }
  370. /*************************************************************************/
  371. /**
  372. * Returns the preferred size of the specified container using this layout.
  373. *
  374. * @param target The container to calculate the preferred size for.
  375. *
  376. * @return The preferred size of the container
  377. */
  378. public Dimension
  379. preferredLayoutSize(Container target)
  380. {
  381. return calcSize(target, PREF);
  382. }
  383. /*************************************************************************/
  384. /**
  385. * Returns the maximum size of the specified container using this layout.
  386. *
  387. * @param target The container to calculate the maximum size for.
  388. *
  389. * @return The maximum size of the container
  390. */
  391. public Dimension
  392. maximumLayoutSize(Container target)
  393. {
  394. return calcSize(target, MAX);
  395. }
  396. /*************************************************************************/
  397. /**
  398. * Returns the X axis alignment, which is a <code>float</code> indicating
  399. * where along the X axis this container wishs to position its layout.
  400. * 0 indicates align to the left, 1 indicates align to the right, and 0.5
  401. * indicates align to the center.
  402. *
  403. * @param parent The parent container.
  404. *
  405. * @return The X alignment value.
  406. */
  407. public float
  408. getLayoutAlignmentX(Container parent)
  409. {
  410. return(parent.getAlignmentX());
  411. }
  412. /*************************************************************************/
  413. /**
  414. * Returns the Y axis alignment, which is a <code>float</code> indicating
  415. * where along the Y axis this container wishs to position its layout.
  416. * 0 indicates align to the top, 1 indicates align to the bottom, and 0.5
  417. * indicates align to the center.
  418. *
  419. * @param parent The parent container.
  420. *
  421. * @return The Y alignment value.
  422. */
  423. public float
  424. getLayoutAlignmentY(Container parent)
  425. {
  426. return(parent.getAlignmentY());
  427. }
  428. /*************************************************************************/
  429. /**
  430. * Instructs this object to discard any layout information it might
  431. * have cached.
  432. *
  433. * @param parent The parent container.
  434. */
  435. public void
  436. invalidateLayout(Container parent)
  437. {
  438. }
  439. /*************************************************************************/
  440. /**
  441. * Lays out the specified container according to the constraints
  442. * in this object.
  443. *
  444. * @param target The container to lay out.
  445. */
  446. public void
  447. layoutContainer(Container target)
  448. {
  449. synchronized (target.getTreeLock ())
  450. {
  451. Insets i = target.getInsets();
  452. ComponentOrientation orient = target.getComponentOrientation ();
  453. boolean left_to_right = orient.isLeftToRight ();
  454. Component my_north = north;
  455. Component my_east = east;
  456. Component my_south = south;
  457. Component my_west = west;
  458. // Note that we currently don't handle vertical layouts. Neither
  459. // does JDK 1.3.
  460. if (firstLine != null)
  461. my_north = firstLine;
  462. if (lastLine != null)
  463. my_south = lastLine;
  464. if (firstItem != null)
  465. {
  466. if (left_to_right)
  467. my_west = firstItem;
  468. else
  469. my_east = firstItem;
  470. }
  471. if (lastItem != null)
  472. {
  473. if (left_to_right)
  474. my_east = lastItem;
  475. else
  476. my_west = lastItem;
  477. }
  478. Dimension c = calcCompSize(center, PREF);
  479. Dimension n = calcCompSize(my_north, PREF);
  480. Dimension s = calcCompSize(my_south, PREF);
  481. Dimension e = calcCompSize(my_east, PREF);
  482. Dimension w = calcCompSize(my_west, PREF);
  483. Dimension t = target.getSize();
  484. /*
  485. <-> hgap <-> hgap
  486. +----------------------------+ }
  487. |t | } i.top
  488. | +----------------------+ | --- y1 }
  489. | |n | |
  490. | +----------------------+ | } vgap
  491. | +---+ +----------+ +---+ | --- y2 } }
  492. | |w | |c | |e | | } hh
  493. | +---+ +----------+ +---+ | } vgap }
  494. | +----------------------+ | --- y3 }
  495. | |s | |
  496. | +----------------------+ | }
  497. | | } i.bottom
  498. +----------------------------+ }
  499. |x1 |x2 |x3
  500. <---------------------->
  501. <--> ww <-->
  502. i.left i.right
  503. */
  504. int x1 = i.left;
  505. int x2 = x1 + w.width + hgap;
  506. int x3 = t.width - i.right - e.width;
  507. int ww = t.width - i.right - i.left;
  508. int y1 = i.top;
  509. int y2 = y1 + n.height + vgap;
  510. int y3 = t.height - i.bottom - s.height;
  511. int hh = y3-y2-vgap;
  512. setBounds(center, x2, y2, x3-x2-hgap, hh);
  513. setBounds(my_north, x1, y1, ww, n.height);
  514. setBounds(my_south, x1, y3, ww, s.height);
  515. setBounds(my_west, x1, y2, w.width, hh);
  516. setBounds(my_east, x3, y2, e.width, hh);
  517. }
  518. }
  519. /*************************************************************************/
  520. /**
  521. * Returns a string representation of this layout manager.
  522. *
  523. * @return A string representation of this object.
  524. */
  525. public String
  526. toString()
  527. {
  528. return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]";
  529. }
  530. private void
  531. setBounds(Component comp, int x, int y, int w, int h)
  532. {
  533. if (comp == null)
  534. return;
  535. comp.setBounds(x, y, w, h);
  536. }
  537. // Some constants for use with calcSize().
  538. private static final int MIN = 0;
  539. private static final int MAX = 1;
  540. private static final int PREF = 2;
  541. private Dimension
  542. calcCompSize(Component comp, int what)
  543. {
  544. if (comp == null)
  545. return new Dimension(0, 0);
  546. if (what == MIN)
  547. return comp.getMinimumSize();
  548. else if (what == MAX)
  549. return comp.getMaximumSize();
  550. return comp.getPreferredSize();
  551. }
  552. // This is a helper function used to compute the various sizes for
  553. // this layout.
  554. private Dimension
  555. calcSize(Container target, int what)
  556. {
  557. synchronized (target.getTreeLock ())
  558. {
  559. Insets ins = target.getInsets();
  560. ComponentOrientation orient = target.getComponentOrientation ();
  561. boolean left_to_right = orient.isLeftToRight ();
  562. Component my_north = north;
  563. Component my_east = east;
  564. Component my_south = south;
  565. Component my_west = west;
  566. // Note that we currently don't handle vertical layouts. Neither
  567. // does JDK 1.3.
  568. if (firstLine != null)
  569. my_north = firstLine;
  570. if (lastLine != null)
  571. my_south = lastLine;
  572. if (firstItem != null)
  573. {
  574. if (left_to_right)
  575. my_west = firstItem;
  576. else
  577. my_east = firstItem;
  578. }
  579. if (lastItem != null)
  580. {
  581. if (left_to_right)
  582. my_east = lastItem;
  583. else
  584. my_west = lastItem;
  585. }
  586. Dimension ndim = calcCompSize(my_north, what);
  587. Dimension sdim = calcCompSize(my_south, what);
  588. Dimension edim = calcCompSize(my_east, what);
  589. Dimension wdim = calcCompSize(my_west, what);
  590. Dimension cdim = calcCompSize(center, what);
  591. int width = edim.width + cdim.width + wdim.width + (hgap * 2);
  592. if (ndim.width > width)
  593. width = ndim.width;
  594. if (sdim.width > width)
  595. width = sdim.width;
  596. width += (ins.left + ins.right);
  597. int height = edim.height;
  598. if (cdim.height > height)
  599. height = cdim.height;
  600. if (wdim.height > height)
  601. height = wdim.height;
  602. height += (ndim.height + sdim.height + (vgap * 2) + ins.top + ins.bottom);
  603. return(new Dimension(width, height));
  604. }
  605. }
  606. } // class BorderLayout