1 7 package javax.swing.text; 8 9 import java.lang.reflect.Method ; 10 11 import java.awt.Component ; 12 import java.awt.Rectangle ; 13 import java.awt.Graphics ; 14 import java.awt.FontMetrics ; 15 import java.awt.Shape ; 16 import java.awt.Toolkit ; 17 import java.awt.Graphics2D ; 18 import java.awt.font.FontRenderContext ; 19 import java.awt.font.TextLayout ; 20 import java.awt.font.TextAttribute ; 21 22 import java.text.*; 23 import javax.swing.JComponent ; 24 import javax.swing.SwingConstants ; 25 import javax.swing.text.ParagraphView.Row ; 26 import com.sun.java.swing.SwingUtilities2; 27 28 35 public class Utilities { 36 40 static JComponent getJComponent(View view) { 41 if (view != null) { 42 Component component = view.getContainer(); 43 if (component instanceof JComponent ) { 44 return (JComponent )component; 45 } 46 } 47 return null; 48 } 49 50 65 public static final int drawTabbedText(Segment s, int x, int y, Graphics g, 66 TabExpander e, int startOffset) { 67 return drawTabbedText(null, s, x, y, g, e, startOffset); 68 } 69 70 86 static final int drawTabbedText(View view, 87 Segment s, int x, int y, Graphics g, 88 TabExpander e, int startOffset) { 89 return drawTabbedText(view, s, x, y, g, e, startOffset, null); 90 } 91 92 static final int drawTabbedText(View view, 100 Segment s, int x, int y, Graphics g, 101 TabExpander e, int startOffset, 102 int [] justificationData) { 103 JComponent component = getJComponent(view); 104 FontMetrics metrics = SwingUtilities2.getFontMetrics(component, g); 105 int nextX = x; 106 char[] txt = s.array; 107 int txtOffset = s.offset; 108 int flushLen = 0; 109 int flushIndex = s.offset; 110 int spaceAddon = 0; 111 int spaceAddonLeftoverEnd = -1; 112 int startJustifiableContent = 0; 113 int endJustifiableContent = 0; 114 if (justificationData != null) { 115 int offset = - startOffset + txtOffset; 116 View parent = null; 117 if (view != null 118 && (parent = view.getParent()) != null) { 119 offset += parent.getStartOffset(); 120 } 121 spaceAddon = 122 justificationData[Row.SPACE_ADDON]; 123 spaceAddonLeftoverEnd = 124 justificationData[Row.SPACE_ADDON_LEFTOVER_END] + offset; 125 startJustifiableContent = 126 justificationData[Row.START_JUSTIFIABLE] + offset; 127 endJustifiableContent = 128 justificationData[Row.END_JUSTIFIABLE] + offset; 129 } 130 int n = s.offset + s.count; 131 for (int i = txtOffset; i < n; i++) { 132 if (txt[i] == '\t' 133 || ((spaceAddon != 0 || i <= spaceAddonLeftoverEnd) 134 && (txt[i] == ' ') 135 && startJustifiableContent <= i 136 && i <= endJustifiableContent 137 )) { 138 if (flushLen > 0) { 139 nextX = SwingUtilities2.drawChars(component, g, txt, 140 flushIndex, flushLen, x, y); 141 flushLen = 0; 142 } 143 flushIndex = i + 1; 144 if (txt[i] == '\t') { 145 if (e != null) { 146 nextX = (int) e.nextTabStop((float) nextX, startOffset + i - txtOffset); 147 } else { 148 nextX += metrics.charWidth(' '); 149 } 150 } else if (txt[i] == ' ') { 151 nextX += metrics.charWidth(' ') + spaceAddon; 152 if (i <= spaceAddonLeftoverEnd) { 153 nextX++; 154 } 155 } 156 x = nextX; 157 } else if ((txt[i] == '\n') || (txt[i] == '\r')) { 158 if (flushLen > 0) { 159 nextX = SwingUtilities2.drawChars(component, g, txt, 160 flushIndex, flushLen, x, y); 161 flushLen = 0; 162 } 163 flushIndex = i + 1; 164 x = nextX; 165 } else { 166 flushLen += 1; 167 } 168 } 169 if (flushLen > 0) { 170 nextX = SwingUtilities2.drawChars(component, g,txt, flushIndex, 171 flushLen, x, y); 172 } 173 return nextX; 174 } 175 176 189 public static final int getTabbedTextWidth(Segment s, FontMetrics metrics, int x, 190 TabExpander e, int startOffset) { 191 return getTabbedTextWidth(null, s, metrics, x, e, startOffset, null); 192 } 193 194 195 static final int getTabbedTextWidth(View view, Segment s, FontMetrics metrics, int x, 203 TabExpander e, int startOffset, 204 int[] justificationData) { 205 int nextX = x; 206 char[] txt = s.array; 207 int txtOffset = s.offset; 208 int n = s.offset + s.count; 209 int charCount = 0; 210 int spaceAddon = 0; 211 int spaceAddonLeftoverEnd = -1; 212 int startJustifiableContent = 0; 213 int endJustifiableContent = 0; 214 if (justificationData != null) { 215 int offset = - startOffset + txtOffset; 216 View parent = null; 217 if (view != null 218 && (parent = view.getParent()) != null) { 219 offset += parent.getStartOffset(); 220 } 221 spaceAddon = 222 justificationData[Row.SPACE_ADDON]; 223 spaceAddonLeftoverEnd = 224 justificationData[Row.SPACE_ADDON_LEFTOVER_END] + offset; 225 startJustifiableContent = 226 justificationData[Row.START_JUSTIFIABLE] + offset; 227 endJustifiableContent = 228 justificationData[Row.END_JUSTIFIABLE] + offset; 229 } 230 231 for (int i = txtOffset; i < n; i++) { 232 if (txt[i] == '\t' 233 || ((spaceAddon != 0 || i <= spaceAddonLeftoverEnd) 234 && (txt[i] == ' ') 235 && startJustifiableContent <= i 236 && i <= endJustifiableContent 237 )) { 238 nextX += metrics.charsWidth(txt, i-charCount, charCount); 239 charCount = 0; 240 if (txt[i] == '\t') { 241 if (e != null) { 242 nextX = (int) e.nextTabStop((float) nextX, 243 startOffset + i - txtOffset); 244 } else { 245 nextX += metrics.charWidth(' '); 246 } 247 } else if (txt[i] == ' ') { 248 nextX += metrics.charWidth(' ') + spaceAddon; 249 if (i <= spaceAddonLeftoverEnd) { 250 nextX++; 251 } 252 } 253 } else if(txt[i] == '\n') { 254 nextX += metrics.charsWidth(txt, i - charCount, charCount); 257 charCount = 0; 258 } else { 259 charCount++; 260 } 261 } 262 nextX += metrics.charsWidth(txt, n - charCount, charCount); 263 return nextX - x; 264 } 265 266 283 public static final int getTabbedTextOffset(Segment s, FontMetrics metrics, 284 int x0, int x, TabExpander e, 285 int startOffset) { 286 return getTabbedTextOffset(s, metrics, x0, x, e, startOffset, true); 287 } 288 289 static final int getTabbedTextOffset(View view, Segment s, FontMetrics metrics, 290 int x0, int x, TabExpander e, 291 int startOffset, 292 int[] justificationData) { 293 return getTabbedTextOffset(view, s, metrics, x0, x, e, startOffset, true, 294 justificationData); 295 } 296 297 public static final int getTabbedTextOffset(Segment s, 298 FontMetrics metrics, 299 int x0, int x, TabExpander e, 300 int startOffset, 301 boolean round) { 302 return getTabbedTextOffset(null, s, metrics, x0, x, e, startOffset, round, null); 303 } 304 305 static final int getTabbedTextOffset(View view, 313 Segment s, 314 FontMetrics metrics, 315 int x0, int x, TabExpander e, 316 int startOffset, 317 boolean round, 318 int[] justificationData) { 319 if (x0 >= x) { 320 return 0; 322 } 323 int currX = x0; 324 int nextX = currX; 325 char[] txt = s.array; 328 int txtOffset = s.offset; 329 int txtCount = s.count; 330 int spaceAddon = 0 ; 331 int spaceAddonLeftoverEnd = -1; 332 int startJustifiableContent = 0 ; 333 int endJustifiableContent = 0; 334 if (justificationData != null) { 335 int offset = - startOffset + txtOffset; 336 View parent = null; 337 if (view != null 338 && (parent = view.getParent()) != null) { 339 offset += parent.getStartOffset(); 340 } 341 spaceAddon = 342 justificationData[Row.SPACE_ADDON]; 343 spaceAddonLeftoverEnd = 344 justificationData[Row.SPACE_ADDON_LEFTOVER_END] + offset; 345 startJustifiableContent = 346 justificationData[Row.START_JUSTIFIABLE] + offset; 347 endJustifiableContent = 348 justificationData[Row.END_JUSTIFIABLE] + offset; 349 } 350 int n = s.offset + s.count; 351 for (int i = s.offset; i < n; i++) { 352 if (txt[i] == '\t' 353 || ((spaceAddon != 0 || i <= spaceAddonLeftoverEnd) 354 && (txt[i] == ' ') 355 && startJustifiableContent <= i 356 && i <= endJustifiableContent 357 )){ 358 if (txt[i] == '\t') { 359 if (e != null) { 360 nextX = (int) e.nextTabStop((float) nextX, 361 startOffset + i - txtOffset); 362 } else { 363 nextX += metrics.charWidth(' '); 364 } 365 } else if (txt[i] == ' ') { 366 nextX += metrics.charWidth(' ') + spaceAddon; 367 if (i <= spaceAddonLeftoverEnd) { 368 nextX++; 369 } 370 } 371 } else { 372 nextX += metrics.charWidth(txt[i]); 373 } 374 if ((x >= currX) && (x < nextX)) { 375 if ((round == false) || ((x - currX) < (nextX - x))) { 377 return i - txtOffset; 378 } else { 379 return i + 1 - txtOffset; 380 } 381 } 382 currX = nextX; 383 } 384 385 return txtCount; 387 } 388 389 403 public static final int getBreakLocation(Segment s, FontMetrics metrics, 404 int x0, int x, TabExpander e, 405 int startOffset) { 406 char[] txt = s.array; 407 int txtOffset = s.offset; 408 int txtCount = s.count; 409 int index = Utilities.getTabbedTextOffset(s, metrics, x0, x, 410 e, startOffset, false); 411 412 413 if (index >= txtCount - 1) { 414 return txtCount; 415 } 416 417 for (int i = txtOffset + index; i >= txtOffset; i--) { 418 char ch = txt[i]; 419 if (ch < 256) { 420 if (Character.isWhitespace(ch)) { 422 index = i - txtOffset + 1; 423 break; 424 } 425 } else { 426 BreakIterator bit = BreakIterator.getLineInstance(); 428 bit.setText(s); 429 int breakPos = bit.preceding(i + 1); 430 if (breakPos > txtOffset) { 431 index = breakPos - txtOffset; 432 } 433 break; 434 } 435 } 436 return index; 437 } 438 439 451 public static final int getRowStart(JTextComponent c, int offs) throws BadLocationException { 452 Rectangle r = c.modelToView(offs); 453 if (r == null) { 454 return -1; 455 } 456 int lastOffs = offs; 457 int y = r.y; 458 while ((r != null) && (y == r.y)) { 459 offs = lastOffs; 460 lastOffs -= 1; 461 r = (lastOffs >= 0) ? c.modelToView(lastOffs) : null; 462 } 463 return offs; 464 } 465 466 478 public static final int getRowEnd(JTextComponent c, int offs) throws BadLocationException { 479 Rectangle r = c.modelToView(offs); 480 if (r == null) { 481 return -1; 482 } 483 int n = c.getDocument().getLength(); 484 int lastOffs = offs; 485 int y = r.y; 486 while ((r != null) && (y == r.y)) { 487 offs = lastOffs; 488 lastOffs += 1; 489 r = (lastOffs <= n) ? c.modelToView(lastOffs) : null; 490 } 491 return offs; 492 } 493 494 507 public static final int getPositionAbove(JTextComponent c, int offs, int x) throws BadLocationException { 508 int lastOffs = getRowStart(c, offs) - 1; 509 if (lastOffs < 0) { 510 return -1; 511 } 512 int bestSpan = Integer.MAX_VALUE; 513 int y = 0; 514 Rectangle r = null; 515 if (lastOffs >= 0) { 516 r = c.modelToView(lastOffs); 517 y = r.y; 518 } 519 while ((r != null) && (y == r.y)) { 520 int span = Math.abs(r.x - x); 521 if (span < bestSpan) { 522 offs = lastOffs; 523 bestSpan = span; 524 } 525 lastOffs -= 1; 526 r = (lastOffs >= 0) ? c.modelToView(lastOffs) : null; 527 } 528 return offs; 529 } 530 531 544 public static final int getPositionBelow(JTextComponent c, int offs, int x) throws BadLocationException { 545 int lastOffs = getRowEnd(c, offs) + 1; 546 if (lastOffs <= 0) { 547 return -1; 548 } 549 int bestSpan = Integer.MAX_VALUE; 550 int n = c.getDocument().getLength(); 551 int y = 0; 552 Rectangle r = null; 553 if (lastOffs <= n) { 554 r = c.modelToView(lastOffs); 555 y = r.y; 556 } 557 while ((r != null) && (y == r.y)) { 558 int span = Math.abs(x - r.x); 559 if (span < bestSpan) { 560 offs = lastOffs; 561 bestSpan = span; 562 } 563 lastOffs += 1; 564 r = (lastOffs <= n) ? c.modelToView(lastOffs) : null; 565 } 566 return offs; 567 } 568 569 578 public static final int getWordStart(JTextComponent c, int offs) throws BadLocationException { 579 Document doc = c.getDocument(); 580 Element line = getParagraphElement(c, offs); 581 if (line == null) { 582 throw new BadLocationException ("No word at " + offs, offs); 583 } 584 int lineStart = line.getStartOffset(); 585 int lineEnd = Math.min(line.getEndOffset(), doc.getLength()); 586 587 Segment seg = SegmentCache.getSharedSegment(); 588 doc.getText(lineStart, lineEnd - lineStart, seg); 589 if(seg.count > 0) { 590 BreakIterator words = BreakIterator.getWordInstance(c.getLocale()); 591 words.setText(seg); 592 int wordPosition = seg.offset + offs - lineStart; 593 if(wordPosition >= words.last()) { 594 wordPosition = words.last() - 1; 595 } 596 words.following(wordPosition); 597 offs = lineStart + words.previous() - seg.offset; 598 } 599 SegmentCache.releaseSharedSegment(seg); 600 return offs; 601 } 602 603 612 public static final int getWordEnd(JTextComponent c, int offs) throws BadLocationException { 613 Document doc = c.getDocument(); 614 Element line = getParagraphElement(c, offs); 615 if (line == null) { 616 throw new BadLocationException ("No word at " + offs, offs); 617 } 618 int lineStart = line.getStartOffset(); 619 int lineEnd = Math.min(line.getEndOffset(), doc.getLength()); 620 621 Segment seg = SegmentCache.getSharedSegment(); 622 doc.getText(lineStart, lineEnd - lineStart, seg); 623 if(seg.count > 0) { 624 BreakIterator words = BreakIterator.getWordInstance(c.getLocale()); 625 words.setText(seg); 626 int wordPosition = offs - lineStart + seg.offset; 627 if(wordPosition >= words.last()) { 628 wordPosition = words.last() - 1; 629 } 630 offs = lineStart + words.following(wordPosition) - seg.offset; 631 } 632 SegmentCache.releaseSharedSegment(seg); 633 return offs; 634 } 635 636 645 public static final int getNextWord(JTextComponent c, int offs) throws BadLocationException { 646 int nextWord; 647 Element line = getParagraphElement(c, offs); 648 for (nextWord = getNextWordInParagraph(c, line, offs, false); 649 nextWord == BreakIterator.DONE; 650 nextWord = getNextWordInParagraph(c, line, offs, true)) { 651 652 offs = line.getEndOffset(); 654 line = getParagraphElement(c, offs); 655 } 656 return nextWord; 657 } 658 659 666 static int getNextWordInParagraph(JTextComponent c, Element line, int offs, boolean first) throws BadLocationException { 667 if (line == null) { 668 throw new BadLocationException ("No more words", offs); 669 } 670 Document doc = line.getDocument(); 671 int lineStart = line.getStartOffset(); 672 int lineEnd = Math.min(line.getEndOffset(), doc.getLength()); 673 if ((offs >= lineEnd) || (offs < lineStart)) { 674 throw new BadLocationException ("No more words", offs); 675 } 676 Segment seg = SegmentCache.getSharedSegment(); 677 doc.getText(lineStart, lineEnd - lineStart, seg); 678 BreakIterator words = BreakIterator.getWordInstance(c.getLocale()); 679 words.setText(seg); 680 if ((first && (words.first() == (seg.offset + offs - lineStart))) && 681 (! Character.isWhitespace(seg.array[words.first()]))) { 682 683 return offs; 684 } 685 int wordPosition = words.following(seg.offset + offs - lineStart); 686 if ((wordPosition == BreakIterator.DONE) || 687 (wordPosition >= seg.offset + seg.count)) { 688 return BreakIterator.DONE; 690 } 691 char ch = seg.array[wordPosition]; 695 if (! Character.isWhitespace(ch)) { 696 return lineStart + wordPosition - seg.offset; 697 } 698 699 wordPosition = words.next(); 703 if (wordPosition != BreakIterator.DONE) { 704 offs = lineStart + wordPosition - seg.offset; 705 if (offs != lineEnd) { 706 return offs; 707 } 708 } 709 SegmentCache.releaseSharedSegment(seg); 710 return BreakIterator.DONE; 711 } 712 713 714 723 public static final int getPreviousWord(JTextComponent c, int offs) throws BadLocationException { 724 int prevWord; 725 Element line = getParagraphElement(c, offs); 726 for (prevWord = getPrevWordInParagraph(c, line, offs); 727 prevWord == BreakIterator.DONE; 728 prevWord = getPrevWordInParagraph(c, line, offs)) { 729 730 offs = line.getStartOffset() - 1; 732 line = getParagraphElement(c, offs); 733 } 734 return prevWord; 735 } 736 737 744 static int getPrevWordInParagraph(JTextComponent c, Element line, int offs) throws BadLocationException { 745 if (line == null) { 746 throw new BadLocationException ("No more words", offs); 747 } 748 Document doc = line.getDocument(); 749 int lineStart = line.getStartOffset(); 750 int lineEnd = line.getEndOffset(); 751 if ((offs > lineEnd) || (offs < lineStart)) { 752 throw new BadLocationException ("No more words", offs); 753 } 754 Segment seg = SegmentCache.getSharedSegment(); 755 doc.getText(lineStart, lineEnd - lineStart, seg); 756 BreakIterator words = BreakIterator.getWordInstance(c.getLocale()); 757 words.setText(seg); 758 if (words.following(seg.offset + offs - lineStart) == BreakIterator.DONE) { 759 words.last(); 760 } 761 int wordPosition = words.previous(); 762 if (wordPosition == (seg.offset + offs - lineStart)) { 763 wordPosition = words.previous(); 764 } 765 766 if (wordPosition == BreakIterator.DONE) { 767 return BreakIterator.DONE; 769 } 770 char ch = seg.array[wordPosition]; 774 if (! Character.isWhitespace(ch)) { 775 return lineStart + wordPosition - seg.offset; 776 } 777 778 wordPosition = words.previous(); 782 if (wordPosition != BreakIterator.DONE) { 783 return lineStart + wordPosition - seg.offset; 784 } 785 SegmentCache.releaseSharedSegment(seg); 786 return BreakIterator.DONE; 787 } 788 789 796 public static final Element getParagraphElement(JTextComponent c, int offs) { 797 Document doc = c.getDocument(); 798 if (doc instanceof StyledDocument ) { 799 return ((StyledDocument )doc).getParagraphElement(offs); 800 } 801 Element map = doc.getDefaultRootElement(); 802 int index = map.getElementIndex(offs); 803 Element paragraph = map.getElement(index); 804 if ((offs >= paragraph.getStartOffset()) && (offs < paragraph.getEndOffset())) { 805 return paragraph; 806 } 807 return null; 808 } 809 810 static boolean isComposedTextElement(Document doc, int offset) { 811 Element elem = doc.getDefaultRootElement(); 812 while (!elem.isLeaf()) { 813 elem = elem.getElement(elem.getElementIndex(offset)); 814 } 815 return isComposedTextElement(elem); 816 } 817 818 static boolean isComposedTextElement(Element elem) { 819 AttributeSet as = elem.getAttributes(); 820 return isComposedTextAttributeDefined(as); 821 } 822 823 static boolean isComposedTextAttributeDefined(AttributeSet as) { 824 return ((as != null) && 825 (as.isDefined(StyleConstants.ComposedTextAttribute))); 826 } 827 828 840 static int drawComposedText(View view, AttributeSet attr, Graphics g, 841 int x, int y, int p0, int p1) 842 throws BadLocationException { 843 Graphics2D g2d = (Graphics2D )g; 844 AttributedString as = (AttributedString)attr.getAttribute( 845 StyleConstants.ComposedTextAttribute); 846 as.addAttribute(TextAttribute.FONT, g.getFont()); 847 848 if (p0 >= p1) 849 return x; 850 851 AttributedCharacterIterator aci = as.getIterator(null, p0, p1); 852 return x + (int)SwingUtilities2.drawString( 853 getJComponent(view), g2d,aci,x,y); 854 } 855 856 859 static void paintComposedText(Graphics g, Rectangle alloc, GlyphView v) { 860 if (g instanceof Graphics2D ) { 861 Graphics2D g2d = (Graphics2D ) g; 862 int p0 = v.getStartOffset(); 863 int p1 = v.getEndOffset(); 864 AttributeSet attrSet = v.getElement().getAttributes(); 865 AttributedString as = 866 (AttributedString)attrSet.getAttribute(StyleConstants.ComposedTextAttribute); 867 int start = v.getElement().getStartOffset(); 868 int y = alloc.y + alloc.height - (int)v.getGlyphPainter().getDescent(v); 869 int x = alloc.x; 870 871 as.addAttribute(TextAttribute.FONT, v.getFont()); 873 as.addAttribute(TextAttribute.FOREGROUND, v.getForeground()); 874 if (StyleConstants.isBold(v.getAttributes())) { 875 as.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); 876 } 877 if (StyleConstants.isItalic(v.getAttributes())) { 878 as.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE); 879 } 880 if (v.isUnderline()) { 881 as.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); 882 } 883 if (v.isStrikeThrough()) { 884 as.addAttribute(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON); 885 } 886 if (v.isSuperscript()) { 887 as.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER); 888 } 889 if (v.isSubscript()) { 890 as.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUB); 891 } 892 893 AttributedCharacterIterator aci = as.getIterator(null, p0 - start, p1 - start); 895 SwingUtilities2.drawString(getJComponent(v), 896 g2d,aci,x,y); 897 } 898 } 899 900 904 static boolean isLeftToRight( java.awt.Component c ) { 905 return c.getComponentOrientation().isLeftToRight(); 906 } 907 908 909 941 static int getNextVisualPositionFrom(View v, int pos, Position.Bias b, 942 Shape alloc, int direction, 943 Position.Bias [] biasRet) 944 throws BadLocationException { 945 if (v.getViewCount() == 0) { 946 return pos; 948 } 949 boolean top = (direction == SwingConstants.NORTH || 950 direction == SwingConstants.WEST); 951 int retValue; 952 if (pos == -1) { 953 int childIndex = (top) ? v.getViewCount() - 1 : 0; 955 View child = v.getView(childIndex); 956 Shape childBounds = v.getChildAllocation(childIndex, alloc); 957 retValue = child.getNextVisualPositionFrom(pos, b, childBounds, 958 direction, biasRet); 959 if (retValue == -1 && !top && v.getViewCount() > 1) { 960 child = v.getView(1); 964 childBounds = v.getChildAllocation(1, alloc); 965 retValue = child.getNextVisualPositionFrom(-1, biasRet[0], 966 childBounds, 967 direction, biasRet); 968 } 969 } 970 else { 971 int increment = (top) ? -1 : 1; 972 int childIndex; 973 if (b == Position.Bias.Backward && pos > 0) { 974 childIndex = v.getViewIndex(pos - 1, Position.Bias.Forward); 975 } 976 else { 977 childIndex = v.getViewIndex(pos, Position.Bias.Forward); 978 } 979 View child = v.getView(childIndex); 980 Shape childBounds = v.getChildAllocation(childIndex, alloc); 981 retValue = child.getNextVisualPositionFrom(pos, b, childBounds, 982 direction, biasRet); 983 if ((direction == SwingConstants.EAST || 984 direction == SwingConstants.WEST) && 985 (v instanceof CompositeView ) && 986 ((CompositeView )v).flipEastAndWestAtEnds(pos, b)) { 987 increment *= -1; 988 } 989 childIndex += increment; 990 if (retValue == -1 && childIndex >= 0 && 991 childIndex < v.getViewCount()) { 992 child = v.getView(childIndex); 993 childBounds = v.getChildAllocation(childIndex, alloc); 994 retValue = child.getNextVisualPositionFrom( 995 -1, b, childBounds, direction, biasRet); 996 if (retValue == pos && biasRet[0] != b) { 1000 return getNextVisualPositionFrom(v, pos, biasRet[0], 1001 alloc, direction, 1002 biasRet); 1003 } 1004 } 1005 else if (retValue != -1 && biasRet[0] != b && 1006 ((increment == 1 && child.getEndOffset() == retValue) || 1007 (increment == -1 && 1008 child.getStartOffset() == retValue)) && 1009 childIndex >= 0 && childIndex < v.getViewCount()) { 1010 child = v.getView(childIndex); 1013 childBounds = v.getChildAllocation(childIndex, alloc); 1014 Position.Bias originalBias = biasRet[0]; 1015 int nextPos = child.getNextVisualPositionFrom( 1016 -1, b, childBounds, direction, biasRet); 1017 if (biasRet[0] == b) { 1018 retValue = nextPos; 1019 } 1020 else { 1021 biasRet[0] = originalBias; 1022 } 1023 } 1024 } 1025 return retValue; 1026 } 1027} 1028 | Popular Tags |