Merge "Suppress horizontal scrolling with trailing blanks"

This commit is contained in:
Raph Levien
2012-12-20 15:46:23 -08:00
committed by Android (Google) Code Review
3 changed files with 82 additions and 24 deletions

View File

@@ -792,8 +792,17 @@ public abstract class Layout {
* the paragraph's primary direction.
*/
public float getPrimaryHorizontal(int offset) {
return getPrimaryHorizontal(offset, false /* not clamped */);
}
/**
* Get the primary horizontal position for the specified text offset, but
* optionally clamp it so that it doesn't exceed the width of the layout.
* @hide
*/
public float getPrimaryHorizontal(int offset, boolean clamped) {
boolean trailing = primaryIsTrailingPrevious(offset);
return getHorizontal(offset, trailing);
return getHorizontal(offset, trailing, clamped);
}
/**
@@ -802,17 +811,26 @@ public abstract class Layout {
* the direction other than the paragraph's primary direction.
*/
public float getSecondaryHorizontal(int offset) {
boolean trailing = primaryIsTrailingPrevious(offset);
return getHorizontal(offset, !trailing);
return getSecondaryHorizontal(offset, false /* not clamped */);
}
private float getHorizontal(int offset, boolean trailing) {
/**
* Get the secondary horizontal position for the specified text offset, but
* optionally clamp it so that it doesn't exceed the width of the layout.
* @hide
*/
public float getSecondaryHorizontal(int offset, boolean clamped) {
boolean trailing = primaryIsTrailingPrevious(offset);
return getHorizontal(offset, !trailing, clamped);
}
private float getHorizontal(int offset, boolean trailing, boolean clamped) {
int line = getLineForOffset(offset);
return getHorizontal(offset, trailing, line);
return getHorizontal(offset, trailing, line, clamped);
}
private float getHorizontal(int offset, boolean trailing, int line) {
private float getHorizontal(int offset, boolean trailing, int line, boolean clamped) {
int start = getLineStart(line);
int end = getLineEnd(line);
int dir = getParagraphDirection(line);
@@ -834,6 +852,9 @@ public abstract class Layout {
float wid = tl.measure(offset - start, trailing, null);
TextLine.recycle(tl);
if (clamped && wid > mWidth) {
wid = mWidth;
}
int left = getParagraphLeft(line);
int right = getParagraphRight(line);
@@ -1256,6 +1277,23 @@ public abstract class Layout {
return offset;
}
/**
* Determine whether we should clamp cursor position. Currently it's
* only robust for left-aligned displays.
* @hide
*/
public boolean shouldClampCursor(int line) {
// Only clamp cursor position in left-aligned displays.
switch (getParagraphAlignment(line)) {
case ALIGN_LEFT:
return true;
case ALIGN_NORMAL:
return getParagraphDirection(line) > 0;
default:
return false;
}
}
/**
* Fills in the specified Path with a representation of a cursor
* at the specified offset. This will often be a vertical line
@@ -1270,8 +1308,9 @@ public abstract class Layout {
int top = getLineTop(line);
int bottom = getLineTop(line+1);
float h1 = getPrimaryHorizontal(point) - 0.5f;
float h2 = isLevelBoundary(point) ? getSecondaryHorizontal(point) - 0.5f : h1;
boolean clamped = shouldClampCursor(line);
float h1 = getPrimaryHorizontal(point, clamped) - 0.5f;
float h2 = isLevelBoundary(point) ? getSecondaryHorizontal(point, clamped) - 0.5f : h1;
int caps = TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SHIFT_ON) |
TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SELECTING);
@@ -1357,8 +1396,8 @@ public abstract class Layout {
int en = Math.min(end, there);
if (st != en) {
float h1 = getHorizontal(st, false, line);
float h2 = getHorizontal(en, true, line);
float h1 = getHorizontal(st, false, line, false /* not clamped */);
float h2 = getHorizontal(en, true, line, false /* not clamped */);
float left = Math.min(h1, h2);
float right = Math.max(h1, h2);

View File

@@ -1468,20 +1468,24 @@ public class Editor {
middle = (top + bottom) >> 1;
}
updateCursorPosition(0, top, middle, getPrimaryHorizontal(layout, hintLayout, offset));
boolean clamped = layout.shouldClampCursor(line);
updateCursorPosition(0, top, middle,
getPrimaryHorizontal(layout, hintLayout, offset, clamped));
if (mCursorCount == 2) {
updateCursorPosition(1, middle, bottom, layout.getSecondaryHorizontal(offset));
updateCursorPosition(1, middle, bottom,
layout.getSecondaryHorizontal(offset, clamped));
}
}
private float getPrimaryHorizontal(Layout layout, Layout hintLayout, int offset) {
private float getPrimaryHorizontal(Layout layout, Layout hintLayout, int offset,
boolean clamped) {
if (TextUtils.isEmpty(layout.getText()) &&
hintLayout != null &&
!TextUtils.isEmpty(hintLayout.getText())) {
return hintLayout.getPrimaryHorizontal(offset);
return hintLayout.getPrimaryHorizontal(offset, clamped);
} else {
return layout.getPrimaryHorizontal(offset);
return layout.getPrimaryHorizontal(offset, clamped);
}
}

View File

@@ -6553,15 +6553,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
int line = layout.getLineForOffset(offset);
// FIXME: Is it okay to truncate this, or should we round?
final int x = (int)layout.getPrimaryHorizontal(offset);
final int top = layout.getLineTop(line);
final int bottom = layout.getLineTop(line + 1);
int left = (int) FloatMath.floor(layout.getLineLeft(line));
int right = (int) FloatMath.ceil(layout.getLineRight(line));
int ht = layout.getHeight();
int grav;
switch (layout.getParagraphAlignment(line)) {
@@ -6583,8 +6574,32 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
break;
}
// We only want to clamp the cursor to fit within the layout width
// in left-to-right modes, because in a right to left alignment,
// we want to scroll to keep the line-right on the screen, as other
// lines are likely to have text flush with the right margin, which
// we want to keep visible.
// A better long-term solution would probably be to measure both
// the full line and a blank-trimmed version, and, for example, use
// the latter measurement for centering and right alignment, but for
// the time being we only implement the cursor clamping in left to
// right where it is most likely to be annoying.
final boolean clamped = grav > 0;
// FIXME: Is it okay to truncate this, or should we round?
final int x = (int)layout.getPrimaryHorizontal(offset, clamped);
final int top = layout.getLineTop(line);
final int bottom = layout.getLineTop(line + 1);
int left = (int) FloatMath.floor(layout.getLineLeft(line));
int right = (int) FloatMath.ceil(layout.getLineRight(line));
int ht = layout.getHeight();
int hspace = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight();
int vspace = mBottom - mTop - getExtendedPaddingTop() - getExtendedPaddingBottom();
if (!mHorizontallyScrolling && right - left > hspace && right > x) {
// If cursor has been clamped, make sure we don't scroll.
right = Math.max(x, left + hspace);
}
int hslack = (bottom - top) / 2;
int vslack = hslack;