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