svn-gvsig-desktop / trunk / build / distribution / IzPack / src / lib / com / izforge / izpack / gui / TwoColumnLayout.java @ 21757
History | View | Annotate | Download (32 KB)
1 |
/*
|
---|---|
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 |
/*---------------------------------------------------------------------------*/
|