Merge "Paste popup window is displayed on the side when it would be clipped on top of screen." into honeycomb

This commit is contained in:
Gilles Debunne
2011-01-21 11:29:39 -08:00
committed by Android (Google) Code Review
10 changed files with 189 additions and 30 deletions

View File

@@ -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"

View File

@@ -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() {

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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" />

View File

@@ -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">

View File

@@ -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>