summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/inputmethod/ExtractedText.java2
-rw-r--r--core/java/android/widget/Editor.java187
-rw-r--r--core/java/android/widget/SpellChecker.java5
-rw-r--r--core/java/android/widget/TextView.java19
4 files changed, 81 insertions, 132 deletions
diff --git a/core/java/android/view/inputmethod/ExtractedText.java b/core/java/android/view/inputmethod/ExtractedText.java
index 662ba3f..3b2508c 100644
--- a/core/java/android/view/inputmethod/ExtractedText.java
+++ b/core/java/android/view/inputmethod/ExtractedText.java
@@ -45,7 +45,7 @@ public class ExtractedText implements Parcelable {
/**
* If the content is a report of a partial text change, this is the offset
* where the change ends. Note that the actual text may be larger or
- * smaller than the difference between this and {@link #partialEndOffset},
+ * smaller than the difference between this and {@link #partialStartOffset},
* meaning a reduction or increase, respectively, in the total text.
*/
public int partialEndOffset;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index cbff58c..d16e9da 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -47,7 +47,6 @@ import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.StaticLayout;
import android.text.TextUtils;
-import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.text.method.MetaKeyKeyListener;
import android.text.method.MovementMethod;
@@ -183,8 +182,6 @@ public class Editor {
Editor(TextView textView) {
mTextView = textView;
- mEasyEditSpanController = new EasyEditSpanController();
- mTextView.addTextChangedListener(mEasyEditSpanController);
}
void onAttachedToWindow() {
@@ -1120,7 +1117,7 @@ public class Editor {
if (contentChanged || ims.mSelectionModeChanged) {
ims.mContentChanged = false;
ims.mSelectionModeChanged = false;
- final ExtractedTextRequest req = ims.mExtracting;
+ final ExtractedTextRequest req = ims.mExtractedTextRequest;
if (req != null) {
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) {
@@ -1132,13 +1129,14 @@ public class Editor {
ims.mChangedStart = EXTRACT_NOTHING;
}
if (extractTextInternal(req, ims.mChangedStart, ims.mChangedEnd,
- ims.mChangedDelta, ims.mTmpExtracted)) {
+ ims.mChangedDelta, ims.mExtractedText)) {
if (TextView.DEBUG_EXTRACT) Log.v(TextView.LOG_TAG,
"Reporting extracted start=" +
- ims.mTmpExtracted.partialStartOffset +
- " end=" + ims.mTmpExtracted.partialEndOffset +
- ": " + ims.mTmpExtracted.text);
- imm.updateExtractedText(mTextView, req.token, ims.mTmpExtracted);
+ ims.mExtractedText.partialStartOffset +
+ " end=" + ims.mExtractedText.partialEndOffset +
+ ": " + ims.mExtractedText.text);
+
+ imm.updateExtractedText(mTextView, req.token, ims.mExtractedText);
ims.mChangedStart = EXTRACT_UNKNOWN;
ims.mChangedEnd = EXTRACT_UNKNOWN;
ims.mChangedDelta = 0;
@@ -1734,138 +1732,92 @@ public class Editor {
}
}
+ public void addSpanWatchers(Spannable text) {
+ final int textLength = text.length();
+
+ if (mKeyListener != null) {
+ text.setSpan(mKeyListener, 0, textLength, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ }
+
+ if (mEasyEditSpanController == null) {
+ mEasyEditSpanController = new EasyEditSpanController();
+ }
+ text.setSpan(mEasyEditSpanController, 0, textLength, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ }
+
/**
* Controls the {@link EasyEditSpan} monitoring when it is added, and when the related
* pop-up should be displayed.
*/
- class EasyEditSpanController implements TextWatcher {
+ class EasyEditSpanController implements SpanWatcher {
private static final int DISPLAY_TIMEOUT_MS = 3000; // 3 secs
private EasyEditPopupWindow mPopupWindow;
- private EasyEditSpan mEasyEditSpan;
-
private Runnable mHidePopup;
- public void hide() {
- if (mPopupWindow != null) {
- mPopupWindow.hide();
- mTextView.removeCallbacks(mHidePopup);
- }
- removeSpans(mTextView.getText());
- mEasyEditSpan = null;
- }
-
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- // Intentionally empty
- }
-
- public void afterTextChanged(Editable s) {
- // Intentionally empty
- }
+ @Override
+ public void onSpanAdded(Spannable text, Object span, int start, int end) {
+ if (span instanceof EasyEditSpan) {
+ if (mPopupWindow == null) {
+ mPopupWindow = new EasyEditPopupWindow();
+ mHidePopup = new Runnable() {
+ @Override
+ public void run() {
+ hide();
+ }
+ };
+ }
- /**
- * Monitors the changes in the text.
- *
- * <p>{@link SpanWatcher#onSpanAdded(Spannable, Object, int, int)} cannot be used,
- * as the notifications are not sent when a spannable (with spans) is inserted.
- */
- public void onTextChanged(CharSequence buffer, int start, int before, int after) {
- adjustSpans(buffer, start, after);
+ // Make sure there is only at most one EasyEditSpan in the text
+ if (mPopupWindow.mEasyEditSpan != null) {
+ text.removeSpan(mPopupWindow.mEasyEditSpan);
+ }
- if (mTextView.getWindowVisibility() != View.VISIBLE) {
- // The window is not visible yet, ignore the text change.
- return;
- }
+ mPopupWindow.setEasyEditSpan((EasyEditSpan) span);
- if (mTextView.getLayout() == null) {
- // The view has not been layout yet, ignore the text change
- return;
- }
-
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (!(mTextView instanceof ExtractEditText) && imm != null && imm.isFullscreenMode()) {
- // The input is in extract mode. We do not have to handle the easy edit in the
- // original TextView, as the ExtractEditText will do
- return;
- }
+ if (mTextView.getWindowVisibility() != View.VISIBLE) {
+ // The window is not visible yet, ignore the text change.
+ return;
+ }
- // Remove the current easy edit span, as the text changed, and remove the pop-up
- // (if any)
- if (mEasyEditSpan != null) {
- if (buffer instanceof Spannable) {
- ((Spannable) buffer).removeSpan(mEasyEditSpan);
+ if (mTextView.getLayout() == null) {
+ // The view has not been laid out yet, ignore the text change
+ return;
}
- mEasyEditSpan = null;
- }
- if (mPopupWindow != null && mPopupWindow.isShowing()) {
- mPopupWindow.hide();
- }
- // Display the new easy edit span (if any).
- if (buffer instanceof Spanned) {
- mEasyEditSpan = getSpan((Spanned) buffer);
- if (mEasyEditSpan != null) {
- if (mPopupWindow == null) {
- mPopupWindow = new EasyEditPopupWindow();
- mHidePopup = new Runnable() {
- @Override
- public void run() {
- hide();
- }
- };
- }
- mPopupWindow.show(mEasyEditSpan);
- mTextView.removeCallbacks(mHidePopup);
- mTextView.postDelayed(mHidePopup, DISPLAY_TIMEOUT_MS);
+ if (extractedTextModeWillBeStarted()) {
+ // The input is in extract mode. Do not handle the easy edit in
+ // the original TextView, as the ExtractEditText will do
+ return;
}
+
+ mPopupWindow.show();
+ mTextView.removeCallbacks(mHidePopup);
+ mTextView.postDelayed(mHidePopup, DISPLAY_TIMEOUT_MS);
}
}
- /**
- * Adjusts the spans by removing all of them except the last one.
- */
- private void adjustSpans(CharSequence buffer, int start, int after) {
- // This method enforces that only one easy edit span is attached to the text.
- // A better way to enforce this would be to listen for onSpanAdded, but this method
- // cannot be used in this scenario as no notification is triggered when a text with
- // spans is inserted into a text.
- if (buffer instanceof Spannable) {
- Spannable spannable = (Spannable) buffer;
- EasyEditSpan[] spans = spannable.getSpans(start, start + after, EasyEditSpan.class);
- if (spans.length > 0) {
- // Assuming there was only one EasyEditSpan before, we only need check to
- // check for a duplicate if a new one is found in the modified interval
- spans = spannable.getSpans(0, spannable.length(), EasyEditSpan.class);
- for (int i = 1; i < spans.length; i++) {
- spannable.removeSpan(spans[i]);
- }
- }
+ @Override
+ public void onSpanRemoved(Spannable text, Object span, int start, int end) {
+ if (mPopupWindow != null && span == mPopupWindow.mEasyEditSpan) {
+ hide();
}
}
- /**
- * Removes all the {@link EasyEditSpan} currently attached.
- */
- private void removeSpans(CharSequence buffer) {
- if (buffer instanceof Spannable) {
- Spannable spannable = (Spannable) buffer;
- EasyEditSpan[] spans = spannable.getSpans(0, spannable.length(),
- EasyEditSpan.class);
- for (int i = 0; i < spans.length; i++) {
- spannable.removeSpan(spans[i]);
- }
+ @Override
+ public void onSpanChanged(Spannable text, Object span, int previousStart, int previousEnd,
+ int newStart, int newEnd) {
+ if (mPopupWindow != null && span == mPopupWindow.mEasyEditSpan) {
+ text.removeSpan(mPopupWindow.mEasyEditSpan);
}
}
- private EasyEditSpan getSpan(Spanned spanned) {
- EasyEditSpan[] easyEditSpans = spanned.getSpans(0, spanned.length(),
- EasyEditSpan.class);
- if (easyEditSpans.length == 0) {
- return null;
- } else {
- return easyEditSpans[0];
+ public void hide() {
+ if (mPopupWindow != null) {
+ mPopupWindow.hide();
+ mTextView.removeCallbacks(mHidePopup);
}
}
}
@@ -1910,9 +1862,8 @@ public class Editor {
mContentView.addView(mDeleteTextView);
}
- public void show(EasyEditSpan easyEditSpan) {
+ public void setEasyEditSpan(EasyEditSpan easyEditSpan) {
mEasyEditSpan = easyEditSpan;
- super.show();
}
@Override
@@ -3738,8 +3689,8 @@ public class Editor {
Rect mCursorRectInWindow = new Rect();
RectF mTmpRectF = new RectF();
float[] mTmpOffset = new float[2];
- ExtractedTextRequest mExtracting;
- final ExtractedText mTmpExtracted = new ExtractedText();
+ ExtractedTextRequest mExtractedTextRequest;
+ final ExtractedText mExtractedText = new ExtractedText();
int mBatchEditNesting;
boolean mCursorChanged;
boolean mSelectionModeChanged;
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index c725b64..f033072 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -207,6 +207,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
public void spellCheck(int start, int end) {
final Locale locale = mTextView.getTextServicesLocale();
+ final boolean isSessionActive = isSessionActive();
if (mCurrentLocale == null || (!(mCurrentLocale.equals(locale)))) {
setLocale(locale);
// Re-check the entire text
@@ -214,13 +215,13 @@ public class SpellChecker implements SpellCheckerSessionListener {
end = mTextView.getText().length();
} else {
final boolean spellCheckerActivated = mTextServicesManager.isSpellCheckerEnabled();
- if (isSessionActive() != spellCheckerActivated) {
+ if (isSessionActive != spellCheckerActivated) {
// Spell checker has been turned of or off since last spellCheck
resetSession();
}
}
- if (!isSessionActive()) return;
+ if (!isSessionActive) return;
// Find first available SpellParser from pool
final int length = mSpellParsers.length;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9867e47..5164c7a 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3176,22 +3176,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (text instanceof Spannable && !mAllowTransformationLengthChange) {
Spannable sp = (Spannable) text;
- // Remove any ChangeWatchers that might have come
- // from other TextViews.
+ // Remove any ChangeWatchers that might have come from other TextViews.
final ChangeWatcher[] watchers = sp.getSpans(0, sp.length(), ChangeWatcher.class);
final int count = watchers.length;
- for (int i = 0; i < count; i++)
+ for (int i = 0; i < count; i++) {
sp.removeSpan(watchers[i]);
+ }
- if (mChangeWatcher == null)
- mChangeWatcher = new ChangeWatcher();
+ if (mChangeWatcher == null) mChangeWatcher = new ChangeWatcher();
sp.setSpan(mChangeWatcher, 0, textLength, Spanned.SPAN_INCLUSIVE_INCLUSIVE |
(CHANGE_WATCHER_PRIORITY << Spanned.SPAN_PRIORITY_SHIFT));
- if (mEditor != null && getEditor().mKeyListener != null) {
- sp.setSpan(getEditor().mKeyListener, 0, textLength, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- }
+ if (mEditor != null) mEditor.addSpanWatchers(sp);
if (mTransformation != null) {
sp.setSpan(mTransformation, 0, textLength, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
@@ -5231,7 +5228,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*/
public void setExtracting(ExtractedTextRequest req) {
if (getEditor().mInputMethodState != null) {
- getEditor().mInputMethodState.mExtracting = req;
+ getEditor().mInputMethodState.mExtractedTextRequest = req;
}
// This would stop a possible selection mode, but no such mode is started in case
// extracted mode will start. Some text is selected though, and will trigger an action mode
@@ -6876,7 +6873,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (what instanceof ParcelableSpan) {
// If this is a span that can be sent to a remote process,
// the current extract editor would be interested in it.
- if (ims != null && ims.mExtracting != null) {
+ if (ims != null && ims.mExtractedTextRequest != null) {
if (ims.mBatchEditNesting != 0) {
if (oldStart >= 0) {
if (ims.mChangedStart > oldStart) {
@@ -6897,7 +6894,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} else {
if (DEBUG_EXTRACT) Log.v(LOG_TAG, "Span change outside of batch: "
+ oldStart + "-" + oldEnd + ","
- + newStart + "-" + newEnd + what);
+ + newStart + "-" + newEnd + " " + what);
ims.mContentChanged = true;
}
}