diff options
| -rw-r--r-- | api/current.xml | 22 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 104 | ||||
| -rw-r--r-- | core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png | bin | 0 -> 892 bytes | |||
| -rw-r--r-- | core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png | bin | 0 -> 426 bytes | |||
| -rw-r--r-- | core/res/res/layout/text_edit_side_no_paste_window.xml | 38 | ||||
| -rw-r--r-- | core/res/res/layout/text_edit_side_paste_window.xml | 38 | ||||
| -rwxr-xr-x | core/res/res/values/attrs.xml | 11 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 2 | ||||
| -rw-r--r-- | core/res/res/values/styles.xml | 2 | ||||
| -rw-r--r-- | core/res/res/values/themes.xml | 2 |
10 files changed, 189 insertions, 30 deletions
diff --git a/api/current.xml b/api/current.xml index 52d48b63a0ac..8655ad32f8fd 100644 --- a/api/current.xml +++ b/api/current.xml @@ -9926,6 +9926,28 @@ visibility="public" > </field> +<field name="textEditSideNoPasteWindowLayout" + type="int" + transient="false" + volatile="false" + value="16843615" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="textEditSidePasteWindowLayout" + type="int" + transient="false" + volatile="false" + value="16843614" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="textFilterEnabled" type="int" transient="false" diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index d09e52f7ba8b..fad0a4f43d48 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -307,8 +307,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int mTextSelectHandleLeftRes; int mTextSelectHandleRightRes; int mTextSelectHandleRes; - int mTextEditPasteWindowLayout; - int mTextEditNoPasteWindowLayout; + int mTextEditPasteWindowLayout, mTextEditSidePasteWindowLayout; + int mTextEditNoPasteWindowLayout, mTextEditSideNoPasteWindowLayout; Drawable mSelectHandleLeft; Drawable mSelectHandleRight; @@ -762,6 +762,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mTextEditNoPasteWindowLayout = a.getResourceId(attr, 0); break; + case com.android.internal.R.styleable.TextView_textEditSidePasteWindowLayout: + mTextEditSidePasteWindowLayout = a.getResourceId(attr, 0); + break; + + case com.android.internal.R.styleable.TextView_textEditSideNoPasteWindowLayout: + mTextEditSideNoPasteWindowLayout = a.getResourceId(attr, 0); + break; + case com.android.internal.R.styleable.TextView_textIsSelectable: mTextIsSelectable = a.getBoolean(attr, false); break; @@ -8422,8 +8430,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private final PopupWindow mContainer; private int mPositionX; private int mPositionY; - private View mPasteView, mNoPasteView; - + private final View[] mPasteViews = new View[4]; + private final int[] mPasteViewLayouts = new int[] { + mTextEditPasteWindowLayout, mTextEditNoPasteWindowLayout, + mTextEditSidePasteWindowLayout, mTextEditSideNoPasteWindowLayout }; + public PastePopupMenu() { mContainer = new PopupWindow(TextView.this.mContext, null, com.android.internal.R.attr.textSelectHandleWindowStyle); @@ -8435,12 +8446,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mContainer.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); } - private void updateContent() { - View view = canPaste() ? mPasteView : mNoPasteView; + private int viewIndex(boolean onTop) { + return (onTop ? 0 : 1<<1) + (canPaste() ? 0 : 1<<0); + } + + private void updateContent(boolean onTop) { + final int viewIndex = viewIndex(onTop); + View view = mPasteViews[viewIndex]; if (view == null) { - final int layout = canPaste() ? mTextEditPasteWindowLayout : - mTextEditNoPasteWindowLayout; + final int layout = mPasteViewLayouts[viewIndex]; LayoutInflater inflater = (LayoutInflater)TextView.this.mContext. getSystemService(Context.LAYOUT_INFLATER_SERVICE); if (inflater != null) { @@ -8457,26 +8472,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener view.measure(size, size); view.setOnClickListener(this); - - if (canPaste()) mPasteView = view; - else mNoPasteView = view; + + mPasteViews[viewIndex] = view; } mContainer.setContentView(view); } public void show() { - updateContent(); - final int[] coords = mTempCoords; - TextView.this.getLocationInWindow(coords); + updateContent(true); positionAtCursor(); - coords[0] += mPositionX; - coords[1] += mPositionY; - coords[0] = Math.max(0, coords[0]); - final int screenWidth = mContext.getResources().getDisplayMetrics().widthPixels; - coords[0] = Math.min(screenWidth - mContainer.getContentView().getMeasuredWidth(), - coords[0]); - mContainer.showAtLocation(TextView.this, Gravity.NO_GRAVITY, coords[0], coords[1]); } public void hide() { @@ -8496,15 +8501,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } void positionAtCursor() { - final int offset = TextView.this.getSelectionStart(); View contentView = mContainer.getContentView(); - final int width = contentView.getMeasuredWidth(); - final int height = contentView.getMeasuredHeight(); + int width = contentView.getMeasuredWidth(); + int height = contentView.getMeasuredHeight(); + final int offset = TextView.this.getSelectionStart(); final int line = mLayout.getLineForOffset(offset); final int lineTop = mLayout.getLineTop(line); + float primaryHorizontal = mLayout.getPrimaryHorizontal(offset); final Rect bounds = sCursorControllerTempRect; - bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - width / 2.0f); + bounds.left = (int) (primaryHorizontal - width / 2.0f); bounds.top = lineTop - height; bounds.right = bounds.left + width; @@ -8514,6 +8520,44 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mPositionX = bounds.left; mPositionY = bounds.top; + + + final int[] coords = mTempCoords; + TextView.this.getLocationInWindow(coords); + coords[0] += mPositionX; + coords[1] += mPositionY; + + final int screenWidth = mContext.getResources().getDisplayMetrics().widthPixels; + if (coords[1] < 0) { + updateContent(false); + // Update dimensions from new view + contentView = mContainer.getContentView(); + width = contentView.getMeasuredWidth(); + height = contentView.getMeasuredHeight(); + + // Vertical clipping, move under edited line and to the side of insertion cursor + // TODO bottom clipping in case there is no system bar + coords[1] += height; + final int lineBottom = mLayout.getLineBottom(line); + final int lineHeight = lineBottom - lineTop; + coords[1] += lineHeight; + + // Move to right hand side of insertion cursor by default. TODO RTL text. + final Drawable handle = mContext.getResources().getDrawable(mTextSelectHandleRes); + final int handleHalfWidth = handle.getIntrinsicWidth() / 2; + + if (primaryHorizontal + handleHalfWidth + width < screenWidth) { + coords[0] += handleHalfWidth + width / 2; + } else { + coords[0] -= handleHalfWidth + width / 2; + } + } else { + // Horizontal clipping + coords[0] = Math.max(0, coords[0]); + coords[0] = Math.min(screenWidth - width, coords[0]); + } + + mContainer.showAtLocation(TextView.this, Gravity.NO_GRAVITY, coords[0], coords[1]); } } @@ -8915,11 +8959,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener hideDelayed(); getHandle().show(); removePastePopupCallback(); - if (canPaste()) { - final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime; - if (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION) { - delayBeforePaste = 0; - } + final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime; + if (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION) { + delayBeforePaste = 0; + } + if (delayBeforePaste == 0 || canPaste()) { if (mPastePopupShower == null) { mPastePopupShower = new Runnable() { public void run() { diff --git a/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png b/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png Binary files differnew file mode 100644 index 000000000000..7cd000bfd47d --- /dev/null +++ b/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png diff --git a/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png b/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png Binary files differnew file mode 100644 index 000000000000..d87c35b85bdd --- /dev/null +++ b/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png diff --git a/core/res/res/layout/text_edit_side_no_paste_window.xml b/core/res/res/layout/text_edit_side_no_paste_window.xml new file mode 100644 index 000000000000..0ed384979ecd --- /dev/null +++ b/core/res/res/layout/text_edit_side_no_paste_window.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + <TextView android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingLeft="16dip" + android:paddingRight="16dip" + android:paddingTop="8dip" + android:paddingBottom="8dip" + android:drawableLeft="@android:drawable/ic_menu_paste_dark" + android:drawablePadding="8dip" + android:gravity="center" + android:textAppearance="?android:attr/textAppearanceMediumInverse" + android:textColor="@android:color/dim_foreground_dark_inverse_disabled" + android:background="@android:drawable/text_edit_side_paste_window" + android:text="@android:string/pasteDisabled" + android:layout_marginBottom="12dip" + /> + +</LinearLayout> diff --git a/core/res/res/layout/text_edit_side_paste_window.xml b/core/res/res/layout/text_edit_side_paste_window.xml new file mode 100644 index 000000000000..689a0392a8fe --- /dev/null +++ b/core/res/res/layout/text_edit_side_paste_window.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + <TextView android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingLeft="16dip" + android:paddingRight="16dip" + android:paddingTop="8dip" + android:paddingBottom="8dip" + android:drawableLeft="@android:drawable/ic_menu_paste_light" + android:drawablePadding="8dip" + android:gravity="center" + android:textAppearance="?android:attr/textAppearanceMediumInverse" + android:textColor="@android:color/black" + android:background="@android:drawable/text_edit_side_paste_window" + android:text="@android:string/paste" + android:layout_marginBottom="12dip" + /> + +</LinearLayout> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index fbd5b5e81234..e76692ad3ee0 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -649,6 +649,11 @@ <attr name="textEditPasteWindowLayout" format="reference" /> <!-- Variation of textEditPasteWindowLayout displayed when the clipboard is empty. --> <attr name="textEditNoPasteWindowLayout" format="reference" /> + <!-- Used instead of textEditPasteWindowLayout when the window is moved on the side of the + insertion cursor because it would be clipped if it were positioned on top. --> + <attr name="textEditSidePasteWindowLayout" format="reference" /> + <!-- Variation of textEditSidePasteWindowLayout displayed when the clipboard is empty. --> + <attr name="textEditSideNoPasteWindowLayout" format="reference" /> <!-- Theme to use for dialogs spawned from this theme. --> <attr name="dialogTheme" format="reference" /> @@ -2741,6 +2746,12 @@ <attr name="textEditPasteWindowLayout" /> <!-- Variation of textEditPasteWindowLayout displayed when the clipboard is empty. --> <attr name="textEditNoPasteWindowLayout" /> + <!-- Used instead of textEditPasteWindowLayout when the window is moved on the side of the + insertion cursor because it would be clipped if it were positioned on top. --> + <attr name="textEditSidePasteWindowLayout" /> + <!-- Variation of textEditSidePasteWindowLayout displayed when the clipboard is empty. --> + <attr name="textEditSideNoPasteWindowLayout" /> + <!-- Indicates that the content of a non-editable text can be selected. --> <attr name="textIsSelectable" /> </declare-styleable> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 786c4d080acf..e6552dfcea8b 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1633,6 +1633,8 @@ <public type="style" name="Widget.Holo.Light.CalendarView" /> <public type="style" name="Widget.DatePicker" /> <public type="style" name="Widget.Holo.DatePicker" /> + <public type="attr" name="textEditSidePasteWindowLayout" /> + <public type="attr" name="textEditSideNoPasteWindowLayout" /> <public type="string" name="selectTextMode" /> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 939e9ef10063..2c627309c880 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -419,6 +419,8 @@ <item name="android:textSelectHandle">?android:attr/textSelectHandle</item> <item name="android:textEditPasteWindowLayout">?android:attr/textEditPasteWindowLayout</item> <item name="android:textEditNoPasteWindowLayout">?android:attr/textEditNoPasteWindowLayout</item> + <item name="android:textEditSidePasteWindowLayout">?android:attr/textEditSidePasteWindowLayout</item> + <item name="android:textEditSideNoPasteWindowLayout">?android:attr/textEditSideNoPasteWindowLayout</item> </style> <style name="Widget.TextView.ListSeparator"> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 2f8cffcb3505..e6e23aa06044 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -174,6 +174,8 @@ <item name="textSelectHandleWindowStyle">@android:style/Widget.TextSelectHandle</item> <item name="textEditPasteWindowLayout">@android:layout/text_edit_paste_window</item> <item name="textEditNoPasteWindowLayout">@android:layout/text_edit_no_paste_window</item> + <item name="textEditSidePasteWindowLayout">@android:layout/text_edit_side_paste_window</item> + <item name="textEditSideNoPasteWindowLayout">@android:layout/text_edit_side_no_paste_window</item> <!-- Widget styles --> <item name="absListViewStyle">@android:style/Widget.AbsListView</item> |