1 7 package javax.swing.text; 8 9 import java.io.PrintStream ; 10 import java.util.Vector ; 11 import java.awt.*; 12 import javax.swing.event.DocumentEvent ; 13 import javax.swing.SizeRequirements ; 14 15 44 public class BoxView extends CompositeView { 45 46 52 public BoxView(Element elem, int axis) { 53 super(elem); 54 tempRect = new Rectangle(); 55 this.majorAxis = axis; 56 57 majorOffsets = new int[0]; 58 majorSpans = new int[0]; 59 majorReqValid = false; 60 majorAllocValid = false; 61 minorOffsets = new int[0]; 62 minorSpans = new int[0]; 63 minorReqValid = false; 64 minorAllocValid = false; 65 } 66 67 76 public int getAxis() { 77 return majorAxis; 78 } 79 80 88 public void setAxis(int axis) { 89 boolean axisChanged = (axis != majorAxis); 90 majorAxis = axis; 91 if (axisChanged) { 92 preferenceChanged(null, true, true); 93 } 94 } 95 96 110 public void layoutChanged(int axis) { 111 if (axis == majorAxis) { 112 majorAllocValid = false; 113 } else { 114 minorAllocValid = false; 115 } 116 } 117 118 125 protected boolean isLayoutValid(int axis) { 126 if (axis == majorAxis) { 127 return majorAllocValid; 128 } else { 129 return minorAllocValid; 130 } 131 } 132 133 142 protected void paintChild(Graphics g, Rectangle alloc, int index) { 143 View child = getView(index); 144 child.paint(g, alloc); 145 } 146 147 149 163 public void replace(int index, int length, View [] elems) { 164 super.replace(index, length, elems); 165 166 int nInserted = (elems != null) ? elems.length : 0; 168 majorOffsets = updateLayoutArray(majorOffsets, index, nInserted); 169 majorSpans = updateLayoutArray(majorSpans, index, nInserted); 170 majorReqValid = false; 171 majorAllocValid = false; 172 minorOffsets = updateLayoutArray(minorOffsets, index, nInserted); 173 minorSpans = updateLayoutArray(minorSpans, index, nInserted); 174 minorReqValid = false; 175 minorAllocValid = false; 176 } 177 178 192 int[] updateLayoutArray(int[] oldArray, int offset, int nInserted) { 193 int n = getViewCount(); 194 int[] newArray = new int[n]; 195 196 System.arraycopy(oldArray, 0, newArray, 0, offset); 197 System.arraycopy(oldArray, offset, 198 newArray, offset + nInserted, n - nInserted - offset); 199 return newArray; 200 } 201 202 219 protected void forwardUpdate(DocumentEvent.ElementChange ec, 220 DocumentEvent e, Shape a, ViewFactory f) { 221 boolean wasValid = isLayoutValid(majorAxis); 222 super.forwardUpdate(ec, e, a, f); 223 224 if (wasValid && (! isLayoutValid(majorAxis))) { 226 Component c = getContainer(); 230 if ((a != null) && (c != null)) { 231 int pos = e.getOffset(); 232 int index = getViewIndexAtPosition(pos); 233 Rectangle alloc = getInsideAllocation(a); 234 if (majorAxis == X_AXIS) { 235 alloc.x += majorOffsets[index]; 236 alloc.width -= majorOffsets[index]; 237 } else { 238 alloc.y += minorOffsets[index]; 239 alloc.height -= minorOffsets[index]; 240 } 241 c.repaint(alloc.x, alloc.y, alloc.width, alloc.height); 242 } 243 } 244 } 245 246 257 public void preferenceChanged(View child, boolean width, boolean height) { 258 boolean majorChanged = (majorAxis == X_AXIS) ? width : height; 259 boolean minorChanged = (majorAxis == X_AXIS) ? height : width; 260 if (majorChanged) { 261 majorReqValid = false; 262 majorAllocValid = false; 263 } 264 if (minorChanged) { 265 minorReqValid = false; 266 minorAllocValid = false; 267 } 268 super.preferenceChanged(child, width, height); 269 } 270 271 279 public int getResizeWeight(int axis) { 280 checkRequests(axis); 281 if (axis == majorAxis) { 282 if ((majorRequest.preferred != majorRequest.minimum) || 283 (majorRequest.preferred != majorRequest.maximum)) { 284 return 1; 285 } 286 } else { 287 if ((minorRequest.preferred != minorRequest.minimum) || 288 (minorRequest.preferred != minorRequest.maximum)) { 289 return 1; 290 } 291 } 292 return 0; 293 } 294 295 303 void setSpanOnAxis(int axis, float span) { 304 if (axis == majorAxis) { 305 if (majorSpan != (int) span) { 306 majorAllocValid = false; 307 } 308 if (! majorAllocValid) { 309 majorSpan = (int) span; 311 checkRequests(majorAxis); 312 layoutMajorAxis(majorSpan, axis, majorOffsets, majorSpans); 313 majorAllocValid = true; 314 315 updateChildSizes(); 317 } 318 } else { 319 if (((int) span) != minorSpan) { 320 minorAllocValid = false; 321 } 322 if (! minorAllocValid) { 323 minorSpan = (int) span; 325 checkRequests(axis); 326 layoutMinorAxis(minorSpan, axis, minorOffsets, minorSpans); 327 minorAllocValid = true; 328 329 updateChildSizes(); 331 } 332 } 333 } 334 335 338 void updateChildSizes() { 339 int n = getViewCount(); 340 if (majorAxis == X_AXIS) { 341 for (int i = 0; i < n; i++) { 342 View v = getView(i); 343 v.setSize((float) majorSpans[i], (float) minorSpans[i]); 344 } 345 } else { 346 for (int i = 0; i < n; i++) { 347 View v = getView(i); 348 v.setSize((float) minorSpans[i], (float) majorSpans[i]); 349 } 350 } 351 } 352 353 361 float getSpanOnAxis(int axis) { 362 if (axis == majorAxis) { 363 return majorSpan; 364 } else { 365 return minorSpan; 366 } 367 } 368 369 378 public void setSize(float width, float height) { 379 layout((int)(width - getLeftInset() - getRightInset()), 380 (int)(height - getTopInset() - getBottomInset())); 381 } 382 383 394 public void paint(Graphics g, Shape allocation) { 395 Rectangle alloc = (allocation instanceof Rectangle) ? 396 (Rectangle)allocation : allocation.getBounds(); 397 int n = getViewCount(); 398 int x = alloc.x + getLeftInset(); 399 int y = alloc.y + getTopInset(); 400 Rectangle clip = g.getClipBounds(); 401 for (int i = 0; i < n; i++) { 402 tempRect.x = x + getOffset(X_AXIS, i); 403 tempRect.y = y + getOffset(Y_AXIS, i); 404 tempRect.width = getSpan(X_AXIS, i); 405 tempRect.height = getSpan(Y_AXIS, i); 406 if (tempRect.intersects(clip)) { 407 paintChild(g, tempRect, i); 408 } 409 } 410 } 411 412 425 public Shape getChildAllocation(int index, Shape a) { 426 if (a != null) { 427 Shape ca = super.getChildAllocation(index, a); 428 if ((ca != null) && (! isAllocationValid())) { 429 Rectangle r = (ca instanceof Rectangle) ? 431 (Rectangle) ca : ca.getBounds(); 432 if ((r.width == 0) && (r.height == 0)) { 433 return null; 434 } 435 } 436 return ca; 437 } 438 return null; 439 } 440 441 453 public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException { 454 if (! isAllocationValid()) { 455 Rectangle alloc = a.getBounds(); 456 setSize(alloc.width, alloc.height); 457 } 458 return super.modelToView(pos, a, b); 459 } 460 461 472 public int viewToModel(float x, float y, Shape a, Position.Bias [] bias) { 473 if (! isAllocationValid()) { 474 Rectangle alloc = a.getBounds(); 475 setSize(alloc.width, alloc.height); 476 } 477 return super.viewToModel(x, y, a, bias); 478 } 479 480 497 public float getAlignment(int axis) { 498 checkRequests(axis); 499 if (axis == majorAxis) { 500 return majorRequest.alignment; 501 } else { 502 return minorRequest.alignment; 503 } 504 } 505 506 518 public float getPreferredSpan(int axis) { 519 checkRequests(axis); 520 float marginSpan = (axis == X_AXIS) ? getLeftInset() + getRightInset() : 521 getTopInset() + getBottomInset(); 522 if (axis == majorAxis) { 523 return ((float)majorRequest.preferred) + marginSpan; 524 } else { 525 return ((float)minorRequest.preferred) + marginSpan; 526 } 527 } 528 529 541 public float getMinimumSpan(int axis) { 542 checkRequests(axis); 543 float marginSpan = (axis == X_AXIS) ? getLeftInset() + getRightInset() : 544 getTopInset() + getBottomInset(); 545 if (axis == majorAxis) { 546 return ((float)majorRequest.minimum) + marginSpan; 547 } else { 548 return ((float)minorRequest.minimum) + marginSpan; 549 } 550 } 551 552 564 public float getMaximumSpan(int axis) { 565 checkRequests(axis); 566 float marginSpan = (axis == X_AXIS) ? getLeftInset() + getRightInset() : 567 getTopInset() + getBottomInset(); 568 if (axis == majorAxis) { 569 return ((float)majorRequest.maximum) + marginSpan; 570 } else { 571 return ((float)minorRequest.maximum) + marginSpan; 572 } 573 } 574 575 577 583 protected boolean isAllocationValid() { 584 return (majorAllocValid && minorAllocValid); 585 } 586 587 596 protected boolean isBefore(int x, int y, Rectangle innerAlloc) { 597 if (majorAxis == View.X_AXIS) { 598 return (x < innerAlloc.x); 599 } else { 600 return (y < innerAlloc.y); 601 } 602 } 603 604 613 protected boolean isAfter(int x, int y, Rectangle innerAlloc) { 614 if (majorAxis == View.X_AXIS) { 615 return (x > (innerAlloc.width + innerAlloc.x)); 616 } else { 617 return (y > (innerAlloc.height + innerAlloc.y)); 618 } 619 } 620 621 630 protected View getViewAtPoint(int x, int y, Rectangle alloc) { 631 int n = getViewCount(); 632 if (majorAxis == View.X_AXIS) { 633 if (x < (alloc.x + majorOffsets[0])) { 634 childAllocation(0, alloc); 635 return getView(0); 636 } 637 for (int i = 0; i < n; i++) { 638 if (x < (alloc.x + majorOffsets[i])) { 639 childAllocation(i - 1, alloc); 640 return getView(i - 1); 641 } 642 } 643 childAllocation(n - 1, alloc); 644 return getView(n - 1); 645 } else { 646 if (y < (alloc.y + majorOffsets[0])) { 647 childAllocation(0, alloc); 648 return getView(0); 649 } 650 for (int i = 0; i < n; i++) { 651 if (y < (alloc.y + majorOffsets[i])) { 652 childAllocation(i - 1, alloc); 653 return getView(i - 1); 654 } 655 } 656 childAllocation(n - 1, alloc); 657 return getView(n - 1); 658 } 659 } 660 661 668 protected void childAllocation(int index, Rectangle alloc) { 669 alloc.x += getOffset(X_AXIS, index); 670 alloc.y += getOffset(Y_AXIS, index); 671 alloc.width = getSpan(X_AXIS, index); 672 alloc.height = getSpan(Y_AXIS, index); 673 } 674 675 681 protected void layout(int width, int height) { 682 setSpanOnAxis(X_AXIS, width); 683 setSpanOnAxis(Y_AXIS, height); 684 } 685 686 691 public int getWidth() { 692 int span; 693 if (majorAxis == X_AXIS) { 694 span = majorSpan; 695 } else { 696 span = minorSpan; 697 } 698 span += getLeftInset() - getRightInset(); 699 return span; 700 } 701 702 707 public int getHeight() { 708 int span; 709 if (majorAxis == Y_AXIS) { 710 span = majorSpan; 711 } else { 712 span = minorSpan; 713 } 714 span += getTopInset() - getBottomInset(); 715 return span; 716 } 717 718 735 protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans) { 736 740 long preferred = 0; 741 int n = getViewCount(); 742 for (int i = 0; i < n; i++) { 743 View v = getView(i); 744 spans[i] = (int) v.getPreferredSpan(axis); 745 preferred += spans[i]; 746 } 747 748 752 753 long desiredAdjustment = targetSpan - preferred; 755 float adjustmentFactor = 0.0f; 756 int[] diffs = null; 757 758 if (desiredAdjustment != 0) { 759 long totalSpan = 0; 760 diffs = new int[n]; 761 for (int i = 0; i < n; i++) { 762 View v = getView(i); 763 int tmp; 764 if (desiredAdjustment < 0) { 765 tmp = (int)v.getMinimumSpan(axis); 766 diffs[i] = spans[i] - tmp; 767 } else { 768 tmp = (int)v.getMaximumSpan(axis); 769 diffs[i] = tmp - spans[i]; 770 } 771 totalSpan += tmp; 772 } 773 774 float maximumAdjustment = Math.abs(totalSpan - preferred); 775 adjustmentFactor = desiredAdjustment / maximumAdjustment; 776 adjustmentFactor = Math.min(adjustmentFactor, 1.0f); 777 adjustmentFactor = Math.max(adjustmentFactor, -1.0f); 778 } 779 780 int totalOffset = 0; 782 for (int i = 0; i < n; i++) { 783 offsets[i] = totalOffset; 784 if (desiredAdjustment != 0) { 785 float adjF = adjustmentFactor * diffs[i]; 786 spans[i] += Math.round(adjF); 787 } 788 totalOffset = (int) Math.min((long) totalOffset + (long) spans[i], Integer.MAX_VALUE); 789 } 790 } 791 792 809 protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets, int[] spans) { 810 int n = getViewCount(); 811 for (int i = 0; i < n; i++) { 812 View v = getView(i); 813 int max = (int) v.getMaximumSpan(axis); 814 if (max < targetSpan) { 815 float align = v.getAlignment(axis); 817 offsets[i] = (int) ((targetSpan - max) * align); 818 spans[i] = max; 819 } else { 820 int min = (int)v.getMinimumSpan(axis); 822 offsets[i] = 0; 823 spans[i] = Math.max(min, targetSpan); 824 } 825 } 826 } 827 828 838 protected SizeRequirements calculateMajorAxisRequirements(int axis, SizeRequirements r) { 839 float min = 0; 841 float pref = 0; 842 float max = 0; 843 844 int n = getViewCount(); 845 for (int i = 0; i < n; i++) { 846 View v = getView(i); 847 min += v.getMinimumSpan(axis); 848 pref += v.getPreferredSpan(axis); 849 max += v.getMaximumSpan(axis); 850 } 851 852 if (r == null) { 853 r = new SizeRequirements (); 854 } 855 r.alignment = 0.5f; 856 r.minimum = (int) min; 857 r.preferred = (int) pref; 858 r.maximum = (int) max; 859 return r; 860 } 861 862 872 protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) { 873 int min = 0; 874 long pref = 0; 875 int max = Integer.MAX_VALUE; 876 int n = getViewCount(); 877 for (int i = 0; i < n; i++) { 878 View v = getView(i); 879 min = Math.max((int) v.getMinimumSpan(axis), min); 880 pref = Math.max((int) v.getPreferredSpan(axis), pref); 881 max = Math.max((int) v.getMaximumSpan(axis), max); 882 } 883 884 if (r == null) { 885 r = new SizeRequirements (); 886 r.alignment = 0.5f; 887 } 888 r.preferred = (int) pref; 889 r.minimum = min; 890 r.maximum = max; 891 return r; 892 } 893 894 900 void checkRequests(int axis) { 901 if ((axis != X_AXIS) && (axis != Y_AXIS)) { 902 throw new IllegalArgumentException ("Invalid axis: " + axis); 903 } 904 if (axis == majorAxis) { 905 if (!majorReqValid) { 906 majorRequest = calculateMajorAxisRequirements(axis, 907 majorRequest); 908 majorReqValid = true; 909 } 910 } else if (! minorReqValid) { 911 minorRequest = calculateMinorAxisRequirements(axis, minorRequest); 912 minorReqValid = true; 913 } 914 } 915 916 931 protected void baselineLayout(int targetSpan, int axis, int[] offsets, int[] spans) { 932 int totalAscent = (int)(targetSpan * getAlignment(axis)); 933 int totalDescent = targetSpan - totalAscent; 934 935 int n = getViewCount(); 936 937 for (int i = 0; i < n; i++) { 938 View v = getView(i); 939 float align = v.getAlignment(axis); 940 int viewSpan; 941 942 if (v.getResizeWeight(axis) > 0) { 943 945 int minSpan = (int)v.getMinimumSpan(axis); 947 int maxSpan = (int)v.getMaximumSpan(axis); 949 950 if (align == 0.0f) { 951 viewSpan = Math.max(Math.min(maxSpan, totalDescent), minSpan); 953 } else if (align == 1.0f) { 954 viewSpan = Math.max(Math.min(maxSpan, totalAscent), minSpan); 956 } else { 957 int fitSpan = (int)Math.min(totalAscent / align, 959 totalDescent / (1.0f - align)); 960 viewSpan = Math.max(Math.min(maxSpan, fitSpan), minSpan); 962 } 963 } else { 964 viewSpan = (int)v.getPreferredSpan(axis); 966 } 967 968 offsets[i] = totalAscent - (int)(viewSpan * align); 969 spans[i] = viewSpan; 970 } 971 } 972 973 982 protected SizeRequirements baselineRequirements(int axis, SizeRequirements r) { 983 SizeRequirements totalAscent = new SizeRequirements (); 984 SizeRequirements totalDescent = new SizeRequirements (); 985 986 if (r == null) { 987 r = new SizeRequirements (); 988 } 989 990 r.alignment = 0.5f; 991 992 int n = getViewCount(); 993 994 for (int i = 0; i < n; i++) { 997 View v = getView(i); 998 float align = v.getAlignment(axis); 999 int span; 1000 int ascent; 1001 int descent; 1002 1003 span = (int)v.getPreferredSpan(axis); 1005 ascent = (int)(align * span); 1006 descent = span - ascent; 1007 totalAscent.preferred = Math.max(ascent, totalAscent.preferred); 1008 totalDescent.preferred = Math.max(descent, totalDescent.preferred); 1009 1010 if (v.getResizeWeight(axis) > 0) { 1011 span = (int)v.getMinimumSpan(axis); 1014 ascent = (int)(align * span); 1015 descent = span - ascent; 1016 totalAscent.minimum = Math.max(ascent, totalAscent.minimum); 1017 totalDescent.minimum = Math.max(descent, totalDescent.minimum); 1018 1019 span = (int)v.getMaximumSpan(axis); 1020 ascent = (int)(align * span); 1021 descent = span - ascent; 1022 totalAscent.maximum = Math.max(ascent, totalAscent.maximum); 1023 totalDescent.maximum = Math.max(descent, totalDescent.maximum); 1024 } else { 1025 totalAscent.minimum = Math.max(ascent, totalAscent.minimum); 1027 totalDescent.minimum = Math.max(descent, totalDescent.minimum); 1028 totalAscent.maximum = Math.max(ascent, totalAscent.maximum); 1029 totalDescent.maximum = Math.max(descent, totalDescent.maximum); 1030 } 1031 } 1032 1033 1035 r.preferred = (int)Math.min((long)totalAscent.preferred + (long)totalDescent.preferred, 1037 Integer.MAX_VALUE); 1038 1039 if (r.preferred > 0) { 1041 r.alignment = (float)totalAscent.preferred / r.preferred; 1042 } 1043 1044 1045 if (r.alignment == 0.0f) { 1046 r.minimum = totalDescent.minimum; 1049 r.maximum = totalDescent.maximum; 1050 } else if (r.alignment == 1.0f) { 1051 r.minimum = totalAscent.minimum; 1054 r.maximum = totalAscent.maximum; 1055 } else { 1056 r.minimum = Math.max((int)(totalAscent.minimum / r.alignment), 1060 (int)(totalDescent.minimum / (1.0f - r.alignment))); 1061 r.maximum = Math.min((int)(totalAscent.maximum / r.alignment), 1063 (int)(totalDescent.maximum / (1.0f - r.alignment))); 1064 } 1065 1066 return r; 1067 } 1068 1069 1075 protected int getOffset(int axis, int childIndex) { 1076 int[] offsets = (axis == majorAxis) ? majorOffsets : minorOffsets; 1077 return offsets[childIndex]; 1078 } 1079 1080 1086 protected int getSpan(int axis, int childIndex) { 1087 int[] spans = (axis == majorAxis) ? majorSpans : minorSpans; 1088 return spans[childIndex]; 1089 } 1090 1091 1120 protected boolean flipEastAndWestAtEnds(int position, 1121 Position.Bias bias) { 1122 if(majorAxis == Y_AXIS) { 1123 int testPos = (bias == Position.Bias.Backward) ? 1124 Math.max(0, position - 1) : position; 1125 int index = getViewIndexAtPosition(testPos); 1126 if(index != -1) { 1127 View v = getView(index); 1128 if(v != null && v instanceof CompositeView ) { 1129 return ((CompositeView )v).flipEastAndWestAtEnds(position, 1130 bias); 1131 } 1132 } 1133 } 1134 return false; 1135 } 1136 1137 1139 int majorAxis; 1140 1141 int majorSpan; 1142 int minorSpan; 1143 1144 1147 boolean majorReqValid; 1148 boolean minorReqValid; 1149 SizeRequirements majorRequest; 1150 SizeRequirements minorRequest; 1151 1152 1155 boolean majorAllocValid; 1156 int[] majorOffsets; 1157 int[] majorSpans; 1158 boolean minorAllocValid; 1159 int[] minorOffsets; 1160 int[] minorSpans; 1161 1162 1163 Rectangle tempRect; 1164} 1165 | Popular Tags |