public Shape modelToView(GlyphView v, int pos, Position.Bias bias, Shape a) throws BadLocationException { int offs = pos - v.getStartOffset(); Rectangle2D alloc = a.getBounds2D(); TextHitInfo hit = (bias == Position.Bias.Forward) ? TextHitInfo.afterOffset(offs) : TextHitInfo.beforeOffset(offs); float[] locs = layout.getCaretInfo(hit); // vertical at the baseline, should use slope and check if glyphs // are being rendered vertically. alloc.setRect(alloc.getX() + locs[0], alloc.getY(), 1, alloc.getHeight()); return alloc; }
/** * Determine the span the glyphs given a start location (for tab expansion). This implementation * assumes it has no tabs (i.e. TextLayout doesn't deal with tab expansion). */ public float getSpan(GlyphView v, int p0, int p1, TabExpander e, float x) { if ((p0 == v.getStartOffset()) && (p1 == v.getEndOffset())) { return layout.getAdvance(); } int p = v.getStartOffset(); int index0 = p0 - p; int index1 = p1 - p; TextHitInfo hit0 = TextHitInfo.afterOffset(index0); TextHitInfo hit1 = TextHitInfo.beforeOffset(index1); float[] locs = layout.getCaretInfo(hit0); float x0 = locs[0]; locs = layout.getCaretInfo(hit1); float x1 = locs[0]; return (x1 > x0) ? x1 - x0 : x0 - x1; }
/** * Provides a way to determine the next visually represented model location that one might place a * caret. Some views may not be visible, they might not be in the same order found in the model, * or they just might not allow access to some of the locations in the model. * * @param v the view to use * @param pos the position to convert >= 0 * @param a the allocated region to render into * @param direction the direction from the current position that can be thought of as the arrow * keys typically found on a keyboard. This may be SwingConstants.WEST, SwingConstants.EAST, * SwingConstants.NORTH, or SwingConstants.SOUTH. * @return the location within the model that best represents the next location visual position. * @exception BadLocationException * @exception IllegalArgumentException for an invalid direction */ public int getNextVisualPositionFrom( GlyphView v, int pos, Position.Bias b, Shape a, int direction, Position.Bias[] biasRet) throws BadLocationException { int startOffset = v.getStartOffset(); int endOffset = v.getEndOffset(); Segment text; AbstractDocument doc; boolean viewIsLeftToRight; TextHitInfo currentHit, nextHit; switch (direction) { case View.NORTH: break; case View.SOUTH: break; case View.EAST: doc = (AbstractDocument) v.getDocument(); viewIsLeftToRight = doc.isLeftToRight(startOffset, endOffset); if (startOffset == doc.getLength()) { if (pos == -1) { biasRet[0] = Position.Bias.Forward; return startOffset; } // End case for bidi text where newline is at beginning // of line. return -1; } if (pos == -1) { // Entering view from the left. if (viewIsLeftToRight) { biasRet[0] = Position.Bias.Forward; return startOffset; } else { text = v.getText(endOffset - 1, endOffset); char c = text.array[text.offset]; SegmentCache.releaseSharedSegment(text); if (c == '\n') { biasRet[0] = Position.Bias.Forward; return endOffset - 1; } biasRet[0] = Position.Bias.Backward; return endOffset; } } if (b == Position.Bias.Forward) currentHit = TextHitInfo.afterOffset(pos - startOffset); else currentHit = TextHitInfo.beforeOffset(pos - startOffset); nextHit = layout.getNextRightHit(currentHit); if (nextHit == null) { return -1; } if (viewIsLeftToRight != layout.isLeftToRight()) { // If the layout's base direction is different from // this view's run direction, we need to use the weak // carrat. nextHit = layout.getVisualOtherHit(nextHit); } pos = nextHit.getInsertionIndex() + startOffset; if (pos == endOffset) { // A move to the right from an internal position will // only take us to the endOffset in a left to right run. text = v.getText(endOffset - 1, endOffset); char c = text.array[text.offset]; SegmentCache.releaseSharedSegment(text); if (c == '\n') { return -1; } biasRet[0] = Position.Bias.Backward; } else { biasRet[0] = Position.Bias.Forward; } return pos; case View.WEST: doc = (AbstractDocument) v.getDocument(); viewIsLeftToRight = doc.isLeftToRight(startOffset, endOffset); if (startOffset == doc.getLength()) { if (pos == -1) { biasRet[0] = Position.Bias.Forward; return startOffset; } // End case for bidi text where newline is at beginning // of line. return -1; } if (pos == -1) { // Entering view from the right if (viewIsLeftToRight) { text = v.getText(endOffset - 1, endOffset); char c = text.array[text.offset]; SegmentCache.releaseSharedSegment(text); if ((c == '\n') || Character.isSpaceChar(c)) { biasRet[0] = Position.Bias.Forward; return endOffset - 1; } biasRet[0] = Position.Bias.Backward; return endOffset; } else { biasRet[0] = Position.Bias.Forward; return startOffset; } } if (b == Position.Bias.Forward) currentHit = TextHitInfo.afterOffset(pos - startOffset); else currentHit = TextHitInfo.beforeOffset(pos - startOffset); nextHit = layout.getNextLeftHit(currentHit); if (nextHit == null) { return -1; } if (viewIsLeftToRight != layout.isLeftToRight()) { // If the layout's base direction is different from // this view's run direction, we need to use the weak // carrat. nextHit = layout.getVisualOtherHit(nextHit); } pos = nextHit.getInsertionIndex() + startOffset; if (pos == endOffset) { // A move to the left from an internal position will // only take us to the endOffset in a right to left run. text = v.getText(endOffset - 1, endOffset); char c = text.array[text.offset]; SegmentCache.releaseSharedSegment(text); if (c == '\n') { return -1; } biasRet[0] = Position.Bias.Backward; } else { biasRet[0] = Position.Bias.Forward; } return pos; default: throw new IllegalArgumentException("Bad direction: " + direction); } return pos; }