001: /*
002: * IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved.
003: *
004: * http://izpack.org/
005: * http://izpack.codehaus.org/
006: *
007: * Copyright 2002 Elmar Grom
008: *
009: * Licensed under the Apache License, Version 2.0 (the "License");
010: * you may not use this file except in compliance with the License.
011: * You may obtain a copy of the License at
012: *
013: * http://www.apache.org/licenses/LICENSE-2.0
014: *
015: * Unless required by applicable law or agreed to in writing, software
016: * distributed under the License is distributed on an "AS IS" BASIS,
017: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018: * See the License for the specific language governing permissions and
019: * limitations under the License.
020: */
021:
022: package com.izforge.izpack.gui;
023:
024: import java.awt.*;
025: import java.util.Vector;
026:
027: /**
028: * This class implements a layout manager that generally lays out components in two columns. <BR>
029: * <BR>
030: * The design goal for this layout manager was to lay out forms for data entry, where there are
031: * several rows of entry fields with associated labels. The goal was to have the beginning off all
032: * labels line up, as well as the left edge of all the data entry fields. This leads to a situation
033: * where all components are essentially laid out in two columns. The columns adjust to accommodate
034: * components of various sizes. This means that components that are added are laid out top to
035: * bottom, either in the left column, in the right column or straddling both columns. In addition to
036: * this general behavior, the following additional layout capabilities are supported:<br>
037: * <ul>
038: * <li>Resizable margins are provided on the left and right side.
039: * <li>A special region is provided at the top that is only affected by the side margins but not by
040: * any other layout behavior.
041: * <li>It is possible to specify the vertical positioning of the cluster of laid out components for
042: * the case that they do not occupy the entire available real estate.
043: * <li>Individual components can be indented.
044: * </ul>
045: *
046: * <b>The Layout Behavior</b> <br>
047: * <br>
048: * The left and right margin are absolute. This means that they can not be penetrated by components.
049: * All layout happens between the limits established by these margins. The purpose of these margins
050: * is to ensure that components are not laid out all the way to the edge of their container, without
051: * the need to set matching borders for each component. <br>
052: * <br>
053: * The title margin at the top factors only into the layout behavior if there is a component set to
054: * be laid out in that region, otherwise it is ignored. <br>
055: * <br>
056: * The vertical space available to each row of components depends on the space requirements of the
057: * tallest component in that row. Both components are placed vertically centered in their row. <br>
058: * <br>
059: * All horizontal layout is based on the position of three vertical rules, the left rule, the right
060: * rule and the center rule. <br>
061: * <br>
062: * <img src="doc-files/TwoColumnLayout.gif"/> <br>
063: * <br>
064: * The actual position of each rule depends on the alignment strategy, margin settings and component
065: * sizes. Regardless of these factors, components placed in the left column are <i>always</i>
066: * positioned with their left edge aligned with the left rule. Components placed in the right column
067: * are <i>always</i> positioned with their left edge aligned with the center rule. If a component
068: * straddles both columns, it is <i>always</i> positioned with the left edge aligned with the left
069: * rule, but is allowed to extend all the way to the right rule. The only exception is a component
070: * that is specified with an indent. In this case the component is moved to the right of the
071: * respective rule by the indent amount. <br>
072: * <br>
073: * The location of the rules is determined based on the alignment strategy as follows:<br>
074: * <ul>
075: * <li>The right rule is always located at the edge of the right margin.
076: * <li><b>Left Alignment:</b> The left rule is located the edge of the left margin. The center
077: * rule is located far enough to the right to clear the widest component in the left column.
078: * <li><b>Center Alignment:</b> The center rule is located at the center of the panel. The left
079: * rule is located far enough to the left to make the widest component in the left column fit.
080: * <li><b>Right Alignment</b> The center rule is located far enough to the left of the right rule
081: * to make the widest component in the right column fit. The left rule is located far enough to the
082: * left to make the widest component in the left column fit.
083: * </ul>
084: * All components clump together vertically and are positioned right beneath the title margin. This
085: * is of course not a very appealing presentation. By setting how the remaining vertical space is
086: * distributed above and below the cluster of components the cluster can be positioned more
087: * favorably (see the shaded area in the illustration).
088: *
089: * @see com.izforge.izpack.gui.TwoColumnConstraints
090: *
091: * @version 0.0.1 / 11/14/02
092: * @author Elmar Grom
093: */
094: public class TwoColumnLayout implements LayoutManager2 {
095:
096: public static final int LEFT = 0;
097:
098: public static final int RIGHT = 1;
099:
100: public static final int CENTER = 2;
101:
102: /** holds all the components and layout constraints. */
103: private Vector[] components = { new Vector(), new Vector() };
104:
105: /**
106: * holds the component to be placed in the title region, including layout constraints.
107: */
108: private TwoColumnConstraints title = null;
109:
110: /** the margin setting in % of the container's width */
111: private int margin = 0;
112:
113: /**
114: * the setting for the buffer area on top of hte comonent cluster in % of the left over height.
115: */
116: private int topBuffer = 0;
117:
118: /** the indent setting in % of the conteiner's width */
119: private int indent = 0;
120:
121: /** the gap between the two columns */
122: private int gap = 5;
123:
124: private int alignment = LEFT;
125:
126: private int leftRule;
127:
128: private int rightRule;
129:
130: private int centerRule;
131:
132: private int titleHeight;
133:
134: /**
135: * Constructs a <code>TwoColumnLayout</code> layout manager. To add components use the
136: * container's <code>add(comp, constraints)</code> method with a TwoColumnConstraints object.
137: *
138: * @param margin the margin width to use on the left and right side in % of the total container
139: * width. Values less than 0% and greater than 50% are not accepted.
140: * @param gap the gap between the two columns.
141: * @param indent the indent to use for components that have that constraint set. This is a value
142: * in pixels.
143: * @param topBuffer the percentage of left over vertical space to place on top of the component
144: * cluster. Values between 0% and 100% are accepted.
145: * @param alignment how to align the overall layout. Legal values are LEFT, CENTER, RIGHT.
146: */
147: public TwoColumnLayout(int margin, int gap, int indent,
148: int topBuffer, int alignment) {
149: this .indent = indent;
150: this .gap = gap;
151:
152: if ((margin >= 0) && (margin <= 50)) {
153: this .margin = margin;
154: }
155: if ((topBuffer >= 0) && (topBuffer <= 100)) {
156: this .topBuffer = topBuffer;
157: }
158: if ((alignment == LEFT) || (alignment == CENTER)
159: || (alignment == RIGHT)) {
160: this .alignment = alignment;
161: }
162: }
163:
164: /**
165: * Sets the constraints for the specified component in this layout. <code>null</code> is a
166: * legal value for a component, but not for a constraints object.
167: *
168: * @param comp the component to be modified.
169: * @param constraints the constraints to be applied.
170: */
171: public void addLayoutComponent(Component comp, Object constraints) {
172: if (constraints == null) {
173: return;
174: }
175:
176: TwoColumnConstraints component = null;
177: try {
178: component = (TwoColumnConstraints) constraints;
179: component = (TwoColumnConstraints) component.clone();
180: } catch (Throwable exception) {
181: return;
182: }
183:
184: component.component = comp;
185:
186: // ----------------------------------------------------
187: // the title component is recorded in a separate
188: // variable, displacing any component that might have
189: // been previously recorded for that location.
190: // ----------------------------------------------------
191: if (component.position == TwoColumnConstraints.NORTH) {
192: title = component;
193: if (title.stretch) {
194: title.align = LEFT;
195: }
196: }
197:
198: // ----------------------------------------------------
199: // components that straddle both columns are a bit
200: // tricky because these components are recorded in the
201: // left column and the same row cannot contain a
202: // component in the right column.
203: //
204: // If there are fewer components in the left column
205: // than in the right one, a null is inserted at this
206: // place in the right column. This allows the component
207: // to use both columns. The component that previously
208: // occupied this position and any that were placed
209: // below will be pushed down by one row due to this
210: // action.
211: //
212: // If there are the same number of components in both
213: // columns or if there are fewer in the right column
214: // then the component is added to the left column and
215: // then the right column filled with null until both
216: // contain the same number of components. this means
217: // that any components that will now be placed in the
218: // right column are positioned beneath this component.
219: // Unoccupied spots higher in the right column become
220: // inaccessible.
221: // ----------------------------------------------------
222: else if (component.position == TwoColumnConstraints.BOTH) {
223: // first make sure that both columns have the same number of entries
224: while (components[RIGHT].size() > components[LEFT].size()) {
225: components[LEFT].add(null);
226: }
227:
228: while (components[LEFT].size() > components[RIGHT].size()) {
229: components[RIGHT].add(null);
230: }
231:
232: components[LEFT].add(component);
233: components[RIGHT].add(null);
234: }
235:
236: // ----------------------------------------------------
237: // WEST components are added to the left column
238: // ----------------------------------------------------
239: else if (component.position == TwoColumnConstraints.WEST) {
240: components[LEFT].add(component);
241: }
242:
243: // ----------------------------------------------------
244: // WESTONLY components are added to the left column
245: // the right column has to be kept free
246: // ----------------------------------------------------
247: else if (component.position == TwoColumnConstraints.WESTONLY) {
248: components[LEFT].add(component);
249:
250: // fill right column to make sure nothing is placed there
251: while (components[RIGHT].size() < components[LEFT].size()) {
252: components[RIGHT].add(null);
253: }
254:
255: }
256:
257: // ----------------------------------------------------
258: // EAST components are added to the right column
259: // ----------------------------------------------------
260: else if (component.position == TwoColumnConstraints.EAST) {
261: components[RIGHT].add(component);
262: }
263:
264: // ----------------------------------------------------
265: // EASTONLY components are added to the left column
266: // the right column has to be kept free
267: // ----------------------------------------------------
268: else if (component.position == TwoColumnConstraints.EASTONLY) {
269: components[RIGHT].add(component);
270:
271: // fill left column to make sure nothing is placed there
272: while (components[LEFT].size() < components[RIGHT].size()) {
273: components[LEFT].add(null);
274: }
275:
276: }
277:
278: // ----------------------------------------------------
279: // If the position did not match any of the above
280: // criteria then the component is not added and
281: // consequently will not be laid out.
282: // ----------------------------------------------------
283: }
284:
285: /**
286: * Lays out the container in the specified panel.
287: *
288: * @param parent the component which needs to be laid out.
289: */
290: public void layoutContainer(Container parent) {
291: positionRules(parent);
292: positionTitle(parent);
293: positionComponents(parent);
294: }
295:
296: /**
297: * Positions the three rules in preparation for layout. Sets the variables:<br>
298: * <ul>
299: * <li><code>leftRule</code>
300: * <li><code>rightRule</code>
301: * <li><code>centerRule</code>
302: * </ul>
303: *
304: * @param parent the component which needs to be laid out.
305: */
306: private void positionRules(Container parent) {
307: int margin = margin(parent);
308:
309: if (alignment == LEFT) {
310: leftRule = margin;
311: centerRule = leftRule + minimumColumnWidth(LEFT, parent)
312: + gap;
313: rightRule = parent.getWidth() - margin;
314: }
315:
316: else if (alignment == CENTER) {
317: centerRule = (int) (parent.getMinimumSize().getWidth() / 2);
318: leftRule = centerRule - minimumColumnWidth(LEFT, parent)
319: - gap;
320: rightRule = parent.getWidth() - margin;
321: }
322:
323: else if (alignment == RIGHT) {
324: rightRule = parent.getWidth() - margin;
325: centerRule = rightRule - minimumColumnWidth(RIGHT, parent);
326: leftRule = centerRule - minimumColumnWidth(LEFT, parent)
327: - gap;
328: }
329: }
330:
331: /**
332: * Positions the title component and sets the variable <code>titleHeight</code>. <b>Note:</b>
333: * this method depends on the fact that the rules are set to their correct layout position.
334: *
335: * @param parent the component which needs to be laid out.
336: */
337: private void positionTitle(Container parent) {
338: if (title != null) {
339: Component component = title.component;
340: int width = (int) component.getMinimumSize().getWidth();
341: titleHeight = (int) component.getMinimumSize().getHeight();
342:
343: if (component != null) {
344: if (title.stretch) {
345: width = rightRule - leftRule;
346: component
347: .setBounds(leftRule, 0, width, titleHeight);
348: }
349:
350: else if (title.align == TwoColumnConstraints.LEFT) {
351: component
352: .setBounds(leftRule, 0, width, titleHeight);
353: }
354:
355: else if (title.align == TwoColumnConstraints.CENTER) {
356: int left = centerRule - (width / 2);
357: component.setBounds(left, 0, width, titleHeight);
358: }
359:
360: else if (title.align == TwoColumnConstraints.RIGHT) {
361: int left = rightRule - width;
362: component.setBounds(left, 0, width, titleHeight);
363: }
364: }
365: }
366: }
367:
368: /**
369: * Positions all components in the container.
370: *
371: * @param parent the component which needs to be laid out.
372: */
373: private void positionComponents(Container parent) {
374: int usedHeight = titleHeight + minimumClusterHeight();
375: int topBuffer = topBuffer(usedHeight, parent);
376: int leftHeight = 0;
377: int rightHeight = 0;
378:
379: if (topBuffer < 0) {
380: topBuffer = 0;
381: }
382:
383: int y = titleHeight + topBuffer;
384:
385: for (int i = 0; i < rows(); i++) {
386: leftHeight = height(i, LEFT);
387: rightHeight = height(i, RIGHT);
388:
389: if (leftHeight > rightHeight) {
390: int offset = (leftHeight - rightHeight) / 2;
391:
392: positionComponent(y, i, LEFT, parent);
393: positionComponent((y + offset), i, RIGHT, parent);
394:
395: y += leftHeight;
396: } else if (leftHeight < rightHeight) {
397: int offset = (rightHeight - leftHeight) / 2;
398:
399: positionComponent((y + offset), i, LEFT, parent);
400: positionComponent(y, i, RIGHT, parent);
401:
402: y += rightHeight;
403: } else {
404: positionComponent(y, i, LEFT, parent);
405: positionComponent(y, i, RIGHT, parent);
406:
407: y += leftHeight;
408: }
409: }
410: }
411:
412: /**
413: * Positiones one component as instructed. Constraints for each component, such as
414: * <code>stretch</code>, <code>BOTH</code> and <code>indent</code> are taken into
415: * account. In addition, empty comonents are handled properly.
416: *
417: * @param y the y location within the continer, where the component should be positioned.
418: * @param row the row of the component
419: * @param column the column of the component
420: * @param parent the container which needs to be laid out.
421: */
422: private void positionComponent(int y, int row, int column,
423: Container parent) {
424: TwoColumnConstraints constraints = null;
425:
426: try {
427: constraints = (TwoColumnConstraints) (components[column]
428: .elementAt(row));
429: } catch (Throwable exception) {
430: return;
431: }
432:
433: int x = 0;
434:
435: if (constraints != null) {
436: Component component = constraints.component;
437: int width = (int) component.getPreferredSize().getWidth();
438: int height = (int) component.getPreferredSize().getHeight();
439:
440: // --------------------------------------------------
441: // set x to the appropriate rule. The only need to
442: // modify this is for indent
443: // --------------------------------------------------
444: if (column == LEFT) {
445: x = leftRule;
446: } else {
447: x = centerRule;
448: }
449:
450: if (component != null) {
451: // --------------------------------------------------
452: // set the width for stretch based on BOTH, LEFT and
453: // RIGHT positionsing
454: // --------------------------------------------------
455: if ((constraints.stretch)
456: && (constraints.position == TwoColumnConstraints.BOTH)) {
457: width = rightRule - leftRule;
458: x = leftRule;
459: } else if ((constraints.stretch) && (column == LEFT)) {
460: width = centerRule - leftRule;
461: } else if ((constraints.stretch) && (column == RIGHT)) {
462: width = rightRule - centerRule;
463: }
464:
465: // --------------------------------------------------
466: // if we straddle both columns but are not stretching
467: // use the preferred width as long as it is less then
468: // the width of both columns combined. Also set the x
469: // position to left, just to be sure.
470: // --------------------------------------------------
471: else if (constraints.position == TwoColumnConstraints.BOTH) {
472: if (width > (rightRule - leftRule)) {
473: width = rightRule - leftRule;
474: }
475: x = leftRule;
476: }
477:
478: // --------------------------------------------------
479: // correct for indent if this option is set
480: // --------------------------------------------------
481: if (constraints.indent) {
482: width -= indent;
483: x += indent;
484: }
485:
486: component.setBounds(x, y, width, height);
487: }
488: }
489: }
490:
491: /**
492: * Returns the minimum width of the column requested.
493: *
494: * @param column the columns to measure (LEFT / RIGHT)
495: * @param parent the component which needs to be laid out.
496: *
497: * @return the minimum width required to fis the components in this column
498: */
499: private int minimumColumnWidth(int column, Container parent) {
500: Component component = null;
501: TwoColumnConstraints constraints = null;
502: int width = 0;
503: int temp = 0;
504:
505: for (int i = 0; i < components[column].size(); i++) {
506: constraints = (TwoColumnConstraints) components[column]
507: .elementAt(i);
508:
509: if ((constraints != null)
510: && (constraints.position != TwoColumnConstraints.BOTH)) {
511: component = constraints.component;
512: temp = (int) component.getMinimumSize().getWidth();
513:
514: if (constraints.indent) {
515: temp += indent;
516: }
517:
518: if (temp > width) {
519: width = temp;
520: }
521: }
522: }
523:
524: return (width);
525: }
526:
527: /**
528: * Retrunds the minimum width both columns together should have based on the minimum widths of
529: * all the components that straddle both columns and the minimum width of the title component.
530: *
531: * @param parent the component which needs to be laid out.
532: *
533: * @return the minimum width required to fis the components in this column
534: */
535: private int minimumBothColumnsWidth(Container parent) {
536: Component component = null;
537: TwoColumnConstraints constraints = null;
538: int width = 0;
539: int temp = 0;
540:
541: if (title != null) {
542: component = title.component;
543: width = (int) component.getMinimumSize().getWidth();
544: }
545:
546: for (int i = 0; i < components[LEFT].size(); i++) {
547: constraints = (TwoColumnConstraints) components[LEFT]
548: .elementAt(i);
549:
550: if ((constraints != null)
551: && (constraints.position == TwoColumnConstraints.BOTH)) {
552: component = constraints.component;
553: temp = (int) component.getMinimumSize().getWidth();
554:
555: if (constraints.indent) {
556: temp += indent;
557: }
558:
559: if (temp > width) {
560: width = temp;
561: }
562: }
563: }
564:
565: return (width);
566: }
567:
568: private int minimumClusterHeight() {
569: int height = 0;
570:
571: for (int i = 0; i < rows(); i++) {
572: height += rowHeight(i);
573: }
574:
575: return (height);
576: }
577:
578: /**
579: * Returns the number of rows that need to be laid out.
580: */
581: private int rows() {
582: int rows = 0;
583: int leftRows = components[LEFT].size();
584: int rightRows = components[RIGHT].size();
585:
586: if (leftRows > rightRows) {
587: rows = leftRows;
588: } else {
589: rows = rightRows;
590: }
591:
592: return (rows);
593: }
594:
595: /**
596: * Measures and returns the minimum height required to render the components in the indicated
597: * row.
598: *
599: * @param row the index of the row to measure
600: */
601: private int rowHeight(int row) {
602: int height = 0;
603: int height1 = height(row, LEFT);
604: int height2 = height(row, RIGHT);
605:
606: // ----------------------------------------------------
607: // take the higher one
608: // ----------------------------------------------------
609: if (height1 > height2) {
610: height = height1;
611: } else {
612: height = height2;
613: }
614:
615: return (height);
616: }
617:
618: /**
619: * Measures and returns the minimum height required to render the component in the indicated row
620: * and column.
621: *
622: * @param row the index of the row to measure
623: * @param column the column of the component to measure (<code>LEFT</code> or
624: * <code>RIGHT</code>)
625: */
626: private int height(int row, int column) {
627: int height = 0;
628: int width = 0;
629: Component component;
630: TwoColumnConstraints constraints;
631:
632: try {
633: constraints = (TwoColumnConstraints) components[column]
634: .elementAt(row);
635: if (constraints != null) {
636: component = constraints.component;
637: width = (int) component.getMinimumSize().getWidth();
638: height = (int) component.getMinimumSize().getHeight();
639:
640: if (constraints.position == TwoColumnConstraints.WEST) {
641: if (width > (centerRule - leftRule)) {
642: component.setBounds(0, 0,
643: (centerRule - leftRule), height);
644: }
645: } else if (constraints.position == TwoColumnConstraints.EAST) {
646: if (width > (rightRule - centerRule)) {
647: component.setBounds(0, 0,
648: (rightRule - centerRule), height);
649: }
650: } else if (constraints.position == TwoColumnConstraints.BOTH) {
651: if (width > (rightRule - leftRule)) {
652: component.setBounds(0, 0,
653: (rightRule - leftRule), height);
654: }
655: }
656:
657: height = (int) component.getMinimumSize().getHeight();
658: }
659: }
660: // ----------------------------------------------------
661: // we might get an exception if one of the vectors is
662: // shorter, because we index out of bounds. If there
663: // is nothing there then the height is 0, nothing
664: // further to worry about!
665: // ----------------------------------------------------
666: catch (Throwable exception) {
667: }
668:
669: return (height);
670: }
671:
672: /**
673: * Computes the margin value based on the container width and the margin setting.
674: *
675: * @param parent the component which needs to be laid out.
676: */
677: private int margin(Container parent) {
678: int amount = (int) (((parent.getSize().getWidth()) * margin) / 100);
679:
680: return (amount);
681: }
682:
683: /**
684: * Computes the top buffer value based on the container width and the setting for the top buffer
685: *
686: * @param usedHeight the amount of the parent component's height that is already in use (height
687: * of the title and the combined height of all rows).
688: * @param parent the component which needs to be laid out.
689: */
690: private int topBuffer(int usedHeight, Container parent) {
691: int amount = ((int) parent.getSize().getHeight()) - usedHeight;
692: amount = amount * topBuffer / 100;
693:
694: return (amount);
695: }
696:
697: /*--------------------------------------------------------------------------*/
698: /**
699: * Computes the indent value based on the container width and the indent setting.
700: *
701: * @param parent the component which needs to be laid out.
702: */
703: /*--------------------------------------------------------------------------*/
704: /*
705: * private int indent (Container parent) { int amount = (int)(((parent.getMinimumSize
706: * ().getWidth ()) * indent) / 100);
707: *
708: * return (amount); }
709: */
710: /**
711: * Calculates the preferred size dimensions for the specified panel given the components in the
712: * specified parent container.
713: *
714: * @param parent the component to be laid out
715: */
716: public Dimension preferredLayoutSize(Container parent) {
717: return (minimumLayoutSize(parent));
718: }
719:
720: /**
721: * Calculates the minimum size dimensions for the specified panel given the components in the
722: * specified parent container.
723: *
724: * @param parent the component to be laid out
725: */
726: public Dimension minimumLayoutSize(Container parent) {
727: positionTitle(parent);
728:
729: int width = minimumBothColumnsWidth(parent);
730: int height = minimumClusterHeight() + titleHeight;
731:
732: return (new Dimension(width, height));
733: }
734:
735: /**
736: * Calculates the maximum size dimensions for the specified panel given the components in the
737: * specified parent container.
738: *
739: * @param parent the component to be laid out
740: */
741: public Dimension maximumLayoutSize(Container parent) {
742: return (minimumLayoutSize(parent));
743: }
744:
745: /**
746: * Returns the alignment along the x axis. This specifies how the component would like to be
747: * aligned relative to other components. The value should be a number between 0 and 1 where 0
748: * represents alignment along the origin, 1 is aligned the furthest away from the origin, 0.5 is
749: * centered, etc.
750: *
751: * @param parent the component to be laid out
752: */
753: public float getLayoutAlignmentX(Container parent) {
754: return (0);
755: }
756:
757: /**
758: * Returns the alignment along the y axis. This specifies how the component would like to be
759: * aligned relative to other components. The value should be a number between 0 and 1 where 0
760: * represents alignment along the origin, 1 is aligned the furthest away from the origin, 0.5 is
761: * centered, etc.
762: *
763: * @param parent the component to be laid out
764: */
765: public float getLayoutAlignmentY(Container parent) {
766: return (0);
767: }
768:
769: /**
770: * Invalidates the layout, indicating that if the layout manager has cached information it
771: * should be discarded.
772: *
773: * @param parent the component to be laid out
774: */
775: public void invalidateLayout(Container parent) {
776: leftRule = 0;
777: rightRule = 0;
778: centerRule = 0;
779: titleHeight = 0;
780: }
781:
782: /**
783: * Adds the specified component with the specified name to the layout. This version is not
784: * supported, use <code>addLayoutComponent</code> with layout contsraints.
785: *
786: * @param name the component name
787: * @param comp the component to be added
788: */
789: public void addLayoutComponent(String name, Component comp) {
790: }
791:
792: /**
793: * This functionality removes the TwoColumnConstraints from Vectors
794: * so that alignment of components on UserInputPanel doesn't get
795: * dirty
796: *
797: * @param comp the component to be removed
798: */
799: public void removeLayoutComponent(Component comp) {
800: Vector left = components[LEFT];
801: Vector right = components[RIGHT];
802:
803: for (int i = 0; i < left.size(); i++) {
804: TwoColumnConstraints constraints = (TwoColumnConstraints) left
805: .get(i);
806: if (constraints == null) {
807: continue;
808: }
809: Component ctemp = constraints.component;
810: if (ctemp != null && ctemp.equals(comp)) {
811: if (constraints.position == TwoColumnConstraints.BOTH
812: || constraints.position == TwoColumnConstraints.WESTONLY) {
813: right.remove(i);
814: }
815: break;
816: }
817: }
818:
819: for (int j = 0; j < right.size(); j++) {
820: TwoColumnConstraints constraints = (TwoColumnConstraints) right
821: .get(j);
822: if (constraints == null) {
823: continue;
824: }
825: Component ctemp = constraints.component;
826: if (ctemp != null && ctemp.equals(comp)) {
827: if (constraints.position == TwoColumnConstraints.BOTH
828: || constraints.position == TwoColumnConstraints.EASTONLY) {
829: left.remove(j);
830: }
831: break;
832: }
833: }
834: }
835:
836: /**
837: * This method is provided for conveninence of debugging layout problems. It renders the three
838: * rules and the limit of the title marign visible after these positions have been computed. In
839: * addition, the indent locations are shown as dashed lines. To use this functionality do the
840: * following:<br>
841: * <br>
842: * <ul>
843: * <li>in the container using this layout manager override the <code>paint()</code> method.
844: * <li>in that method, first call <code>super.paint()</code>
845: * <li>then call this method
846: * </ul>
847: * <br>
848: * <b>Note:</b> cast the graphics object received in the <code>paint()</code> method to
849: * <code>Graphics2D</code> when making the call.<br>
850: * <br>
851: *
852: * @param graphics the graphics context used for drawing.
853: * @param color the color to use for rendering the layout grid
854: */
855: public void showRules(Graphics2D graphics, Color color) {
856: int height = graphics.getClipBounds().height;
857:
858: Stroke currentStroke = graphics.getStroke();
859: Color currentColor = graphics.getColor();
860:
861: Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
862: BasicStroke.JOIN_BEVEL, 1.5f, new float[] { 10, 5 }, 5);
863: graphics.setColor(color);
864:
865: graphics.drawLine(leftRule, 0, leftRule, height);
866: graphics.drawLine(centerRule, titleHeight, centerRule, height);
867: graphics.drawLine(rightRule, 0, rightRule, height);
868: graphics
869: .drawLine(leftRule, titleHeight, rightRule, titleHeight);
870:
871: graphics.setStroke(stroke);
872: graphics.drawLine((leftRule + indent), titleHeight,
873: (leftRule + indent), height);
874: graphics.drawLine((centerRule + indent), titleHeight,
875: (centerRule + indent), height);
876:
877: graphics.setStroke(currentStroke);
878: graphics.setColor(currentColor);
879: }
880: }
881: /*---------------------------------------------------------------------------*/
|