1 30 31 package com.jgoodies.forms.layout; 32 33 import java.awt.Component ; 34 import java.awt.Insets ; 35 import java.awt.Rectangle ; 36 import java.util.StringTokenizer ; 37 38 65 public final class CellConstraints implements Cloneable { 66 67 69 72 public static final Alignment DEFAULT = 73 new Alignment("default", Alignment.BOTH); 74 75 78 public static final Alignment FILL = 79 new Alignment("fill", Alignment.BOTH); 80 81 84 public static final Alignment LEFT = 85 new Alignment("left", Alignment.HORIZONTAL); 86 87 90 public static final Alignment RIGHT = 91 new Alignment("right", Alignment.HORIZONTAL); 92 95 public static final Alignment CENTER = 96 new Alignment("center", Alignment.BOTH); 97 98 101 public static final Alignment TOP = 102 new Alignment("top", Alignment.VERTICAL); 103 104 107 public static final Alignment BOTTOM = 108 new Alignment("bottom", Alignment.VERTICAL); 109 110 private static final Insets EMPTY_INSETS = 111 new Insets (0, 0, 0, 0); 112 113 115 118 public int gridX; 119 120 123 public int gridY; 124 125 128 public int gridWidth; 129 130 133 public int gridHeight; 134 135 138 public Alignment hAlign; 139 140 143 public Alignment vAlign; 144 145 148 public Insets insets; 149 150 151 153 156 public CellConstraints() { 157 this(1, 1); 158 } 159 160 167 public CellConstraints(int gridX, int gridY) { 168 this(gridX, gridY, 1, 1); 169 } 170 171 180 public CellConstraints(int gridX, int gridY, 181 Alignment hAlign, Alignment vAlign) { 182 this(gridX, gridY, 1, 1, hAlign, vAlign, EMPTY_INSETS); 183 } 184 185 194 public CellConstraints(int gridX, int gridY, int gridWidth, int gridHeight) { 195 this(gridX, gridY, gridWidth, gridHeight, DEFAULT, DEFAULT); 196 } 197 198 209 public CellConstraints(int gridX, int gridY, int gridWidth, int gridHeight, 210 Alignment hAlign, Alignment vAlign) { 211 this(gridX, gridY, gridWidth, gridHeight, hAlign, vAlign, EMPTY_INSETS); 212 } 213 214 229 public CellConstraints(int gridX, int gridY, int gridWidth, int gridHeight, 230 Alignment hAlign, Alignment vAlign, Insets insets) { 231 this.gridX = gridX; 232 this.gridY = gridY; 233 this.gridWidth = gridWidth; 234 this.gridHeight = gridHeight; 235 this.hAlign = hAlign; 236 this.vAlign = vAlign; 237 this.insets = insets; 238 if (gridX <= 0) 239 throw new IndexOutOfBoundsException ("The grid x must be a positive number."); 240 if (gridY <= 0) 241 throw new IndexOutOfBoundsException ("The grid y must be a positive number."); 242 if (gridWidth <= 0) 243 throw new IndexOutOfBoundsException ("The grid width must be a positive number."); 244 if (gridHeight <= 0) 245 throw new IndexOutOfBoundsException ("The grid height must be a positive number."); 246 if (hAlign == null) 247 throw new NullPointerException ("The horizontal alignment must not be null."); 248 if (vAlign == null) 249 throw new NullPointerException ("The vertical alignment must not be null."); 250 ensureValidOrientations(hAlign, vAlign); 251 } 252 253 259 public CellConstraints(String encodedConstraints) { 260 this(); 261 initFromConstraints(encodedConstraints); 262 } 263 264 265 267 275 public CellConstraints xy(int col, int row) { 276 return xywh(col, row, 1, 1); 277 } 278 279 288 public CellConstraints xy(int col, int row, String encodedAlignments) { 289 return xywh(col, row, 1, 1, encodedAlignments); 290 } 291 292 302 public CellConstraints xy(int col, int row, 303 Alignment colAlign, Alignment rowAlign) { 304 return xywh(col, row, 1, 1, colAlign, rowAlign); 305 } 306 307 308 318 public CellConstraints xywh(int col, int row, int colSpan, int rowSpan) { 319 return xywh(col, row, colSpan, rowSpan, DEFAULT, DEFAULT); 320 } 321 322 334 public CellConstraints xywh(int col, int row, int colSpan, int rowSpan, 335 String encodedAlignments) { 336 CellConstraints result = xywh(col, row, colSpan, rowSpan); 337 result.setAlignments(encodedAlignments); 338 return result; 339 } 340 341 354 public CellConstraints xywh(int col, int row, int colSpan, int rowSpan, 355 Alignment colAlign, Alignment rowAlign) { 356 this.gridX = col; 357 this.gridY = row; 358 this.gridWidth = colSpan; 359 this.gridHeight = rowSpan; 360 this.hAlign = colAlign; 361 this.vAlign = rowAlign; 362 ensureValidOrientations(hAlign, vAlign); 363 return this; 364 } 365 366 367 369 384 private void initFromConstraints(String encodedConstraints) { 385 StringTokenizer tokenizer = new StringTokenizer (encodedConstraints, " ,"); 386 int argCount = tokenizer.countTokens(); 387 if (!(argCount == 2 || argCount == 4 || argCount == 6)) 388 throw new IllegalArgumentException ( 389 "You must provide 2, 4 or 6 arguments."); 390 391 Integer nextInt = decodeInt(tokenizer.nextToken()); 392 if (nextInt == null) { 393 throw new IllegalArgumentException ( 394 "First cell constraint element must be a number."); 395 } 396 gridX = nextInt.intValue(); 397 if (gridX <= 0) 398 throw new IndexOutOfBoundsException ("The grid x must be a positive number."); 399 400 nextInt = decodeInt(tokenizer.nextToken()); 401 if (nextInt == null) { 402 throw new IllegalArgumentException ( 403 "Second cell constraint element must be a number."); 404 } 405 gridY = nextInt.intValue(); 406 if (gridY <= 0) 407 throw new IndexOutOfBoundsException ( 408 "The grid y must be a positive number."); 409 410 if (!tokenizer.hasMoreTokens()) 411 return; 412 413 String token = tokenizer.nextToken(); 414 nextInt = decodeInt(token); 415 if (nextInt != null) { 416 gridWidth = nextInt.intValue(); 419 if (gridWidth <= 0) 420 throw new IndexOutOfBoundsException ( 421 "The grid width must be a positive number."); 422 nextInt = decodeInt(tokenizer.nextToken()); 423 if (nextInt == null) 424 throw new IllegalArgumentException ( 425 "Fourth cell constraint element must be like third."); 426 gridHeight = nextInt.intValue(); 427 if (gridHeight <= 0) 428 throw new IndexOutOfBoundsException ( 429 "The grid height must be a positive number."); 430 431 if (!tokenizer.hasMoreTokens()) 432 return; 433 token = tokenizer.nextToken(); 434 } 435 436 hAlign = decodeAlignment(token); 437 vAlign = decodeAlignment(tokenizer.nextToken()); 438 ensureValidOrientations(hAlign, vAlign); 439 } 440 441 442 460 private void setAlignments(String encodedAlignments) { 461 StringTokenizer tokenizer = new StringTokenizer (encodedAlignments, " ,"); 462 hAlign = decodeAlignment(tokenizer.nextToken()); 463 vAlign = decodeAlignment(tokenizer.nextToken()); 464 ensureValidOrientations(hAlign, vAlign); 465 } 466 467 474 private Integer decodeInt(String token) { 475 try { 476 return Integer.decode(token); 477 } catch (NumberFormatException e) { 478 return null; 479 } 480 } 481 482 489 private Alignment decodeAlignment(String encodedAlignment) { 490 return Alignment.valueOf(encodedAlignment); 491 } 492 493 502 void ensureValidGridBounds(int colCount, int rowCount) { 503 if (gridX <= 0) { 504 throw new IndexOutOfBoundsException ( 505 "The column index " + gridX + " must be positive."); 506 } 507 if (gridX > colCount) { 508 throw new IndexOutOfBoundsException ( 509 "The column index " + gridX + " must be less than or equal to " 510 + colCount + "."); 511 } 512 if (gridX + gridWidth - 1 > colCount) { 513 throw new IndexOutOfBoundsException ( 514 "The grid width " + gridWidth + " must be less than or equal to " 515 + (colCount - gridX + 1) + "."); 516 } 517 if (gridY <= 0) { 518 throw new IndexOutOfBoundsException ( 519 "The row index " + gridY + " must be positive."); 520 } 521 if (gridY > rowCount) { 522 throw new IndexOutOfBoundsException ( 523 "The row index " + gridY + " must be less than or equal to " 524 + rowCount + "."); 525 } 526 if (gridY + gridHeight - 1 > rowCount) { 527 throw new IndexOutOfBoundsException ( 528 "The grid height " + gridHeight + " must be less than or equal to " 529 + (rowCount - gridY + 1) + "."); 530 } 531 } 532 533 534 542 private void ensureValidOrientations(Alignment horizontalAlignment, Alignment verticalAlignment) { 543 if (!horizontalAlignment.isHorizontal()) 544 throw new IllegalArgumentException ("The horizontal alignment must be one of: left, center, right, fill, default."); 545 if (!verticalAlignment.isVertical()) 546 throw new IllegalArgumentException ("The vertical alignment must be one of: top, center, botto, fill, default."); 547 } 548 549 550 552 564 void setBounds(Component c, FormLayout layout, 565 Rectangle cellBounds, 566 FormLayout.Measure minWidthMeasure, 567 FormLayout.Measure minHeightMeasure, 568 FormLayout.Measure prefWidthMeasure, 569 FormLayout.Measure prefHeightMeasure) { 570 ColumnSpec colSpec = gridWidth == 1 ? layout.getColumnSpec(gridX) : null; 571 RowSpec rowSpec = gridHeight == 1 ? layout.getRowSpec(gridY) : null; 572 Alignment concreteHAlign = concreteAlignment(this.hAlign, colSpec); 573 Alignment concreteVAlign = concreteAlignment(this.vAlign, rowSpec); 574 Insets concreteInsets = this.insets != null ? this.insets : EMPTY_INSETS; 575 int cellX = cellBounds.x + concreteInsets.left; 576 int cellY = cellBounds.y + concreteInsets.top; 577 int cellW = cellBounds.width - concreteInsets.left - concreteInsets.right; 578 int cellH = cellBounds.height - concreteInsets.top - concreteInsets.bottom; 579 int compW = componentSize(c, colSpec, cellW, minWidthMeasure, 580 prefWidthMeasure); 581 int compH = componentSize(c, rowSpec, cellH, minHeightMeasure, 582 prefHeightMeasure); 583 int x = origin(concreteHAlign, cellX, cellW, compW); 584 int y = origin(concreteVAlign, cellY, cellH, compH); 585 int w = extent(concreteHAlign, cellW, compW); 586 int h = extent(concreteVAlign, cellH, compH); 587 c.setBounds(x, y, w, h); 588 } 589 590 591 608 private Alignment concreteAlignment(Alignment cellAlignment, FormSpec formSpec) { 609 return formSpec == null 610 ? (cellAlignment == DEFAULT ? FILL : cellAlignment) 611 : usedAlignment(cellAlignment, formSpec); 612 } 613 614 624 private Alignment usedAlignment(Alignment cellAlignment, FormSpec formSpec) { 625 if (cellAlignment != CellConstraints.DEFAULT) { 626 return cellAlignment; 628 } 629 FormSpec.DefaultAlignment defaultAlignment = formSpec.getDefaultAlignment(); 630 if (defaultAlignment == FormSpec.FILL_ALIGN) 631 return FILL; 632 if (defaultAlignment == ColumnSpec.LEFT) 633 return LEFT; 634 else if (defaultAlignment == FormSpec.CENTER_ALIGN) 635 return CENTER; 636 else if (defaultAlignment == ColumnSpec.RIGHT) 637 return RIGHT; 638 else if (defaultAlignment == RowSpec.TOP) 639 return TOP; 640 else 641 return BOTTOM; 642 } 643 644 655 private int componentSize(Component component, 656 FormSpec formSpec, 657 int cellSize, 658 FormLayout.Measure minMeasure, 659 FormLayout.Measure prefMeasure) { 660 if (formSpec == null) { 661 return prefMeasure.sizeOf(component); 662 } else if (formSpec.getSize() == Sizes.MINIMUM) { 663 return minMeasure.sizeOf(component); 664 } else if (formSpec.getSize() == Sizes.PREFERRED) { 665 return prefMeasure.sizeOf(component); 666 } else { return Math.min(cellSize, prefMeasure.sizeOf(component)); 668 } 669 } 670 671 680 private int origin(Alignment alignment, 681 int cellOrigin, 682 int cellSize, 683 int componentSize) { 684 if (alignment == RIGHT || alignment == BOTTOM) { 685 return cellOrigin + cellSize - componentSize; 686 } else if (alignment == CENTER) { 687 return cellOrigin + (cellSize - componentSize) / 2; 688 } else { return cellOrigin; 690 } 691 } 692 693 701 private int extent(Alignment alignment, int cellSize, int componentSize) { 702 return alignment == FILL 703 ? cellSize 704 : componentSize; 705 } 706 707 708 709 711 716 public Object clone() { 717 try { 718 CellConstraints c = (CellConstraints) super.clone(); 719 c.insets = (Insets ) insets.clone(); 720 return c; 721 } catch (CloneNotSupportedException e) { 722 throw new InternalError (); 724 } 725 } 726 727 728 733 public String toString() { 734 StringBuffer buffer = new StringBuffer ("CellConstraints"); 735 buffer.append("[x="); 736 buffer.append(gridX); 737 buffer.append("; y="); 738 buffer.append(gridY); 739 buffer.append("; w="); 740 buffer.append(gridWidth); 741 buffer.append("; h="); 742 buffer.append(gridHeight); 743 buffer.append("; hAlign="); 744 buffer.append(hAlign); 745 buffer.append("; vAlign="); 746 buffer.append(vAlign); 747 if (!(EMPTY_INSETS.equals(insets))) { 748 buffer.append("; insets="); 749 buffer.append(insets); 750 } 751 752 buffer.append(']'); 753 return buffer.toString(); 754 } 755 756 761 public String toShortString() { 762 return toShortString(null); 763 } 764 765 766 775 public String toShortString(FormLayout layout) { 776 StringBuffer buffer = new StringBuffer ("("); 777 buffer.append(formatInt(gridX)); 778 buffer.append(", "); 779 buffer.append(formatInt(gridY)); 780 buffer.append(", "); 781 buffer.append(formatInt(gridWidth)); 782 buffer.append(", "); 783 buffer.append(formatInt(gridHeight)); 784 buffer.append(", \""); 785 buffer.append(hAlign.abbreviation()); 786 if (hAlign == DEFAULT && layout != null) { 787 buffer.append('='); 788 ColumnSpec colSpec = gridWidth == 1 789 ? layout.getColumnSpec(gridX) 790 : null; 791 buffer.append(concreteAlignment(hAlign, colSpec).abbreviation()); 792 } 793 buffer.append(", "); 794 buffer.append(vAlign.abbreviation()); 795 if (vAlign == DEFAULT && layout != null) { 796 buffer.append('='); 797 RowSpec rowSpec = gridHeight == 1 798 ? layout.getRowSpec(gridY) 799 : null; 800 buffer.append(concreteAlignment(vAlign, rowSpec).abbreviation()); 801 } 802 buffer.append("\""); 803 if (!(EMPTY_INSETS.equals(insets))) { 804 buffer.append(", "); 805 buffer.append(insets); 806 } 807 808 buffer.append(')'); 809 return buffer.toString(); 810 } 811 812 813 814 816 820 public static final class Alignment { 821 822 private static final int HORIZONTAL = 0; 823 private static final int VERTICAL = 1; 824 private static final int BOTH = 2; 825 826 private final String name; 827 private final int orientation; 828 829 private Alignment(String name, int orientation) { 830 this.name = name; 831 this.orientation = orientation; 832 } 833 834 static Alignment valueOf(String nameOrAbbreviation) { 835 String str = nameOrAbbreviation.toLowerCase(); 836 if (str.equals("d") || str.equals("default")) 837 return DEFAULT; 838 else if (str.equals("f") || str.equals("fill")) 839 return FILL; 840 else if (str.equals("c") || str.equals("center")) 841 return CENTER; 842 else if (str.equals("l") || str.equals("left")) 843 return LEFT; 844 else if (str.equals("r") || str.equals("right")) 845 return RIGHT; 846 else if (str.equals("t") || str.equals("top")) 847 return TOP; 848 else if (str.equals("b") || str.equals("bottom")) 849 return BOTTOM; 850 else 851 throw new IllegalArgumentException ( 852 "Invalid alignment " + nameOrAbbreviation 853 + ". Must be one of: left, center, right, top, bottom, " 854 + "fill, default, l, c, r, t, b, f, d."); 855 } 856 857 public String toString() { 858 return name; 859 } 860 861 public char abbreviation() { 862 return name.charAt(0); 863 } 864 865 private boolean isHorizontal() { 866 return orientation != VERTICAL; 867 } 868 869 private boolean isVertical() { 870 return orientation != HORIZONTAL; 871 } 872 873 } 874 875 876 881 private String formatInt(int number) { 882 String str = Integer.toString(number); 883 return number < 10 ? " " + str : str; 884 } 885 } 886 887 | Popular Tags |