svn-gvsig-desktop / trunk / build / distribution / IzPack / src / lib / com / izforge / izpack / gui / TwoColumnLayout.java @ 21757
History | View | Annotate | Download (32 KB)
1 | 21757 | jcampos | /*
|
---|---|---|---|
2 | * $Id: TwoColumnLayout.java 5819 2006-06-14 07:29:09Z cesar $
|
||
3 | * Copyright (C) 2002 Elmar Grom
|
||
4 | *
|
||
5 | * File : TwoColumnLayout.java
|
||
6 | * Description : A special layout manger designed for the UserInputPanel
|
||
7 | * Author's email : elmar@grom.net
|
||
8 | * Author's Website : http://www.izforge.com
|
||
9 | *
|
||
10 | * This program is free software; you can redistribute it and/or
|
||
11 | * modify it under the terms of the GNU General Public License
|
||
12 | * as published by the Free Software Foundation; either version 2
|
||
13 | * of the License, or any later version.
|
||
14 | *
|
||
15 | * This program is distributed in the hope that it will be useful,
|
||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
18 | * GNU General Public License for more details.
|
||
19 | *
|
||
20 | * You should have received a copy of the GNU General Public License
|
||
21 | * along with this program; if not, write to the Free Software
|
||
22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
23 | */
|
||
24 | |||
25 | package com.izforge.izpack.gui; |
||
26 | |||
27 | import java.awt.BasicStroke; |
||
28 | import java.awt.Color; |
||
29 | import java.awt.Component; |
||
30 | import java.awt.Container; |
||
31 | import java.awt.Dimension; |
||
32 | import java.awt.Graphics2D; |
||
33 | import java.awt.LayoutManager2; |
||
34 | import java.awt.Stroke; |
||
35 | import java.util.Vector; |
||
36 | |||
37 | /**
|
||
38 | * This class implements a layout manager that generally lays out components
|
||
39 | * in two columns.
|
||
40 | * <BR><BR>
|
||
41 | * The design goal for this layout manager was to lay out forms for data
|
||
42 | * entry, where there are several rows of entry fields with associated labels.
|
||
43 | * The goal was to have the beginning off all labels line up, as well as the
|
||
44 | * left edge of all the data entry fields. This leads to a situation where all
|
||
45 | * components are essentially laid out in two columns. The columns adjust to
|
||
46 | * accommodate components of various sizes. This means that components that
|
||
47 | * are added are laid out top to bottom, either in the left column, in the
|
||
48 | * right column or straddling both columns. In addition to this general
|
||
49 | * behavior, the following additional layout capabilities are supported:<br>
|
||
50 | * <ul>
|
||
51 | * <li>Resizable margins are provided on the left and right side.
|
||
52 | * <li>A special region is provided at the top that is only affected by the
|
||
53 | * side margins but not by any other layout behavior.
|
||
54 | * <li>It is possible to specify the vertical positioning of the cluster of
|
||
55 | * laid out components for the case that they do not occupy the entire
|
||
56 | * available real estate.
|
||
57 | * <li>Individual components can be indented.
|
||
58 | * </ul>
|
||
59 | *
|
||
60 | * <b>The Layout Behavior</b>
|
||
61 | * <br><br>
|
||
62 | * The left and right margin are absolute. This means that they can not be
|
||
63 | * penetrated by components. All layout happens between the limits established
|
||
64 | * by these margins. The purpose of these margins is to ensure that components
|
||
65 | * are not laid out all the way to the edge of their container, without the
|
||
66 | * need to set matching borders for each component.
|
||
67 | * <br><br>
|
||
68 | * The title margin at the top factors only into the layout behavior if there
|
||
69 | * is a component set to be laid out in that region, otherwise it is ignored.
|
||
70 | * <br><br>
|
||
71 | * The vertical space available to each row of components depends on the space
|
||
72 | * requirements of the tallest component in that row. Both components are
|
||
73 | * placed vertically centered in their row.
|
||
74 | * <br><br>
|
||
75 | * All horizontal layout is based on the position of three vertical rules,
|
||
76 | * the left rule, the right rule and the center rule.
|
||
77 | * <br><br>
|
||
78 | * <img src="doc-files/TwoColumnLayout.gif"/>
|
||
79 | * <br><br>
|
||
80 | * The actual position of each rule depends on the alignment strategy, margin
|
||
81 | * settings and component sizes. Regardless of these factors, components
|
||
82 | * placed in the left column are <i>always</i> positioned with their left edge
|
||
83 | * aligned with the left rule. Components placed in the right column are
|
||
84 | * <i>always</i> positioned with their left edge aligned with the center rule.
|
||
85 | * If a component straddles both columns, it is <i>always</i> positioned with
|
||
86 | * the left edge aligned with the left rule, but is allowed to extend all the
|
||
87 | * way to the right rule. The only exception is a component that is specified
|
||
88 | * with an indent. In this case the component is moved to the right of the
|
||
89 | * respective rule by the indent amount.
|
||
90 | * <br><br>
|
||
91 | * The location of the rules is determined based on the alignment strategy
|
||
92 | * as follows:<br>
|
||
93 | * <ul>
|
||
94 | * <li>The right rule is always located at the edge of the right margin.
|
||
95 | * <li><b>Left Alignment:</b> The left rule is located the edge of the left
|
||
96 | * margin. The center rule is located far enough to the right to clear
|
||
97 | * the widest component in the left column.
|
||
98 | * <li><b>Center Alignment:</b> The center rule is located at the center of
|
||
99 | * the panel. The left rule is located far enough to the left to make
|
||
100 | * the widest component in the left column fit.
|
||
101 | * <li><b>Right Alignment</b> The center rule is located far enough to the
|
||
102 | * left of the right rule to make the widest component in the right
|
||
103 | * column fit. The left rule is located far enough to the left to make
|
||
104 | * the widest component in the left column fit.
|
||
105 | * </ul>
|
||
106 | * All components clump together vertically and are positioned right beneath
|
||
107 | * the title margin. This is of course not a very appealing presentation.
|
||
108 | * By setting how the remaining vertical space is distributed above and below
|
||
109 | * the cluster of components the cluster can be positioned more favorably
|
||
110 | * (see the shaded area in the illustration).
|
||
111 | *
|
||
112 | * @see com.izforge.izpack.gui.TwoColumnConstraints
|
||
113 | *
|
||
114 | * @version 0.0.1 / 11/14/02
|
||
115 | * @author Elmar Grom
|
||
116 | */
|
||
117 | public class TwoColumnLayout implements LayoutManager2 |
||
118 | { |
||
119 | public static final int LEFT = 0; |
||
120 | public static final int RIGHT = 1; |
||
121 | public static final int CENTER = 2; |
||
122 | |||
123 | /** holds all the components and layout constraints. */
|
||
124 | private Vector [] components = |
||
125 | { |
||
126 | new Vector (), |
||
127 | new Vector () |
||
128 | }; |
||
129 | |||
130 | /** holds the component to be placed in the title region, including layout
|
||
131 | constraints. */
|
||
132 | private TwoColumnConstraints title = null; |
||
133 | |||
134 | /** the margin setting in % of the container's width */
|
||
135 | private int margin = 0; |
||
136 | /** the setting for the buffer area on top of hte comonent cluster in % of
|
||
137 | the left over height. */
|
||
138 | private int topBuffer = 0; |
||
139 | /** the indent setting in % of the conteiner's width */
|
||
140 | private int indent = 0; |
||
141 | /** the gap between the two columns */
|
||
142 | private int gap = 5; |
||
143 | |||
144 | private int alignment = LEFT; |
||
145 | |||
146 | private int leftRule; |
||
147 | private int rightRule; |
||
148 | private int centerRule; |
||
149 | private int titleHeight; |
||
150 | |||
151 | /**
|
||
152 | * Constructs a <code>TwoColumnLayout</code> layout manager. To add components
|
||
153 | * use the container's <code>add(comp, constraints)</code> method with a
|
||
154 | * TwoColumnConstraints object.
|
||
155 | *
|
||
156 | * @param margin the margin width to use on the left and right side
|
||
157 | * in % of the total container width. Values less than
|
||
158 | * 0% and greater than 50% are not accepted.
|
||
159 | * @param gap the gap between the two columns.
|
||
160 | * @param indent the indent to use for components that have that
|
||
161 | * constraint set. This is a value in pixels.
|
||
162 | * @param topBuffer the percentage of left over vertical space to place
|
||
163 | * on top of the component cluster. Values between 0%
|
||
164 | * and 100% are accepted.
|
||
165 | * @param alignment how to align the overall layout. Legal values are
|
||
166 | * LEFT, CENTER, RIGHT.
|
||
167 | */
|
||
168 | public TwoColumnLayout (int margin, |
||
169 | int gap,
|
||
170 | int indent,
|
||
171 | int topBuffer,
|
||
172 | int alignment)
|
||
173 | { |
||
174 | this.indent = indent;
|
||
175 | this.gap = gap;
|
||
176 | |||
177 | if ((margin >= 0) && (margin <= 50)) |
||
178 | { |
||
179 | this.margin = margin;
|
||
180 | } |
||
181 | if ((topBuffer >= 0) && (topBuffer <= 100)) |
||
182 | { |
||
183 | this.topBuffer = topBuffer;
|
||
184 | } |
||
185 | if ((alignment == LEFT) || (alignment == CENTER) || (alignment == RIGHT))
|
||
186 | { |
||
187 | this.alignment = alignment;
|
||
188 | } |
||
189 | } |
||
190 | |||
191 | /**
|
||
192 | * Sets the constraints for the specified component in this layout.
|
||
193 | * <code>null</code> is a legal value for a component, but not for a
|
||
194 | * constraints object.
|
||
195 | *
|
||
196 | * @param comp the component to be modified.
|
||
197 | * @param constraints the constraints to be applied.
|
||
198 | */
|
||
199 | public void addLayoutComponent (Component comp, |
||
200 | Object constraints)
|
||
201 | { |
||
202 | if (constraints == null) |
||
203 | { |
||
204 | return;
|
||
205 | } |
||
206 | |||
207 | TwoColumnConstraints component = null;
|
||
208 | try
|
||
209 | { |
||
210 | component = (TwoColumnConstraints)constraints; |
||
211 | component = (TwoColumnConstraints)component.clone (); |
||
212 | } |
||
213 | catch (Throwable exception) |
||
214 | { |
||
215 | return;
|
||
216 | } |
||
217 | |||
218 | component.component = comp; |
||
219 | |||
220 | // ----------------------------------------------------
|
||
221 | // the title component is recorded in a separate
|
||
222 | // variable, displacing any component that might have
|
||
223 | // been previously recorded for that location.
|
||
224 | // ----------------------------------------------------
|
||
225 | if (component.position == TwoColumnConstraints.NORTH)
|
||
226 | { |
||
227 | title = component; |
||
228 | if (title.stretch)
|
||
229 | { |
||
230 | title.align = LEFT; |
||
231 | } |
||
232 | } |
||
233 | |||
234 | // ----------------------------------------------------
|
||
235 | // components that straddle both columns are a bit
|
||
236 | // tricky because these components are recorded in the
|
||
237 | // left column and the same row cannot contain a
|
||
238 | // component in the right column.
|
||
239 | //
|
||
240 | // If there are fewer components in the left column
|
||
241 | // than in the right one, a null is inserted at this
|
||
242 | // place in the right column. This allows the component
|
||
243 | // to use both columns. The component that previously
|
||
244 | // occupied this position and any that were placed
|
||
245 | // below will be pushed down by one row due to this
|
||
246 | // action.
|
||
247 | //
|
||
248 | // If there are the same number of components in both
|
||
249 | // columns or if there are fewer in the right column
|
||
250 | // then the component is added to the left column and
|
||
251 | // then the right column filled with null until both
|
||
252 | // contain the same number of components. this means
|
||
253 | // that any components that will now be placed in the
|
||
254 | // right column are positioned beneath this component.
|
||
255 | // Unoccupied spots higher in the right column become
|
||
256 | // inaccessible.
|
||
257 | // ----------------------------------------------------
|
||
258 | else if (component.position == TwoColumnConstraints.BOTH) |
||
259 | { |
||
260 | // first make sure that both columns have the same number of entries
|
||
261 | while (components [RIGHT].size () > components [LEFT].size ())
|
||
262 | { |
||
263 | components [LEFT].add (null);
|
||
264 | } |
||
265 | |||
266 | while (components [LEFT].size () > components [RIGHT].size ())
|
||
267 | { |
||
268 | components [RIGHT].add (null);
|
||
269 | } |
||
270 | |||
271 | components [LEFT].add (component); |
||
272 | components [RIGHT].add (null);
|
||
273 | } |
||
274 | |||
275 | // ----------------------------------------------------
|
||
276 | // WEST components are added to the left column
|
||
277 | // ----------------------------------------------------
|
||
278 | else if (component.position == TwoColumnConstraints.WEST) |
||
279 | { |
||
280 | components [LEFT].add (component); |
||
281 | } |
||
282 | |||
283 | // ----------------------------------------------------
|
||
284 | // WESTONLY components are added to the left column
|
||
285 | // the right column has to be kept free
|
||
286 | // ----------------------------------------------------
|
||
287 | else if (component.position == TwoColumnConstraints.WESTONLY) |
||
288 | { |
||
289 | components [LEFT].add (component); |
||
290 | |||
291 | // fill right column to make sure nothing is placed there
|
||
292 | while (components [RIGHT].size () < components [LEFT].size ())
|
||
293 | { |
||
294 | components [RIGHT].add (null);
|
||
295 | } |
||
296 | |||
297 | } |
||
298 | |||
299 | // ----------------------------------------------------
|
||
300 | // EAST components are added to the right column
|
||
301 | // ----------------------------------------------------
|
||
302 | else if (component.position == TwoColumnConstraints.EAST) |
||
303 | { |
||
304 | components [RIGHT].add (component); |
||
305 | } |
||
306 | |||
307 | // ----------------------------------------------------
|
||
308 | // EASTONLY components are added to the left column
|
||
309 | // the right column has to be kept free
|
||
310 | // ----------------------------------------------------
|
||
311 | else if (component.position == TwoColumnConstraints.EASTONLY) |
||
312 | { |
||
313 | components [RIGHT].add (component); |
||
314 | |||
315 | // fill left column to make sure nothing is placed there
|
||
316 | while (components [LEFT].size () < components [RIGHT].size ())
|
||
317 | { |
||
318 | components [LEFT].add (null);
|
||
319 | } |
||
320 | |||
321 | } |
||
322 | |||
323 | // ----------------------------------------------------
|
||
324 | // If the position did not match any of the above
|
||
325 | // criteria then the component is not added and
|
||
326 | // consequently will not be laid out.
|
||
327 | // ----------------------------------------------------
|
||
328 | } |
||
329 | |||
330 | /**
|
||
331 | * Lays out the container in the specified panel.
|
||
332 | *
|
||
333 | * @param parent the component which needs to be laid out.
|
||
334 | */
|
||
335 | public void layoutContainer (Container parent) |
||
336 | { |
||
337 | positionRules (parent); |
||
338 | positionTitle (parent); |
||
339 | positionComponents (parent); |
||
340 | } |
||
341 | |||
342 | /**
|
||
343 | * Positions the three rules in preparation for layout. Sets the variables:<br>
|
||
344 | * <ul>
|
||
345 | * <li><code>leftRule</code>
|
||
346 | * <li><code>rightRule</code>
|
||
347 | * <li><code>centerRule</code>
|
||
348 | * </ul>
|
||
349 | *
|
||
350 | * @param parent the component which needs to be laid out.
|
||
351 | */
|
||
352 | private void positionRules (Container parent) |
||
353 | { |
||
354 | int margin = margin (parent);
|
||
355 | |||
356 | if (alignment == LEFT)
|
||
357 | { |
||
358 | leftRule = margin; |
||
359 | centerRule = leftRule + minimumColumnWidth (LEFT, parent) + gap; |
||
360 | rightRule = parent.getWidth () - margin; |
||
361 | } |
||
362 | |||
363 | else if (alignment == CENTER) |
||
364 | { |
||
365 | centerRule = (int)(parent.getMinimumSize ().getWidth () / 2); |
||
366 | leftRule = centerRule - minimumColumnWidth (LEFT, parent) - gap; |
||
367 | rightRule = parent.getWidth () - margin; |
||
368 | } |
||
369 | |||
370 | else if (alignment == RIGHT) |
||
371 | { |
||
372 | rightRule = parent.getWidth () - margin; |
||
373 | centerRule = rightRule - minimumColumnWidth (RIGHT, parent); |
||
374 | leftRule = centerRule - minimumColumnWidth (LEFT, parent) - gap; |
||
375 | } |
||
376 | } |
||
377 | |||
378 | /**
|
||
379 | * Positions the title component and sets the variable <code>titleHeight</code>.
|
||
380 | * <b>Note:</b> this method depends on the fact that the rules are set to
|
||
381 | * their correct layout position.
|
||
382 | *
|
||
383 | * @param parent the component which needs to be laid out.
|
||
384 | */
|
||
385 | private void positionTitle (Container parent) |
||
386 | { |
||
387 | if (title != null) |
||
388 | { |
||
389 | Component component = title.component;
|
||
390 | int width = (int)component.getMinimumSize ().getWidth (); |
||
391 | titleHeight = (int)component.getMinimumSize ().getHeight ();
|
||
392 | |||
393 | if (component != null) |
||
394 | { |
||
395 | if (title.stretch)
|
||
396 | { |
||
397 | width = rightRule - leftRule; |
||
398 | component.setBounds (leftRule, 0, width, titleHeight);
|
||
399 | } |
||
400 | |||
401 | else if (title.align == TwoColumnConstraints.LEFT) |
||
402 | { |
||
403 | component.setBounds (leftRule, 0, width, titleHeight);
|
||
404 | } |
||
405 | |||
406 | else if (title.align == TwoColumnConstraints.CENTER) |
||
407 | { |
||
408 | int left = centerRule - (width / 2); |
||
409 | component.setBounds (left, 0, width, titleHeight);
|
||
410 | } |
||
411 | |||
412 | else if (title.align == TwoColumnConstraints.RIGHT) |
||
413 | { |
||
414 | int left = rightRule - width;
|
||
415 | component.setBounds (left, 0, width, titleHeight);
|
||
416 | } |
||
417 | } |
||
418 | } |
||
419 | } |
||
420 | |||
421 | /**
|
||
422 | * Positions all components in the container.
|
||
423 | *
|
||
424 | * @param parent the component which needs to be laid out.
|
||
425 | */
|
||
426 | private void positionComponents (Container parent) |
||
427 | { |
||
428 | int usedHeight = titleHeight + minimumClusterHeight ();
|
||
429 | int topBuffer = topBuffer (usedHeight, parent);
|
||
430 | int leftHeight = 0; |
||
431 | int rightHeight = 0; |
||
432 | |||
433 | if (topBuffer < 0) |
||
434 | { |
||
435 | topBuffer = 0;
|
||
436 | } |
||
437 | |||
438 | int y = titleHeight + topBuffer;
|
||
439 | |||
440 | for (int i = 0; i < rows (); i++) |
||
441 | { |
||
442 | leftHeight = height (i, LEFT); |
||
443 | rightHeight = height (i, RIGHT); |
||
444 | |||
445 | if (leftHeight > rightHeight)
|
||
446 | { |
||
447 | int offset = (leftHeight - rightHeight) / 2; |
||
448 | |||
449 | positionComponent (y, i, LEFT, parent); |
||
450 | positionComponent ((y + offset), i, RIGHT, parent); |
||
451 | |||
452 | y = y + leftHeight; |
||
453 | } |
||
454 | else if (leftHeight < rightHeight) |
||
455 | { |
||
456 | int offset = (rightHeight - leftHeight) / 2; |
||
457 | |||
458 | positionComponent ((y + offset), i, LEFT, parent); |
||
459 | positionComponent (y, i, RIGHT, parent); |
||
460 | |||
461 | y = y + rightHeight; |
||
462 | } |
||
463 | else
|
||
464 | { |
||
465 | positionComponent (y, i, LEFT, parent); |
||
466 | positionComponent (y, i, RIGHT, parent); |
||
467 | |||
468 | y = y + leftHeight; |
||
469 | } |
||
470 | } |
||
471 | } |
||
472 | |||
473 | /**
|
||
474 | * Positiones one component as instructed. Constraints for each component,
|
||
475 | * such as <code>stretch</code>, <code>BOTH</code> and <code>indent</code>
|
||
476 | * are taken into account. In addition, empty comonents are handled properly.
|
||
477 | *
|
||
478 | * @param y the y location within the continer, where the
|
||
479 | * component should be positioned.
|
||
480 | * @param row the row of the component
|
||
481 | * @param column the column of the component
|
||
482 | * @param parent the container which needs to be laid out.
|
||
483 | */
|
||
484 | private void positionComponent (int y, |
||
485 | int row,
|
||
486 | int column,
|
||
487 | Container parent)
|
||
488 | { |
||
489 | TwoColumnConstraints constraints = null;
|
||
490 | |||
491 | try
|
||
492 | { |
||
493 | constraints = (TwoColumnConstraints)(components [column].elementAt (row)); |
||
494 | } |
||
495 | catch (Throwable exception) |
||
496 | { |
||
497 | return;
|
||
498 | } |
||
499 | |||
500 | int x = 0; |
||
501 | |||
502 | if (constraints != null) |
||
503 | { |
||
504 | Component component = constraints.component;
|
||
505 | int width = (int)component.getPreferredSize ().getWidth (); |
||
506 | int height = (int)component.getPreferredSize ().getHeight (); |
||
507 | |||
508 | // --------------------------------------------------
|
||
509 | // set x to the appropriate rule. The only need to
|
||
510 | // modify this is for indent
|
||
511 | // --------------------------------------------------
|
||
512 | if (column == LEFT)
|
||
513 | { |
||
514 | x = leftRule; |
||
515 | } |
||
516 | else
|
||
517 | { |
||
518 | x = centerRule; |
||
519 | } |
||
520 | |||
521 | if (component != null) |
||
522 | { |
||
523 | // --------------------------------------------------
|
||
524 | // set the width for stretch based on BOTH, LEFT and
|
||
525 | // RIGHT positionsing
|
||
526 | // --------------------------------------------------
|
||
527 | if ((constraints.stretch) && (constraints.position == TwoColumnConstraints.BOTH))
|
||
528 | { |
||
529 | width = rightRule - leftRule; |
||
530 | x = leftRule; |
||
531 | } |
||
532 | else if ((constraints.stretch) && (column == LEFT)) |
||
533 | { |
||
534 | width = centerRule - leftRule; |
||
535 | } |
||
536 | else if ((constraints.stretch) && (column == RIGHT)) |
||
537 | { |
||
538 | width = rightRule - centerRule; |
||
539 | } |
||
540 | |||
541 | // --------------------------------------------------
|
||
542 | // if we straddle both columns but are not stretching
|
||
543 | // use the preferred width as long as it is less then
|
||
544 | // the width of both columns combined. Also set the x
|
||
545 | // position to left, just to be sure.
|
||
546 | // --------------------------------------------------
|
||
547 | else if (constraints.position == TwoColumnConstraints.BOTH) |
||
548 | { |
||
549 | if (width > (rightRule - leftRule))
|
||
550 | { |
||
551 | width = rightRule - leftRule; |
||
552 | } |
||
553 | x = leftRule; |
||
554 | } |
||
555 | |||
556 | // --------------------------------------------------
|
||
557 | // correct for indent if this option is set
|
||
558 | // --------------------------------------------------
|
||
559 | if (constraints.indent)
|
||
560 | { |
||
561 | width = width - indent; |
||
562 | x = x + indent; |
||
563 | } |
||
564 | |||
565 | component.setBounds (x, y, width, height); |
||
566 | } |
||
567 | } |
||
568 | } |
||
569 | |||
570 | /**
|
||
571 | * Returns the minimum width of the column requested.
|
||
572 | *
|
||
573 | * @param column the columns to measure (LEFT / RIGHT)
|
||
574 | * @param parent the component which needs to be laid out.
|
||
575 | *
|
||
576 | * @return the minimum width required to fis the components in this column
|
||
577 | */
|
||
578 | private int minimumColumnWidth (int column, |
||
579 | Container parent)
|
||
580 | { |
||
581 | Component component = null; |
||
582 | TwoColumnConstraints constraints = null;
|
||
583 | int width = 0; |
||
584 | int temp = 0; |
||
585 | |||
586 | for (int i = 0; i < components [column].size (); i++) |
||
587 | { |
||
588 | constraints = (TwoColumnConstraints)components [column].elementAt (i); |
||
589 | |||
590 | if ((constraints != null) && |
||
591 | (constraints.position != TwoColumnConstraints.BOTH) ) |
||
592 | { |
||
593 | component = constraints.component; |
||
594 | temp = (int)component.getMinimumSize ().getWidth ();
|
||
595 | |||
596 | if (constraints.indent)
|
||
597 | { |
||
598 | temp = temp + indent; |
||
599 | } |
||
600 | |||
601 | if (temp > width)
|
||
602 | { |
||
603 | width = temp; |
||
604 | } |
||
605 | } |
||
606 | } |
||
607 | |||
608 | return (width);
|
||
609 | } |
||
610 | |||
611 | /**
|
||
612 | * Retrunds the minimum width both columns together should have based on the
|
||
613 | * minimum widths of all the components that straddle both columns and the
|
||
614 | * minimum width of the title component.
|
||
615 | *
|
||
616 | * @param parent the component which needs to be laid out.
|
||
617 | *
|
||
618 | * @return the minimum width required to fis the components in this column
|
||
619 | */
|
||
620 | private int minimumBothColumnsWidth (Container parent) |
||
621 | { |
||
622 | Component component = null; |
||
623 | TwoColumnConstraints constraints = null;
|
||
624 | int width = 0; |
||
625 | int temp = 0; |
||
626 | |||
627 | if (title != null) |
||
628 | { |
||
629 | component = title.component; |
||
630 | width = (int)component.getMinimumSize ().getWidth ();
|
||
631 | } |
||
632 | |||
633 | for (int i = 0; i < components [LEFT].size (); i++) |
||
634 | { |
||
635 | constraints = (TwoColumnConstraints)components [LEFT].elementAt (i); |
||
636 | |||
637 | if ((constraints != null) && |
||
638 | (constraints.position == TwoColumnConstraints.BOTH) ) |
||
639 | { |
||
640 | component = constraints.component; |
||
641 | temp = (int)component.getMinimumSize ().getWidth ();
|
||
642 | |||
643 | if (constraints.indent)
|
||
644 | { |
||
645 | temp = temp + indent; |
||
646 | } |
||
647 | |||
648 | if (temp > width)
|
||
649 | { |
||
650 | width = temp; |
||
651 | } |
||
652 | } |
||
653 | } |
||
654 | |||
655 | return (width);
|
||
656 | } |
||
657 | |||
658 | private int minimumClusterHeight () |
||
659 | { |
||
660 | int height = 0; |
||
661 | |||
662 | for (int i = 0; i < rows (); i++) |
||
663 | { |
||
664 | height = height + rowHeight (i); |
||
665 | } |
||
666 | |||
667 | return (height);
|
||
668 | } |
||
669 | |||
670 | /**
|
||
671 | * Returns the number of rows that need to be laid out.
|
||
672 | */
|
||
673 | private int rows () |
||
674 | { |
||
675 | int rows = 0; |
||
676 | int leftRows = components [LEFT].size ();
|
||
677 | int rightRows = components [RIGHT].size ();
|
||
678 | |||
679 | if (leftRows > rightRows)
|
||
680 | { |
||
681 | rows = leftRows; |
||
682 | } |
||
683 | else
|
||
684 | { |
||
685 | rows = rightRows; |
||
686 | } |
||
687 | |||
688 | return (rows);
|
||
689 | } |
||
690 | |||
691 | /**
|
||
692 | * Measures and returns the minimum height required to render the components
|
||
693 | * in the indicated row.
|
||
694 | *
|
||
695 | * @param row the index of the row to measure
|
||
696 | */
|
||
697 | private int rowHeight (int row) |
||
698 | { |
||
699 | int height = 0; |
||
700 | int height1 = height (row, LEFT);
|
||
701 | int height2 = height (row, RIGHT);
|
||
702 | |||
703 | // ----------------------------------------------------
|
||
704 | // take the higher one
|
||
705 | // ----------------------------------------------------
|
||
706 | if (height1 > height2)
|
||
707 | { |
||
708 | height = height1; |
||
709 | } |
||
710 | else
|
||
711 | { |
||
712 | height = height2; |
||
713 | } |
||
714 | |||
715 | return (height);
|
||
716 | } |
||
717 | |||
718 | /**
|
||
719 | * Measures and returns the minimum height required to render the component
|
||
720 | * in the indicated row and column.
|
||
721 | *
|
||
722 | * @param row the index of the row to measure
|
||
723 | * @param column the column of the component to measure
|
||
724 | * (<code>LEFT</code> or <code>RIGHT</code>)
|
||
725 | */
|
||
726 | private int height (int row, |
||
727 | int column)
|
||
728 | { |
||
729 | int height = 0; |
||
730 | int width = 0; |
||
731 | Component component;
|
||
732 | TwoColumnConstraints constraints; |
||
733 | |||
734 | try
|
||
735 | { |
||
736 | constraints = (TwoColumnConstraints)components [column].elementAt (row); |
||
737 | if (constraints != null) |
||
738 | { |
||
739 | component = constraints.component; |
||
740 | width = (int)component.getMinimumSize ().getWidth ();
|
||
741 | height = (int)component.getMinimumSize ().getHeight ();
|
||
742 | |||
743 | if (constraints.position == TwoColumnConstraints.WEST)
|
||
744 | { |
||
745 | if (width > (centerRule - leftRule))
|
||
746 | { |
||
747 | component.setBounds (0, 0, (centerRule - leftRule), height); |
||
748 | } |
||
749 | } |
||
750 | else if (constraints.position == TwoColumnConstraints.EAST) |
||
751 | { |
||
752 | if (width > (rightRule - centerRule))
|
||
753 | { |
||
754 | component.setBounds (0, 0, (rightRule - centerRule), height); |
||
755 | } |
||
756 | } |
||
757 | else if (constraints.position == TwoColumnConstraints.BOTH) |
||
758 | { |
||
759 | if (width > (rightRule - leftRule))
|
||
760 | { |
||
761 | component.setBounds (0, 0, (rightRule - leftRule), height); |
||
762 | } |
||
763 | } |
||
764 | |||
765 | height = (int)component.getMinimumSize ().getHeight ();
|
||
766 | } |
||
767 | } |
||
768 | // ----------------------------------------------------
|
||
769 | // we might get an exception if one of the vectors is
|
||
770 | // shorter, because we index out of bounds. If there
|
||
771 | // is nothing there then the height is 0, nothing
|
||
772 | // further to worry about!
|
||
773 | // ----------------------------------------------------
|
||
774 | catch (Throwable exception) |
||
775 | {} |
||
776 | |||
777 | return (height);
|
||
778 | } |
||
779 | |||
780 | /**
|
||
781 | * Computes the margin value based on the container width and the margin setting.
|
||
782 | *
|
||
783 | * @param parent the component which needs to be laid out.
|
||
784 | */
|
||
785 | private int margin (Container parent) |
||
786 | { |
||
787 | int amount = (int)(((parent.getSize ().getWidth ()) * margin) / 100); |
||
788 | |||
789 | return (amount);
|
||
790 | } |
||
791 | |||
792 | /**
|
||
793 | * Computes the top buffer value based on the container width and the setting
|
||
794 | * for the top buffer
|
||
795 | *
|
||
796 | * @param usedHeight the amount of the parent component's height that
|
||
797 | * is already in use (height of the title and the combined height
|
||
798 | * of all rows).
|
||
799 | * @param parent the component which needs to be laid out.
|
||
800 | */
|
||
801 | private int topBuffer (int usedHeight, |
||
802 | Container parent)
|
||
803 | { |
||
804 | int amount = ((int)parent.getSize ().getHeight ()) - usedHeight; |
||
805 | amount = (int)(amount * topBuffer) / 100; |
||
806 | |||
807 | return (amount);
|
||
808 | } |
||
809 | /*--------------------------------------------------------------------------*/
|
||
810 | /**
|
||
811 | * Computes the indent value based on the container width and the indent setting.
|
||
812 | *
|
||
813 | * @param parent the component which needs to be laid out.
|
||
814 | */
|
||
815 | /*--------------------------------------------------------------------------*/
|
||
816 | /* private int indent (Container parent)
|
||
817 | {
|
||
818 | int amount = (int)(((parent.getMinimumSize ().getWidth ()) * indent) / 100);
|
||
819 | |||
820 | return (amount);
|
||
821 | }*/
|
||
822 | /**
|
||
823 | * Calculates the preferred size dimensions for the specified panel given
|
||
824 | * the components in the specified parent container.
|
||
825 | *
|
||
826 | * @param parent the component to be laid out
|
||
827 | */
|
||
828 | public Dimension preferredLayoutSize (Container parent) |
||
829 | { |
||
830 | return (minimumLayoutSize (parent));
|
||
831 | } |
||
832 | |||
833 | /**
|
||
834 | * Calculates the minimum size dimensions for the specified panel given the
|
||
835 | * components in the specified parent container.
|
||
836 | *
|
||
837 | * @param parent the component to be laid out
|
||
838 | */
|
||
839 | public Dimension minimumLayoutSize (Container parent) |
||
840 | { |
||
841 | positionTitle (parent); |
||
842 | |||
843 | int width = minimumBothColumnsWidth (parent);
|
||
844 | int height = minimumClusterHeight () + titleHeight;
|
||
845 | |||
846 | return (new Dimension (width, height)); |
||
847 | } |
||
848 | |||
849 | /**
|
||
850 | * Calculates the maximum size dimensions for the specified panel given the
|
||
851 | * components in the specified parent container.
|
||
852 | *
|
||
853 | * @param parent the component to be laid out
|
||
854 | */
|
||
855 | public Dimension maximumLayoutSize (Container parent) |
||
856 | { |
||
857 | return (minimumLayoutSize (parent));
|
||
858 | } |
||
859 | |||
860 | /**
|
||
861 | * Returns the alignment along the x axis. This specifies how the component
|
||
862 | * would like to be aligned relative to other components. The value should
|
||
863 | * be a number between 0 and 1 where 0 represents alignment along the origin,
|
||
864 | * 1 is aligned the furthest away from the origin, 0.5 is centered, etc.
|
||
865 | *
|
||
866 | * @param parent the component to be laid out
|
||
867 | */
|
||
868 | public float getLayoutAlignmentX (Container parent) |
||
869 | { |
||
870 | return (0); |
||
871 | } |
||
872 | |||
873 | /**
|
||
874 | * Returns the alignment along the y axis. This specifies how the component
|
||
875 | * would like to be aligned relative to other components. The value should
|
||
876 | * be a number between 0 and 1 where 0 represents alignment along the origin,
|
||
877 | * 1 is aligned the furthest away from the origin, 0.5 is centered, etc.
|
||
878 | *
|
||
879 | * @param parent the component to be laid out
|
||
880 | */
|
||
881 | public float getLayoutAlignmentY (Container parent) |
||
882 | { |
||
883 | return (0); |
||
884 | } |
||
885 | |||
886 | /**
|
||
887 | * Invalidates the layout, indicating that if the layout manager has cached
|
||
888 | * information it should be discarded.
|
||
889 | *
|
||
890 | * @param parent the component to be laid out
|
||
891 | */
|
||
892 | public void invalidateLayout (Container parent) |
||
893 | { |
||
894 | leftRule = 0;
|
||
895 | rightRule = 0;
|
||
896 | centerRule = 0;
|
||
897 | titleHeight = 0;
|
||
898 | } |
||
899 | |||
900 | /**
|
||
901 | * Adds the specified component with the specified name to the layout. This
|
||
902 | * version is not supported, use <code>addLayoutComponent</code> with layout
|
||
903 | * contsraints.
|
||
904 | *
|
||
905 | * @param name the component name
|
||
906 | * @param comp the component to be added
|
||
907 | */
|
||
908 | public void addLayoutComponent (String name, |
||
909 | Component comp)
|
||
910 | { } |
||
911 | |||
912 | /**
|
||
913 | * This functionality is not supported
|
||
914 | *
|
||
915 | * @param comp the component to be removed
|
||
916 | */
|
||
917 | public void removeLayoutComponent (Component comp) |
||
918 | { } |
||
919 | |||
920 | /**
|
||
921 | * This method is provided for conveninence of debugging layout problems. It
|
||
922 | * renders the three rules and the limit of the title marign visible after
|
||
923 | * these positions have been computed. In addition, the indent locations are
|
||
924 | * shown as dashed lines. To use this functionality do the following:<br><br>
|
||
925 | * <ul>
|
||
926 | * <li>in the container using this layout manager override the
|
||
927 | * <code>paint()</code> method.
|
||
928 | * <li>in that method, first call <code>super.paint()</code>
|
||
929 | * <li>then call this method
|
||
930 | * </ul><br>
|
||
931 | * <b>Note:</b> cast the graphics object received in the <code>paint()</code>
|
||
932 | * method to <code>Graphics2D</code> when making the call.<br><br>
|
||
933 | *
|
||
934 | * @param graphics the graphics context used for drawing.
|
||
935 | * @param color the color to use for rendering the layout grid
|
||
936 | */
|
||
937 | public void showRules (Graphics2D graphics, |
||
938 | Color color)
|
||
939 | { |
||
940 | int height = graphics.getClipBounds ().height;
|
||
941 | |||
942 | Stroke currentStroke = graphics.getStroke ();
|
||
943 | Color currentColor = graphics.getColor ();
|
||
944 | |||
945 | Stroke stroke = new BasicStroke (1, |
||
946 | BasicStroke.CAP_BUTT,
|
||
947 | BasicStroke.JOIN_BEVEL,
|
||
948 | 1.5f,
|
||
949 | new float [] {10, 5}, |
||
950 | 5);
|
||
951 | graphics.setColor (color); |
||
952 | |||
953 | graphics.drawLine (leftRule, 0, leftRule, height);
|
||
954 | graphics.drawLine (centerRule, titleHeight, centerRule, height); |
||
955 | graphics.drawLine (rightRule, 0, rightRule, height);
|
||
956 | graphics.drawLine (leftRule, titleHeight, rightRule, titleHeight); |
||
957 | |||
958 | graphics.setStroke (stroke); |
||
959 | graphics.drawLine ((leftRule + indent), titleHeight, (leftRule + indent), height); |
||
960 | graphics.drawLine ((centerRule + indent), titleHeight, (centerRule + indent), height); |
||
961 | |||
962 | graphics.setStroke (currentStroke); |
||
963 | graphics.setColor (currentColor); |
||
964 | } |
||
965 | } |
||
966 | /*---------------------------------------------------------------------------*/ |