summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorLuca Zanolin <zano@google.com>2013-02-14 14:18:26 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-02-20 11:35:19 +0000
commit8cd8135b95da5b471804604b06084eecbe1cc23b (patch)
tree4c2bc2ba891f16b32bfff70f5994ab1ecfc56a1a /core/java
parent8983d11c4069bc136f496987f11df7dcd5771188 (diff)
downloadframeworks_base-8cd8135b95da5b471804604b06084eecbe1cc23b.zip
frameworks_base-8cd8135b95da5b471804604b06084eecbe1cc23b.tar.gz
frameworks_base-8cd8135b95da5b471804604b06084eecbe1cc23b.tar.bz2
Enable correction/deleting notification via EasyEditSpan.
When the "delete" pop-up is clicked (and the wrapped text removed), the creator of the span will receive a notification of the action. Similarly, if the user modifies (i.e., add/remove a char), the creator of the span will receive a notification too. The notification will not contain any information about how the text has been modified. Bug: 6905960 Change-Id: Ic227b8fd50066699915f69a54f225fb5330867c4
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/text/TextUtils.java2
-rw-r--r--core/java/android/text/style/EasyEditSpan.java85
-rw-r--r--core/java/android/widget/Editor.java73
3 files changed, 146 insertions, 14 deletions
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 1508d10..2ab9bf8 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -757,7 +757,7 @@ public class TextUtils {
break;
case EASY_EDIT_SPAN:
- readSpan(p, sp, new EasyEditSpan());
+ readSpan(p, sp, new EasyEditSpan(p));
break;
case LOCALE_SPAN:
diff --git a/core/java/android/text/style/EasyEditSpan.java b/core/java/android/text/style/EasyEditSpan.java
index 2feb719..03b4f60 100644
--- a/core/java/android/text/style/EasyEditSpan.java
+++ b/core/java/android/text/style/EasyEditSpan.java
@@ -16,6 +16,7 @@
package android.text.style;
+import android.app.PendingIntent;
import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextUtils;
@@ -25,12 +26,62 @@ import android.widget.TextView;
* Provides an easy way to edit a portion of text.
* <p>
* The {@link TextView} uses this span to allow the user to delete a chuck of text in one click.
- * the text. {@link TextView} removes this span as soon as the text is edited, or the cursor moves.
+ * <p>
+ * {@link TextView} removes the span when the user deletes the whole text or modifies it.
+ * <p>
+ * This span can be also used to receive notification when the user deletes or modifies the text;
*/
public class EasyEditSpan implements ParcelableSpan {
+ /**
+ * The extra key field in the pending intent that describes how the text changed.
+ *
+ * @see #TEXT_DELETED
+ * @see #TEXT_MODIFIED
+ * @see #getPendingIntent()
+ */
+ public static final String EXTRA_TEXT_CHANGED_TYPE =
+ "android.text.style.EXTRA_TEXT_CHANGED_TYPE";
+
+ /**
+ * The value of {@link #EXTRA_TEXT_CHANGED_TYPE} when the text wrapped by this span is deleted.
+ */
+ public static final int TEXT_DELETED = 1;
+
+ /**
+ * The value of {@link #EXTRA_TEXT_CHANGED_TYPE} when the text wrapped by this span is modified.
+ */
+ public static final int TEXT_MODIFIED = 2;
+
+ private final PendingIntent mPendingIntent;
+
+ private boolean mDeleteEnabled;
+
+ /**
+ * Creates the span. No intent is sent when the wrapped text is modified or
+ * deleted.
+ */
public EasyEditSpan() {
- // Empty
+ mPendingIntent = null;
+ mDeleteEnabled = true;
+ }
+
+ /**
+ * @param pendingIntent The intent will be sent when the wrapped text is deleted or modified.
+ * When the pending intent is sent, {@link #EXTRA_TEXT_CHANGED_TYPE} is
+ * added in the intent to describe how the text changed.
+ */
+ public EasyEditSpan(PendingIntent pendingIntent) {
+ mPendingIntent = pendingIntent;
+ mDeleteEnabled = true;
+ }
+
+ /**
+ * Constructor called from {@link TextUtils} to restore the span.
+ */
+ public EasyEditSpan(Parcel source) {
+ mPendingIntent = source.readParcelable(null);
+ mDeleteEnabled = (source.readByte() == 1);
}
@Override
@@ -40,11 +91,39 @@ public class EasyEditSpan implements ParcelableSpan {
@Override
public void writeToParcel(Parcel dest, int flags) {
- // Empty
+ dest.writeParcelable(mPendingIntent, 0);
+ dest.writeByte((byte) (mDeleteEnabled ? 1 : 0));
}
@Override
public int getSpanTypeId() {
return TextUtils.EASY_EDIT_SPAN;
}
+
+ /**
+ * @return True if the {@link TextView} should offer the ability to delete the text.
+ *
+ * @hide
+ */
+ public boolean isDeleteEnabled() {
+ return mDeleteEnabled;
+ }
+
+ /**
+ * Enables or disables the deletion of the text.
+ *
+ * @hide
+ */
+ public void setDeleteEnabled(boolean value) {
+ mDeleteEnabled = value;
+ }
+
+ /**
+ * @return the pending intent to send when the wrapped text is deleted or modified.
+ *
+ * @hide
+ */
+ public PendingIntent getPendingIntent() {
+ return mPendingIntent;
+ }
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 862e2c8..dc305a5 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -20,6 +20,8 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.EditableInputConnection;
import android.R;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
import android.content.ClipData;
import android.content.ClipData.Item;
import android.content.Context;
@@ -1890,10 +1892,23 @@ public class Editor {
// Make sure there is only at most one EasyEditSpan in the text
if (mPopupWindow.mEasyEditSpan != null) {
- text.removeSpan(mPopupWindow.mEasyEditSpan);
+ mPopupWindow.mEasyEditSpan.setDeleteEnabled(false);
}
mPopupWindow.setEasyEditSpan((EasyEditSpan) span);
+ mPopupWindow.setOnDeleteListener(new EasyEditDeleteListener() {
+ @Override
+ public void onDeleteClick(EasyEditSpan span) {
+ Editable editable = (Editable) mTextView.getText();
+ int start = editable.getSpanStart(span);
+ int end = editable.getSpanEnd(span);
+ if (start >= 0 && end >= 0) {
+ sendNotification(EasyEditSpan.TEXT_DELETED, span);
+ mTextView.deleteText_internal(start, end);
+ }
+ editable.removeSpan(span);
+ }
+ });
if (mTextView.getWindowVisibility() != View.VISIBLE) {
// The window is not visible yet, ignore the text change.
@@ -1927,8 +1942,10 @@ public class Editor {
@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);
+ if (mPopupWindow != null && span instanceof EasyEditSpan) {
+ EasyEditSpan easyEditSpan = (EasyEditSpan) span;
+ sendNotification(EasyEditSpan.TEXT_MODIFIED, easyEditSpan);
+ text.removeSpan(easyEditSpan);
}
}
@@ -1938,6 +1955,31 @@ public class Editor {
mTextView.removeCallbacks(mHidePopup);
}
}
+
+ private void sendNotification(int textChangedType, EasyEditSpan span) {
+ try {
+ PendingIntent pendingIntent = span.getPendingIntent();
+ if (pendingIntent != null) {
+ Intent intent = new Intent();
+ intent.putExtra(EasyEditSpan.EXTRA_TEXT_CHANGED_TYPE, textChangedType);
+ pendingIntent.send(mTextView.getContext(), 0, intent);
+ }
+ } catch (CanceledException e) {
+ // This should not happen, as we should try to send the intent only once.
+ Log.w(TAG, "PendingIntent for notification cannot be sent", e);
+ }
+ }
+ }
+
+ /**
+ * Listens for the delete event triggered by {@link EasyEditPopupWindow}.
+ */
+ private interface EasyEditDeleteListener {
+
+ /**
+ * Clicks the delete pop-up.
+ */
+ void onDeleteClick(EasyEditSpan span);
}
/**
@@ -1950,6 +1992,7 @@ public class Editor {
com.android.internal.R.layout.text_edit_action_popup_text;
private TextView mDeleteTextView;
private EasyEditSpan mEasyEditSpan;
+ private EasyEditDeleteListener mOnDeleteListener;
@Override
protected void createPopupWindow() {
@@ -1984,19 +2027,29 @@ public class Editor {
mEasyEditSpan = easyEditSpan;
}
+ private void setOnDeleteListener(EasyEditDeleteListener listener) {
+ mOnDeleteListener = listener;
+ }
+
@Override
public void onClick(View view) {
- if (view == mDeleteTextView) {
- Editable editable = (Editable) mTextView.getText();
- int start = editable.getSpanStart(mEasyEditSpan);
- int end = editable.getSpanEnd(mEasyEditSpan);
- if (start >= 0 && end >= 0) {
- mTextView.deleteText_internal(start, end);
- }
+ if (view == mDeleteTextView
+ && mEasyEditSpan != null && mEasyEditSpan.isDeleteEnabled()
+ && mOnDeleteListener != null) {
+ mOnDeleteListener.onDeleteClick(mEasyEditSpan);
}
}
@Override
+ public void hide() {
+ if (mEasyEditSpan != null) {
+ mEasyEditSpan.setDeleteEnabled(false);
+ }
+ mOnDeleteListener = null;
+ super.hide();
+ }
+
+ @Override
protected int getTextOffset() {
// Place the pop-up at the end of the span
Editable editable = (Editable) mTextView.getText();