summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/app/ListActivity.java2
-rw-r--r--core/java/android/app/ListFragment.java48
-rw-r--r--core/java/android/app/LoaderManager.java2
-rw-r--r--core/java/android/appwidget/AppWidgetManager.java32
-rw-r--r--core/java/android/provider/MediaStore.java21
-rw-r--r--core/java/android/text/format/Time.java90
-rw-r--r--core/java/android/text/method/ArrowKeyMovementMethod.java44
-rw-r--r--core/java/android/view/GLES20Canvas.java26
-rw-r--r--core/java/android/webkit/BrowserFrame.java14
-rw-r--r--core/java/android/webkit/MimeTypeMap.java1
-rw-r--r--core/java/android/webkit/WebView.java50
-rw-r--r--core/java/android/webkit/WebViewCore.java20
-rw-r--r--core/java/android/widget/TextView.java605
-rw-r--r--core/res/res/drawable-hdpi/selection_end_handle.pngbin0 -> 2077 bytes
-rw-r--r--core/res/res/drawable-hdpi/selection_start_handle.pngbin0 -> 2107 bytes
-rw-r--r--core/res/res/drawable-mdpi/selection_end_handle.pngbin0 -> 1139 bytes
-rw-r--r--core/res/res/drawable-mdpi/selection_start_handle.pngbin0 -> 1199 bytes
-rw-r--r--core/res/res/layout/list_content.xml48
-rw-r--r--core/res/res/layout/list_content_rich.xml56
-rw-r--r--core/res/res/layout/list_content_simple.xml24
-rw-r--r--core/res/res/values/public.xml12
-rw-r--r--core/res/res/values/styles.xml2
22 files changed, 803 insertions, 294 deletions
diff --git a/core/java/android/app/ListActivity.java b/core/java/android/app/ListActivity.java
index 4bf5518..d49968f 100644
--- a/core/java/android/app/ListActivity.java
+++ b/core/java/android/app/ListActivity.java
@@ -309,7 +309,7 @@ public class ListActivity extends Activity {
if (mList != null) {
return;
}
- setContentView(com.android.internal.R.layout.list_content);
+ setContentView(com.android.internal.R.layout.list_content_simple);
}
diff --git a/core/java/android/app/ListFragment.java b/core/java/android/app/ListFragment.java
index 96485f7..73ef869 100644
--- a/core/java/android/app/ListFragment.java
+++ b/core/java/android/app/ListFragment.java
@@ -172,11 +172,17 @@ public class ListFragment extends Fragment {
* is {@link android.R.id#list android.R.id.list} and can optionally
* have a sibling view id {@link android.R.id#empty android.R.id.empty}
* that is to be shown when the list is empty.
+ *
+ * <p>If you are overriding this method with your own custom content,
+ * consider including the standard layout {@link android.R.layout#list_content}
+ * in your layout file, so that you continue to retain all of the standard
+ * behavior of ListFragment. In particular, this is currently the only
+ * way to have the built-in indeterminant progress state be shown.
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- return inflater.inflate(com.android.internal.R.layout.list_content_rich,
+ return inflater.inflate(com.android.internal.R.layout.list_content,
container, false);
}
@@ -217,9 +223,15 @@ public class ListFragment extends Fragment {
* Provide the cursor for the list view.
*/
public void setListAdapter(ListAdapter adapter) {
+ boolean hadAdapter = mAdapter != null;
mAdapter = adapter;
if (mList != null) {
mList.setAdapter(adapter);
+ if (!mListShown && !hadAdapter) {
+ // The list was hidden, and previously didn't have an
+ // adapter. It is now time to show it.
+ setListShown(true, getView().getWindowToken() != null);
+ }
}
}
@@ -276,12 +288,38 @@ public class ListFragment extends Fragment {
* displayed if you are waiting for the initial data to show in it. During
* this time an indeterminant progress indicator will be shown instead.
*
+ * <p>Applications do not normally need to use this themselves. The default
+ * behavior of ListFragment is to start with the list not being shown, only
+ * showing it once an adapter is given with {@link #setListAdapter(ListAdapter)}.
+ * If the list at that point had not been shown, when it does get shown
+ * it will be do without the user ever seeing the hidden state.
+ *
+ * @param shown If true, the list view is shown; if false, the progress
+ * indicator. The initial value is true.
+ */
+ public void setListShown(boolean shown) {
+ setListShown(shown, true);
+ }
+
+ /**
+ * Like {@link #setListShown(boolean)}, but no animation is used when
+ * transitioning from the previous state.
+ */
+ public void setListShownNoAnimation(boolean shown) {
+ setListShown(shown, false);
+ }
+
+ /**
+ * Control whether the list is being displayed. You can make it not
+ * displayed if you are waiting for the initial data to show in it. During
+ * this time an indeterminant progress indicator will be shown instead.
+ *
* @param shown If true, the list view is shown; if false, the progress
* indicator. The initial value is true.
* @param animate If true, an animation will be used to transition to the
* new state.
*/
- public void setListShown(boolean shown, boolean animate) {
+ private void setListShown(boolean shown, boolean animate) {
ensureList();
if (mProgressContainer == null) {
throw new IllegalStateException("Can't be used with a custom content view");
@@ -356,6 +394,12 @@ public class ListFragment extends Fragment {
mList.setOnItemClickListener(mOnClickListener);
if (mAdapter != null) {
setListAdapter(mAdapter);
+ } else {
+ // We are starting without an adapter, so assume we won't
+ // have our data right away and start with the progress indicator.
+ if (mProgressContainer != null) {
+ setListShown(false, false);
+ }
}
mHandler.post(mRequestFocus);
}
diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index 31e3c40..7600899 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -180,7 +180,7 @@ public class LoaderManager {
* will be called as the loader state changes. If at the point of call
* the caller is in its started state, and the requested loader
* already exists and has generated its data, then
- * callback.{@link LoaderCallbacks#onLoadFinished(Loader, Object)} will
+ * callback. {@link LoaderCallbacks#onLoadFinished} will
* be called immediately (inside of this function), so you must be prepared
* for this to happen.
*/
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index d4ce6a1..3f12bf9 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -22,7 +22,6 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.DisplayMetrics;
-import android.util.Log;
import android.util.TypedValue;
import android.widget.RemoteViews;
@@ -149,7 +148,7 @@ public class AppWidgetManager {
* instances as possible.</td>
* </tr>
* </table>
- *
+ *
* @see AppWidgetProvider#onUpdate AppWidgetProvider.onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
*/
public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE";
@@ -163,7 +162,7 @@ public class AppWidgetManager {
/**
* Sent when an instance of an AppWidget is removed from the last host.
- *
+ *
* @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context)
*/
public static final String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED";
@@ -172,7 +171,7 @@ public class AppWidgetManager {
* Sent when an instance of an AppWidget is added to a host for the first time.
* This broadcast is sent at boot time if there is a AppWidgetHost installed with
* an instance for this provider.
- *
+ *
* @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context)
*/
public static final String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED";
@@ -183,20 +182,21 @@ public class AppWidgetManager {
* @see AppWidgetProviderInfo
*/
public static final String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider";
-
+
/**
* Field for the manifest meta-data tag used to indicate any previous name for the
* app widget receiver.
*
* @see AppWidgetProviderInfo
- *
+ *
* @hide Pending API approval
*/
public static final String META_DATA_APPWIDGET_OLD_NAME = "android.appwidget.oldName";
- static WeakHashMap<Context, WeakReference<AppWidgetManager>> sManagerCache = new WeakHashMap();
+ static WeakHashMap<Context, WeakReference<AppWidgetManager>> sManagerCache =
+ new WeakHashMap<Context, WeakReference<AppWidgetManager>>();
static IAppWidgetService sService;
-
+
Context mContext;
private DisplayMetrics mDisplayMetrics;
@@ -219,7 +219,7 @@ public class AppWidgetManager {
}
if (result == null) {
result = new AppWidgetManager(context);
- sManagerCache.put(context, new WeakReference(result));
+ sManagerCache.put(context, new WeakReference<AppWidgetManager>(result));
}
return result;
}
@@ -292,7 +292,15 @@ public class AppWidgetManager {
*/
public List<AppWidgetProviderInfo> getInstalledProviders() {
try {
- return sService.getInstalledProviders();
+ List<AppWidgetProviderInfo> providers = sService.getInstalledProviders();
+ for (AppWidgetProviderInfo info : providers) {
+ // Converting complex to dp.
+ info.minWidth =
+ TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics);
+ info.minHeight =
+ TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics);
+ }
+ return providers;
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -310,7 +318,7 @@ public class AppWidgetManager {
AppWidgetProviderInfo info = sService.getAppWidgetInfo(appWidgetId);
if (info != null) {
// Converting complex to dp.
- info.minWidth =
+ info.minWidth =
TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics);
info.minHeight =
TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics);
@@ -344,7 +352,7 @@ public class AppWidgetManager {
/**
* Get the list of appWidgetIds that have been bound to the given AppWidget
* provider.
- *
+ *
* @param provider The {@link android.content.BroadcastReceiver} that is the
* AppWidget provider to find appWidgetIds for.
*/
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 2c4a9f5..293d31c 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -237,6 +237,14 @@ public final class MediaStore {
* <P>Type: TEXT</P>
*/
public static final String MIME_TYPE = "mime_type";
+
+ /**
+ * The MTP object handle of a newly transfered file.
+ * Used internally by the MediaScanner
+ * <P>Type: INTEGER</P>
+ * @hide
+ */
+ public static final String MTP_OBJECT_HANDLE = "mtp_object_handle";
}
@@ -274,6 +282,19 @@ public final class MediaStore {
* <P>Type: INTEGER</P>
*/
public static final String PARENT = "parent";
+
+ /**
+ * Identifier for the media table containing the object.
+ * Used internally by MediaProvider
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MEDIA_TABLE = "media_table";
+
+ /**
+ * The ID of the object in its media table.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MEDIA_ID = "media_id";
}
}
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index 8eae111..c05a8fe 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -32,7 +32,7 @@ public class Time {
private static final String Y_M_D_T_H_M_S_000 = "%Y-%m-%dT%H:%M:%S.000";
private static final String Y_M_D_T_H_M_S_000_Z = "%Y-%m-%dT%H:%M:%S.000Z";
private static final String Y_M_D = "%Y-%m-%d";
-
+
public static final String TIMEZONE_UTC = "UTC";
/**
@@ -170,11 +170,11 @@ public class Time {
public Time() {
this(TimeZone.getDefault().getID());
}
-
+
/**
* A copy constructor. Construct a Time object by copying the given
* Time object. No normalization occurs.
- *
+ *
* @param other
*/
public Time(Time other) {
@@ -185,17 +185,17 @@ public class Time {
* Ensures the values in each field are in range. For example if the
* current value of this calendar is March 32, normalize() will convert it
* to April 1. It also fills in weekDay, yearDay, isDst and gmtoff.
- *
+ *
* <p>
* If "ignoreDst" is true, then this method sets the "isDst" field to -1
* (the "unknown" value) before normalizing. It then computes the
* correct value for "isDst".
- *
+ *
* <p>
* See {@link #toMillis(boolean)} for more information about when to
* use <tt>true</tt> or <tt>false</tt> for "ignoreDst".
- *
- * @return the UTC milliseconds since the epoch
+ *
+ * @return the UTC milliseconds since the epoch
*/
native public long normalize(boolean ignoreDst);
@@ -379,13 +379,13 @@ public class Time {
* Parses a date-time string in either the RFC 2445 format or an abbreviated
* format that does not include the "time" field. For example, all of the
* following strings are valid:
- *
+ *
* <ul>
* <li>"20081013T160000Z"</li>
* <li>"20081013T160000"</li>
* <li>"20081013"</li>
* </ul>
- *
+ *
* Returns whether or not the time is in UTC (ends with Z). If the string
* ends with "Z" then the timezone is set to UTC. If the date-time string
* included only a date and no time field, then the <code>allDay</code>
@@ -396,10 +396,10 @@ public class Time {
* <code>yearDay</code>, and <code>gmtoff</code> are always set to zero,
* and the field <code>isDst</code> is set to -1 (unknown). To set those
* fields, call {@link #normalize(boolean)} after parsing.
- *
+ *
* To parse a date-time string and convert it to UTC milliseconds, do
* something like this:
- *
+ *
* <pre>
* Time time = new Time();
* String date = "20081013T160000Z";
@@ -428,25 +428,25 @@ public class Time {
* Parse a time in RFC 3339 format. This method also parses simple dates
* (that is, strings that contain no time or time offset). For example,
* all of the following strings are valid:
- *
+ *
* <ul>
* <li>"2008-10-13T16:00:00.000Z"</li>
* <li>"2008-10-13T16:00:00.000+07:00"</li>
* <li>"2008-10-13T16:00:00.000-07:00"</li>
* <li>"2008-10-13"</li>
* </ul>
- *
+ *
* <p>
* If the string contains a time and time offset, then the time offset will
* be used to convert the time value to UTC.
* </p>
- *
+ *
* <p>
* If the given string contains just a date (with no time field), then
* the {@link #allDay} field is set to true and the {@link #hour},
* {@link #minute}, and {@link #second} fields are set to zero.
* </p>
- *
+ *
* <p>
* Returns true if the resulting time value is in UTC time.
* </p>
@@ -462,7 +462,7 @@ public class Time {
}
return false;
}
-
+
native private boolean nativeParse3339(String s);
/**
@@ -484,13 +484,13 @@ public class Time {
* <em>not</em> change any of the fields in this Time object. If you want
* to normalize the fields in this Time object and also get the milliseconds
* then use {@link #normalize(boolean)}.
- *
+ *
* <p>
* If "ignoreDst" is false, then this method uses the current setting of the
* "isDst" field and will adjust the returned time if the "isDst" field is
* wrong for the given time. See the sample code below for an example of
* this.
- *
+ *
* <p>
* If "ignoreDst" is true, then this method ignores the current setting of
* the "isDst" field in this Time object and will instead figure out the
@@ -499,27 +499,27 @@ public class Time {
* correct value of the "isDst" field is when the time is inherently
* ambiguous because it falls in the hour that is repeated when switching
* from Daylight-Saving Time to Standard Time.
- *
+ *
* <p>
* Here is an example where <tt>toMillis(true)</tt> adjusts the time,
* assuming that DST changes at 2am on Sunday, Nov 4, 2007.
- *
+ *
* <pre>
* Time time = new Time();
- * time.set(2007, 10, 4); // set the date to Nov 4, 2007, 12am
+ * time.set(4, 10, 2007); // set the date to Nov 4, 2007, 12am
* time.normalize(); // this sets isDst = 1
* time.monthDay += 1; // changes the date to Nov 5, 2007, 12am
* millis = time.toMillis(false); // millis is Nov 4, 2007, 11pm
* millis = time.toMillis(true); // millis is Nov 5, 2007, 12am
* </pre>
- *
+ *
* <p>
* To avoid this problem, use <tt>toMillis(true)</tt>
* after adding or subtracting days or explicitly setting the "monthDay"
* field. On the other hand, if you are adding
* or subtracting hours or minutes, then you should use
* <tt>toMillis(false)</tt>.
- *
+ *
* <p>
* You should also use <tt>toMillis(false)</tt> if you want
* to read back the same milliseconds that you set with {@link #set(long)}
@@ -531,14 +531,14 @@ public class Time {
* Sets the fields in this Time object given the UTC milliseconds. After
* this method returns, all the fields are normalized.
* This also sets the "isDst" field to the correct value.
- *
+ *
* @param millis the time in UTC milliseconds since the epoch.
*/
native public void set(long millis);
/**
* Format according to RFC 2445 DATETIME type.
- *
+ *
* <p>
* The same as format("%Y%m%dT%H%M%S").
*/
@@ -584,7 +584,7 @@ public class Time {
* Sets the date from the given fields. Also sets allDay to true.
* Sets weekDay, yearDay and gmtoff to 0, and isDst to -1.
* Call {@link #normalize(boolean)} if you need those.
- *
+ *
* @param monthDay the day of the month (in the range [1,31])
* @param month the zero-based month number (in the range [0,11])
* @param year the year
@@ -606,7 +606,7 @@ public class Time {
/**
* Returns true if the time represented by this Time object occurs before
* the given time.
- *
+ *
* @param that a given Time object to compare against
* @return true if this time is less than the given time
*/
@@ -618,7 +618,7 @@ public class Time {
/**
* Returns true if the time represented by this Time object occurs after
* the given time.
- *
+ *
* @param that a given Time object to compare against
* @return true if this time is greater than the given time
*/
@@ -632,12 +632,12 @@ public class Time {
* closest Thursday yearDay.
*/
private static final int[] sThursdayOffset = { -3, 3, 2, 1, 0, -1, -2 };
-
+
/**
* Computes the week number according to ISO 8601. The current Time
* object must already be normalized because this method uses the
* yearDay and weekDay fields.
- *
+ *
* <p>
* In IS0 8601, weeks start on Monday.
* The first week of the year (week 1) is defined by ISO 8601 as the
@@ -645,12 +645,12 @@ public class Time {
* Or equivalently, the week containing January 4. Or equivalently,
* the week with the year's first Thursday in it.
* </p>
- *
+ *
* <p>
* The week number can be calculated by counting Thursdays. Week N
* contains the Nth Thursday of the year.
* </p>
- *
+ *
* @return the ISO week number.
*/
public int getWeekNumber() {
@@ -661,7 +661,7 @@ public class Time {
if (closestThursday >= 0 && closestThursday <= 364) {
return closestThursday / 7 + 1;
}
-
+
// The week crosses a year boundary.
Time temp = new Time(this);
temp.monthDay += sThursdayOffset[weekDay];
@@ -670,7 +670,7 @@ public class Time {
}
/**
- * Return a string in the RFC 3339 format.
+ * Return a string in the RFC 3339 format.
* <p>
* If allDay is true, expresses the time as Y-M-D</p>
* <p>
@@ -691,13 +691,13 @@ public class Time {
int offset = (int)Math.abs(gmtoff);
int minutes = (offset % 3600) / 60;
int hours = offset / 3600;
-
+
return String.format("%s%s%02d:%02d", base, sign, hours, minutes);
}
}
-
+
/**
- * Returns true if the day of the given time is the epoch on the Julian Calendar
+ * Returns true if the day of the given time is the epoch on the Julian Calendar
* (January 1, 1970 on the Gregorian calendar).
*
* @param time the time to test
@@ -707,7 +707,7 @@ public class Time {
long millis = time.toMillis(true);
return getJulianDay(millis, 0) == EPOCH_JULIAN_DAY;
}
-
+
/**
* Computes the Julian day number, given the UTC milliseconds
* and the offset (in seconds) from UTC. The Julian day for a given
@@ -716,10 +716,10 @@ public class Time {
* what timezone is being used. The Julian day is useful for testing
* if two events occur on the same day and for determining the relative
* time of an event from the present ("yesterday", "3 days ago", etc.).
- *
+ *
* <p>
* Use {@link #toMillis(boolean)} to get the milliseconds.
- *
+ *
* @param millis the time in UTC milliseconds
* @param gmtoff the offset from UTC in seconds
* @return the Julian day
@@ -729,7 +729,7 @@ public class Time {
long julianDay = (millis + offsetMillis) / DateUtils.DAY_IN_MILLIS;
return (int) julianDay + EPOCH_JULIAN_DAY;
}
-
+
/**
* <p>Sets the time from the given Julian day number, which must be based on
* the same timezone that is set in this Time object. The "gmtoff" field
@@ -738,7 +738,7 @@ public class Time {
* After this method returns all the fields will be normalized and the time
* will be set to 12am at the beginning of the given Julian day.
* </p>
- *
+ *
* <p>
* The only exception to this is if 12am does not exist for that day because
* of daylight saving time. For example, Cairo, Eqypt moves time ahead one
@@ -746,7 +746,7 @@ public class Time {
* also change daylight saving time at 12am. In those cases, the time
* will be set to 1am.
* </p>
- *
+ *
* @param julianDay the Julian day in the timezone for this Time object
* @return the UTC milliseconds for the beginning of the Julian day
*/
@@ -756,13 +756,13 @@ public class Time {
// the day.
long millis = (julianDay - EPOCH_JULIAN_DAY) * DateUtils.DAY_IN_MILLIS;
set(millis);
-
+
// Figure out how close we are to the requested Julian day.
// We can't be off by more than a day.
int approximateDay = getJulianDay(millis, gmtoff);
int diff = julianDay - approximateDay;
monthDay += diff;
-
+
// Set the time to 12am and re-normalize.
hour = 0;
minute = 0;
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index 9df63a9..55ec655 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -138,35 +138,6 @@ public class ArrowKeyMovementMethod implements MovementMethod {
}
}
- private int getOffset(int x, int y, TextView widget){
- // Converts the absolute X,Y coordinates to the character offset for the
- // character whose position is closest to the specified
- // horizontal position.
- x -= widget.getTotalPaddingLeft();
- y -= widget.getTotalPaddingTop();
-
- // Clamp the position to inside of the view.
- if (x < 0) {
- x = 0;
- } else if (x >= (widget.getWidth()-widget.getTotalPaddingRight())) {
- x = widget.getWidth()-widget.getTotalPaddingRight() - 1;
- }
- if (y < 0) {
- y = 0;
- } else if (y >= (widget.getHeight()-widget.getTotalPaddingBottom())) {
- y = widget.getHeight()-widget.getTotalPaddingBottom() - 1;
- }
-
- x += widget.getScrollX();
- y += widget.getScrollY();
-
- Layout layout = widget.getLayout();
- int line = layout.getLineForVertical(y);
-
- int offset = layout.getOffsetForHorizontal(line, x);
- return offset;
- }
-
public boolean onKeyDown(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
if (executeDown(widget, buffer, keyCode)) {
MetaKeyKeyListener.adjustMetaAfterKeypress(buffer);
@@ -263,7 +234,7 @@ public class ArrowKeyMovementMethod implements MovementMethod {
MetaKeyKeyListener.META_SELECTING) != 0);
int x = (int) event.getX();
int y = (int) event.getY();
- int offset = getOffset(x, y, widget);
+ int offset = widget.getOffset(x, y);
if (cap) {
buffer.setSpan(LAST_TAP_DOWN, offset, offset,
@@ -320,7 +291,7 @@ public class ArrowKeyMovementMethod implements MovementMethod {
// Get the current touch position
int x = (int) event.getX();
int y = (int) event.getY();
- int offset = getOffset(x, y, widget);
+ int offset = widget.getOffset(x, y);
final OnePointFiveTapState[] tap = buffer.getSpans(0, buffer.length(),
OnePointFiveTapState.class);
@@ -366,7 +337,7 @@ public class ArrowKeyMovementMethod implements MovementMethod {
int x = (int) event.getX();
int y = (int) event.getY();
- int off = getOffset(x, y, widget);
+ int off = widget.getOffset(x, y);
// XXX should do the same adjust for x as we do for the line.
@@ -442,11 +413,10 @@ public class ArrowKeyMovementMethod implements MovementMethod {
widget.cancelLongPress();
// Offset the current touch position (from controller to cursor)
- final int x = (int) event.getX() + mCursorController.getOffsetX();
- final int y = (int) event.getY() + mCursorController.getOffsetY();
- int offset = getOffset(x, y, widget);
- Selection.setSelection(buffer, offset);
- mCursorController.updatePosition();
+ final float x = event.getX() + mCursorController.getOffsetX();
+ final float y = event.getY() + mCursorController.getOffsetY();
+ int offset = widget.getOffset((int) x, (int) y);
+ mCursorController.updatePosition(offset);
return true;
case MotionEvent.ACTION_UP:
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 49ef8dc..0ad3c0b 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -45,6 +45,10 @@ class GLES20Canvas extends Canvas {
private final float[] mPoint = new float[2];
private final float[] mLine = new float[4];
+
+ private final Rect mClipBounds = new Rect();
+
+ private DrawFilter mFilter;
///////////////////////////////////////////////////////////////////////////
// Constructors
@@ -164,6 +168,7 @@ class GLES20Canvas extends Canvas {
@Override
public boolean clipRect(Rect rect, Region.Op op) {
+ // TODO: Implement
throw new UnsupportedOperationException();
}
@@ -174,6 +179,7 @@ class GLES20Canvas extends Canvas {
@Override
public boolean clipRect(RectF rect, Region.Op op) {
+ // TODO: Implement
throw new UnsupportedOperationException();
}
@@ -336,12 +342,14 @@ class GLES20Canvas extends Canvas {
@Override
public void setDrawFilter(DrawFilter filter) {
- throw new UnsupportedOperationException();
+ // Don't crash, but ignore the draw filter
+ // TODO: Implement PaintDrawFilter
+ mFilter = filter;
}
@Override
public DrawFilter getDrawFilter() {
- throw new UnsupportedOperationException();
+ return mFilter;
}
///////////////////////////////////////////////////////////////////////////
@@ -408,7 +416,11 @@ class GLES20Canvas extends Canvas {
@Override
public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
int width, int height, boolean hasAlpha, Paint paint) {
- // TODO: Implement
+ final Bitmap.Config config = hasAlpha ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
+ final Bitmap b = Bitmap.createBitmap(colors, offset, stride, width, height, config);
+ final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmap(mRenderer, b.mNativeBitmap, x, y, nativePaint);
+ b.recycle();
}
@Override
@@ -420,7 +432,7 @@ class GLES20Canvas extends Canvas {
@Override
public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
int vertOffset, int[] colors, int colorOffset, Paint paint) {
- throw new UnsupportedOperationException();
+ // TODO: Implement
}
@Override
@@ -466,7 +478,9 @@ class GLES20Canvas extends Canvas {
@Override
public void drawPaint(Paint paint) {
- // TODO: Implement
+ final Rect r = mClipBounds;
+ nGetClipBounds(mRenderer, r);
+ drawRect(r.left, r.top, r.right, r.bottom, paint);
}
@Override
@@ -591,6 +605,6 @@ class GLES20Canvas extends Canvas {
public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
int indexOffset, int indexCount, Paint paint) {
- throw new UnsupportedOperationException();
+ // TODO: Implement
}
}
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 7b1aab2..b021ded 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -301,6 +301,18 @@ class BrowserFrame extends Handler {
}
/**
+ * Saves the contents of the frame as a web archive.
+ *
+ * @param basename The filename where the archive should be placed.
+ * @param autoname If false, takes filename to be a file. If true, filename
+ * is assumed to be a directory in which a filename will be
+ * chosen according to the url of the current page.
+ */
+ /* package */ String saveWebArchive(String basename, boolean autoname) {
+ return nativeSaveWebArchive(basename, autoname);
+ }
+
+ /**
* Go back or forward the number of steps given.
* @param steps A negative or positive number indicating the direction
* and number of steps to move.
@@ -1040,5 +1052,7 @@ class BrowserFrame extends Handler {
*/
private native HashMap getFormTextData();
+ private native String nativeSaveWebArchive(String basename, boolean autoname);
+
private native void nativeOrientationChanged(int orientation);
}
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
index c1ac180..6e9c70a 100644
--- a/core/java/android/webkit/MimeTypeMap.java
+++ b/core/java/android/webkit/MimeTypeMap.java
@@ -363,6 +363,7 @@ public class MimeTypeMap {
sMimeTypeMap.loadEntry("application/x-wais-source", "src");
sMimeTypeMap.loadEntry("application/x-wingz", "wz");
sMimeTypeMap.loadEntry("application/x-webarchive", "webarchive");
+ sMimeTypeMap.loadEntry("application/x-webarchive-xml", "webarchivexml");
sMimeTypeMap.loadEntry("application/x-x509-ca-cert", "crt");
sMimeTypeMap.loadEntry("application/x-x509-user-cert", "crt");
sMimeTypeMap.loadEntry("application/x-xcf", "xcf");
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 140dd55..0c8fc79 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -590,6 +590,7 @@ public class WebView extends AbsoluteLayout
static final int SET_SCROLLBAR_MODES = 129;
static final int SELECTION_STRING_CHANGED = 130;
static final int SET_TOUCH_HIGHLIGHT_RECTS = 131;
+ static final int SAVE_WEBARCHIVE_FINISHED = 132;
private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
private static final int LAST_PACKAGE_MSG_ID = SET_TOUCH_HIGHLIGHT_RECTS;
@@ -638,7 +639,8 @@ public class WebView extends AbsoluteLayout
"REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID", // = 128;
"SET_SCROLLBAR_MODES", // = 129;
"SELECTION_STRING_CHANGED", // = 130;
- "SET_TOUCH_HIGHLIGHT_RECTS" // = 131;
+ "SET_TOUCH_HIGHLIGHT_RECTS", // = 131;
+ "SAVE_WEBARCHIVE_FINISHED" // = 132;
};
// If the site doesn't use the viewport meta tag to specify the viewport,
@@ -1520,6 +1522,45 @@ public class WebView extends AbsoluteLayout
}
/**
+ * Saves the current view as a web archive.
+ *
+ * @param filename The filename where the archive should be placed.
+ */
+ public void saveWebArchive(String filename) {
+ saveWebArchive(filename, false, null);
+ }
+
+ /* package */ static class SaveWebArchiveMessage {
+ SaveWebArchiveMessage (String basename, boolean autoname, ValueCallback<String> callback) {
+ mBasename = basename;
+ mAutoname = autoname;
+ mCallback = callback;
+ }
+
+ /* package */ final String mBasename;
+ /* package */ final boolean mAutoname;
+ /* package */ final ValueCallback<String> mCallback;
+ /* package */ String mResultFile;
+ }
+
+ /**
+ * Saves the current view as a web archive.
+ *
+ * @param basename The filename where the archive should be placed.
+ * @param autoname If false, takes basename to be a file. If true, basename
+ * is assumed to be a directory in which a filename will be
+ * chosen according to the url of the current page.
+ * @param callback Called after the web archive has been saved. The
+ * parameter for onReceiveValue will either be the filename
+ * under which the file was saved, or null if saving the
+ * file failed.
+ */
+ public void saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback) {
+ mWebViewCore.sendMessage(EventHub.SAVE_WEBARCHIVE,
+ new SaveWebArchiveMessage(basename, autoname, callback));
+ }
+
+ /**
* Stop the current load.
*/
public void stopLoading() {
@@ -6435,6 +6476,13 @@ public class WebView extends AbsoluteLayout
}
break;
+ case SAVE_WEBARCHIVE_FINISHED:
+ SaveWebArchiveMessage saveMessage = (SaveWebArchiveMessage)msg.obj;
+ if (saveMessage.mCallback != null) {
+ saveMessage.mCallback.onReceiveValue(saveMessage.mResultFile);
+ }
+ break;
+
default:
super.handleMessage(msg);
break;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index db86a0b..21af570 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -774,6 +774,7 @@ final class WebViewCore {
"ON_RESUME", // = 144
"FREE_MEMORY", // = 145
"VALID_NODE_BOUNDS", // = 146
+ "SAVE_WEBARCHIVE", // = 147
};
class EventHub {
@@ -840,6 +841,9 @@ final class WebViewCore {
static final int FREE_MEMORY = 145;
static final int VALID_NODE_BOUNDS = 146;
+ // Load and save web archives
+ static final int SAVE_WEBARCHIVE = 147;
+
// Network-based messaging
static final int CLEAR_SSL_PREF_TABLE = 150;
@@ -1300,6 +1304,15 @@ final class WebViewCore {
nativeSetJsFlags((String)msg.obj);
break;
+ case SAVE_WEBARCHIVE:
+ WebView.SaveWebArchiveMessage saveMessage =
+ (WebView.SaveWebArchiveMessage)msg.obj;
+ saveMessage.mResultFile =
+ saveWebArchive(saveMessage.mBasename, saveMessage.mAutoname);
+ mWebView.mPrivateHandler.obtainMessage(
+ WebView.SAVE_WEBARCHIVE_FINISHED, saveMessage).sendToTarget();
+ break;
+
case GEOLOCATION_PERMISSIONS_PROVIDE:
GeolocationPermissionsData data =
(GeolocationPermissionsData) msg.obj;
@@ -1601,6 +1614,13 @@ final class WebViewCore {
mBrowserFrame.loadUrl(url, extraHeaders);
}
+ private String saveWebArchive(String filename, boolean autoname) {
+ if (DebugFlags.WEB_VIEW_CORE) {
+ Log.v(LOGTAG, " CORE saveWebArchive " + filename + " " + autoname);
+ }
+ return mBrowserFrame.saveWebArchive(filename, autoname);
+ }
+
private void key(KeyEvent evt, boolean isDown) {
if (DebugFlags.WEB_VIEW_CORE) {
Log.v(LOGTAG, "CORE key at " + System.currentTimeMillis() + ", "
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f591483..a5cb151 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1133,6 +1133,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
setText(mText);
fixFocusableAndClickableSettings();
+ prepareCursorController();
}
private void fixFocusableAndClickableSettings() {
@@ -2375,8 +2376,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
int end = 0;
if (mText != null) {
- start = Selection.getSelectionStart(mText);
- end = Selection.getSelectionEnd(mText);
+ start = getSelectionStart();
+ end = getSelectionEnd();
if (start >= 0 || end >= 0) {
// Or save state if there is a selection
save = true;
@@ -2700,6 +2701,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (needEditableForNotification) {
sendAfterTextChanged((Editable) text);
}
+
+ // Depends on canSelectText, which depends on text
+ prepareCursorController();
}
/**
@@ -3617,7 +3621,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
private void invalidateCursor() {
- int where = Selection.getSelectionEnd(mText);
+ int where = getSelectionEnd();
invalidateCursor(where, where, where);
}
@@ -3693,7 +3697,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
boolean changed = false;
if (mMovement != null) {
- int curs = Selection.getSelectionEnd(mText);
+ /* This code also provides auto-scrolling when a cursor is moved using a
+ * CursorController (insertion point or selection limits).
+ * For selection, ensure start or end is visible depending on controller's state.
+ */
+ int curs = getSelectionEnd();
+ if (mSelectionModifierCursorController != null) {
+ SelectionModifierCursorController selectionController =
+ (SelectionModifierCursorController) mSelectionModifierCursorController;
+ if (selectionController.isSelectionStartDragged()) {
+ curs = getSelectionStart();
+ }
+ }
/*
* TODO: This should really only keep the end in view if
@@ -3986,8 +4001,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// XXX This is not strictly true -- a program could set the
// selection manually if it really wanted to.
if (mMovement != null && (isFocused() || isPressed())) {
- selStart = Selection.getSelectionStart(mText);
- selEnd = Selection.getSelectionEnd(mText);
+ selStart = getSelectionStart();
+ selEnd = getSelectionEnd();
if (mCursorVisible && selStart >= 0 && isEnabled()) {
if (mHighlightPath == null)
@@ -4097,6 +4112,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mInsertionPointCursorController != null) {
mInsertionPointCursorController.draw(canvas);
}
+ if (mSelectionModifierCursorController != null) {
+ mSelectionModifierCursorController.draw(canvas);
+ }
}
@Override
@@ -4511,8 +4529,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
outAttrs.hintText = mHint;
if (mText instanceof Editable) {
InputConnection ic = new EditableInputConnection(this);
- outAttrs.initialSelStart = Selection.getSelectionStart(mText);
- outAttrs.initialSelEnd = Selection.getSelectionEnd(mText);
+ outAttrs.initialSelStart = getSelectionStart();
+ outAttrs.initialSelEnd = getSelectionEnd();
outAttrs.initialCapsMode = ic.getCursorCapsMode(mInputType);
return ic;
}
@@ -4597,8 +4615,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
outText.flags |= ExtractedText.FLAG_SINGLE_LINE;
}
outText.startOffset = 0;
- outText.selectionStart = Selection.getSelectionStart(content);
- outText.selectionEnd = Selection.getSelectionEnd(content);
+ outText.selectionStart = getSelectionStart();
+ outText.selectionEnd = getSelectionEnd();
return true;
}
return false;
@@ -4777,7 +4795,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
void updateAfterEdit() {
invalidate();
- int curs = Selection.getSelectionStart(mText);
+ int curs = getSelectionStart();
if (curs >= 0 || (mGravity & Gravity.VERTICAL_GRAVITY_MASK) ==
Gravity.BOTTOM) {
@@ -4921,7 +4939,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
w, alignment, mSpacingMult, mSpacingAdd,
boring, mIncludePad);
}
- // Log.e("aaa", "Boring: " + mTransformed);
mSavedLayout = (BoringLayout) mLayout;
} else if (shouldEllipsize && boring.width <= w) {
@@ -5677,8 +5694,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (!(mText instanceof Spannable)) {
return false;
}
- int start = Selection.getSelectionStart(mText);
- int end = Selection.getSelectionEnd(mText);
+ int start = getSelectionStart();
+ int end = getSelectionEnd();
if (start != end) {
return false;
}
@@ -6522,6 +6539,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
// Don't leave us in the middle of a batch edit.
onEndBatchEdit();
+
+ if (mInsertionPointCursorController != null) {
+ mInsertionPointCursorController.hide();
+ }
+ if (mSelectionModifierCursorController != null) {
+ mSelectionModifierCursorController.hide();
+ }
}
startStopMarquee(focused);
@@ -6651,12 +6675,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
boolean handled = false;
- int oldSelStart = Selection.getSelectionStart(mText);
- int oldSelEnd = Selection.getSelectionEnd(mText);
+ int oldSelStart = getSelectionStart();
+ int oldSelEnd = getSelectionEnd();
if (mInsertionPointCursorController != null) {
mInsertionPointCursorController.onTouchEvent(event);
}
+ if (mSelectionModifierCursorController != null) {
+ mSelectionModifierCursorController.onTouchEvent(event);
+ }
if (mMovement != null) {
handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
@@ -6667,8 +6694,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
InputMethodManager imm = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- final int newSelStart = Selection.getSelectionStart(mText);
- final int newSelEnd = Selection.getSelectionEnd(mText);
+ final int newSelStart = getSelectionStart();
+ final int newSelEnd = getSelectionEnd();
CommitSelectionReceiver csr = null;
if (newSelStart != oldSelStart || newSelEnd != oldSelEnd) {
@@ -6689,9 +6716,37 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
private void prepareCursorController() {
+ boolean atLeastOneController = false;
+
// TODO Add an extra android:cursorController flag to disable the controller?
- mInsertionPointCursorController =
- mCursorVisible ? new InsertionPointCursorController() : null;
+ if (mCursorVisible) {
+ atLeastOneController = true;
+ if (mInsertionPointCursorController == null) {
+ mInsertionPointCursorController = new InsertionPointCursorController();
+ }
+ } else {
+ mInsertionPointCursorController = null;
+ }
+
+ if (canSelectText()) {
+ atLeastOneController = true;
+ if (mSelectionModifierCursorController == null) {
+ mSelectionModifierCursorController = new SelectionModifierCursorController();
+ }
+ } else {
+ mSelectionModifierCursorController = null;
+ }
+
+ if (atLeastOneController) {
+ if (sCursorControllerTempRect == null) {
+ sCursorControllerTempRect = new Rect();
+ }
+ Resources res = mContext.getResources();
+ mCursorControllerVerticalOffset = res.getDimensionPixelOffset(
+ com.android.internal.R.dimen.cursor_controller_vertical_offset);
+ } else {
+ sCursorControllerTempRect = null;
+ }
}
/**
@@ -6751,8 +6806,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
TextView tv = mView.get();
if (tv != null && tv.isFocused()) {
- int st = Selection.getSelectionStart(tv.mText);
- int en = Selection.getSelectionEnd(tv.mText);
+ int st = tv.getSelectionStart();
+ int en = tv.getSelectionEnd();
if (st == en && st >= 0 && en >= 0) {
if (tv.mLayout != null) {
@@ -6944,6 +6999,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
private boolean canSelectText() {
+ // prepareCursorController() relies on this method.
+ // If you change this condition, make sure prepareCursorController is called anywhere
+ // the value of this condition might be changed.
if (mText instanceof Spannable && mText.length() != 0 &&
mMovement != null && mMovement.canSelectArbitrarily()) {
return true;
@@ -6992,10 +7050,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
- * Returns a word to add to the dictionary from the context menu,
- * or null if there is no cursor or no word at the cursor.
+ * Returns the offsets delimiting the 'word' located at position offset.
+ *
+ * @param offset An offset in the text.
+ * @return The offsets for the start and end of the word located at <code>offset</code>.
+ * The two ints offsets are packed in a long, with the starting offset shifted by 32 bits.
+ * Returns a negative value if no valid word was found.
*/
- private String getWordForDictionary() {
+ private long getWordLimitsAt(int offset) {
/*
* Quick return if the input type is one where adding words
* to the dictionary doesn't make any sense.
@@ -7004,7 +7066,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (klass == InputType.TYPE_CLASS_NUMBER ||
klass == InputType.TYPE_CLASS_PHONE ||
klass == InputType.TYPE_CLASS_DATETIME) {
- return null;
+ return -1;
}
int variation = mInputType & InputType.TYPE_MASK_VARIATION;
@@ -7013,13 +7075,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
variation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD ||
variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS ||
variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
- return null;
+ return -1;
}
- int end = getSelectionEnd();
+ int end = offset;
if (end < 0) {
- return null;
+ return -1;
}
int start = end;
@@ -7053,6 +7115,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
+ if (start == end) {
+ return -1;
+ }
+
+ if (end - start > 48) {
+ return -1;
+ }
+
boolean hasLetter = false;
for (int i = start; i < end; i++) {
if (Character.isLetter(mTransformed.charAt(i))) {
@@ -7060,19 +7130,28 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
break;
}
}
+
if (!hasLetter) {
- return null;
+ return -1;
}
- if (start == end) {
- return null;
- }
+ // Two ints packed in a long
+ return (((long) start) << 32) | end;
+ }
- if (end - start > 48) {
+ /**
+ * Returns a word to add to the dictionary from the context menu,
+ * or null if there is no cursor or no word at the cursor.
+ */
+ private String getWordForDictionary() {
+ long wordLimits = getWordLimitsAt(getSelectionEnd());
+ if (wordLimits < 0) {
return null;
+ } else {
+ int start = (int) (wordLimits >>> 32);
+ int end = (int) (wordLimits & 0x00000000FFFFFFFFL);
+ return TextUtils.substring(mTransformed, start, end);
}
-
- return TextUtils.substring(mTransformed, start, end);
}
@Override
@@ -7372,6 +7451,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
public boolean performLongClick() {
+ // TODO This behavior should be moved to View
+ // TODO handle legacy code that added items to context menu
+ if (canSelectText()) {
+ if (startSelectionMode()) {
+ mEatTouchRelease = true;
+ return true;
+ }
+ }
+
if (super.performLongClick()) {
mEatTouchRelease = true;
return true;
@@ -7380,6 +7468,83 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return false;
}
+ private boolean startSelectionMode() {
+ if (mSelectionModifierCursorController != null) {
+ int offset = ((SelectionModifierCursorController) mSelectionModifierCursorController).
+ getTouchOffset();
+
+ int selectionStart, selectionEnd;
+
+ if (hasSelection()) {
+ selectionStart = getSelectionStart();
+ selectionEnd = getSelectionEnd();
+ if (selectionStart > selectionEnd) {
+ int tmp = selectionStart;
+ selectionStart = selectionEnd;
+ selectionEnd = tmp;
+ }
+ if ((offset >= selectionStart) && (offset <= selectionEnd)) {
+ // Long press in the current selection.
+ // Should initiate a drag. Return false, to rely on context menu for now.
+ return false;
+ }
+ }
+
+ long wordLimits = getWordLimitsAt(offset);
+ if (wordLimits >= 0) {
+ selectionStart = (int) (wordLimits >>> 32);
+ selectionEnd = (int) (wordLimits & 0x00000000FFFFFFFFL);
+ } else {
+ selectionStart = Math.max(offset - 5, 0);
+ selectionEnd = Math.min(offset + 5, mText.length());
+ }
+
+ Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
+
+ // Has to be done AFTER selection has been changed to correctly position controllers.
+ mSelectionModifierCursorController.show();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the offset character closest to the specified absolute position.
+ *
+ * @param x The horizontal absolute position of a point on screen
+ * @param y The vertical absolute position of a point on screen
+ * @return the character offset for the character whose position is closest to the specified
+ * position.
+ *
+ * @hide
+ */
+ public int getOffset(int x, int y) {
+ x -= getTotalPaddingLeft();
+ y -= getTotalPaddingTop();
+
+ // Clamp the position to inside of the view.
+ if (x < 0) {
+ x = 0;
+ } else if (x >= (getWidth() - getTotalPaddingRight())) {
+ x = getWidth()-getTotalPaddingRight() - 1;
+ }
+ if (y < 0) {
+ y = 0;
+ } else if (y >= (getHeight() - getTotalPaddingBottom())) {
+ y = getHeight()-getTotalPaddingBottom() - 1;
+ }
+
+ x += getScrollX();
+ y += getScrollY();
+
+ Layout layout = getLayout();
+ final int line = layout.getLineForVertical(y);
+ final int offset = layout.getOffsetForHorizontal(line, x);
+ return offset;
+ }
+
/**
* A CursorController instance can be used to control a cursor in the text.
*
@@ -7387,6 +7552,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* and send them to this object instead of the cursor.
*/
public interface CursorController {
+ /* Cursor fade-out animation duration, in milliseconds. */
+ static final int FADE_OUT_DURATION = 400;
+
/**
* Makes the cursor controller visible on screen. Will be drawn by {@link #draw(Canvas)}.
* See also {@link #hide()}.
@@ -7402,19 +7570,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
/**
* Update the controller's position.
*/
- public void updatePosition();
+ public void updatePosition(int offset);
/**
* The controller and the cursor's positions can be link by a fixed offset,
* computed when the controller is touched, and then maintained as it moves
* @return Horizontal offset between the controller and the cursor.
*/
- public int getOffsetX();
+ public float getOffsetX();
/**
* @return Vertical offset between the controller and the cursor.
*/
- public int getOffsetY();
+ public float getOffsetY();
/**
* This method is called by {@link #onTouchEvent(MotionEvent)} and gives the controller
@@ -7434,12 +7602,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
class InsertionPointCursorController implements CursorController {
private static final int DELAY_BEFORE_FADE_OUT = 2100;
- private static final int FADE_OUT_DURATION = 400;
// Whether or not the cursor control is currently visible
private boolean mIsVisible = false;
- // Current cursor control bounds, in content coordinates
- private final Rect mBounds = new Rect();
// Starting time of the fade timer
private long mFadeOutTimerStart;
// The cursor controller image
@@ -7447,7 +7612,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Used to detect a tap (vs drag) on the controller
private long mOnDownTimerStart;
// Offset between finger hot point on cursor controller and actual cursor
- private int mOffsetX, mOffsetY;
+ private float mOffsetX, mOffsetY;
InsertionPointCursorController() {
Resources res = mContext.getResources();
@@ -7455,10 +7620,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
public void show() {
- updatePosition();
+ updateDrawablePosition();
// Has to be done after updatePosition, so that previous position invalidate
// in only done if necessary.
mIsVisible = true;
+ if (mSelectionModifierCursorController != null) {
+ mSelectionModifierCursorController.hide();
+ }
}
public void hide() {
@@ -7467,7 +7635,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Start fading out, only if not already in progress
if (time - mFadeOutTimerStart < DELAY_BEFORE_FADE_OUT) {
mFadeOutTimerStart = time - DELAY_BEFORE_FADE_OUT;
- postInvalidate(mBounds.left, mBounds.top, mBounds.right, mBounds.bottom);
+ postInvalidate(mDrawable);
}
}
}
@@ -7476,15 +7644,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mIsVisible) {
int time = (int) (System.currentTimeMillis() - mFadeOutTimerStart);
if (time <= DELAY_BEFORE_FADE_OUT) {
- postInvalidateDelayed(DELAY_BEFORE_FADE_OUT - time,
- mBounds.left, mBounds.top, mBounds.right, mBounds.bottom);
+ postInvalidateDelayed(DELAY_BEFORE_FADE_OUT - time, mDrawable);
} else {
time -= DELAY_BEFORE_FADE_OUT;
if (time <= FADE_OUT_DURATION) {
- int alpha = 255 * (FADE_OUT_DURATION - time) / FADE_OUT_DURATION;
+ final int alpha = 255 * (FADE_OUT_DURATION - time) / FADE_OUT_DURATION;
mDrawable.setAlpha(alpha);
- postInvalidateDelayed(30,
- mBounds.left, mBounds.top, mBounds.right, mBounds.bottom);
+ postInvalidateDelayed(30, mDrawable);
} else {
mDrawable.setAlpha(0);
mIsVisible = false;
@@ -7494,113 +7660,299 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- public void updatePosition() {
+ public void updatePosition(int offset) {
+ Selection.setSelection((Spannable) mText, offset);
+ updateDrawablePosition();
+ }
+
+ private void updateDrawablePosition() {
if (mIsVisible) {
// Clear previous cursor controller before bounds are updated
- postInvalidate(mBounds.left, mBounds.top, mBounds.right, mBounds.bottom);
+ postInvalidate(mDrawable);
}
- final int offset = Selection.getSelectionStart(mText);
+ final int offset = getSelectionStart();
if (offset < 0) {
// Should never happen, safety check.
- Log.w(LOG_TAG, "Update cursor controller position called with no cursor", null);
+ Log.w(LOG_TAG, "Update cursor controller position called with no cursor");
mIsVisible = false;
return;
}
- final int cursorControllerDrawableWidth = mDrawable.getIntrinsicWidth();
- final int cursorControllerDrawableHeight = mDrawable.getIntrinsicHeight();
- final int line = mLayout.getLineForOffset(offset);
+ positionDrawableUnderCursor(offset, mDrawable);
+
+ mFadeOutTimerStart = System.currentTimeMillis();
+ mDrawable.setAlpha(255);
+ }
+
+ public void onTouchEvent(MotionEvent event) {
+ if (isFocused() && isTextEditable() && mIsVisible) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN : {
+ final float x = event.getX();
+ final float y = event.getY();
+
+ if (fingerIsOnDrawable(x, y, mDrawable)) {
+ show();
+
+ if (mMovement instanceof ArrowKeyMovementMethod) {
+ ((ArrowKeyMovementMethod)mMovement).setCursorController(this);
+ }
+
+ if (mParent != null) {
+ // Prevent possible scrollView parent from scrolling, so that
+ // we can use auto-scrolling.
+ mParent.requestDisallowInterceptTouchEvent(true);
+
+ final Rect bounds = mDrawable.getBounds();
+ mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
+ mOffsetY = bounds.top - mCursorControllerVerticalOffset - y;
+
+ mOnDownTimerStart = System.currentTimeMillis();
+ }
+ }
+ break;
+ }
+
+ case MotionEvent.ACTION_UP : {
+ int time = (int) (System.currentTimeMillis() - mOnDownTimerStart);
+
+ if (time <= ViewConfiguration.getTapTimeout()) {
+ // A tap on the controller is not grabbed, move the cursor instead
+ int offset = getOffset((int) event.getX(), (int) event.getY());
+ Selection.setSelection((Spannable) mText, offset);
+
+ // Modified by cancelLongPress and prevents the cursor from changing
+ mScrolled = false;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ public float getOffsetX() {
+ return mOffsetX;
+ }
+
+ public float getOffsetY() {
+ return mOffsetY;
+ }
+ }
+
+ class SelectionModifierCursorController implements CursorController {
+ // Whether or not the selection controls are currently visible
+ private boolean mIsVisible = false;
+ // Whether that start or the end of selection controller is dragged
+ private boolean mStartIsDragged = false;
+ // Starting time of the fade timer
+ private long mFadeOutTimerStart;
+ // The cursor controller images
+ private final Drawable mStartDrawable, mEndDrawable;
+ // Offset between finger hot point on active cursor controller and actual cursor
+ private float mOffsetX, mOffsetY;
+ // The offset of that last touch down event. Remembered to start selection there.
+ private int mTouchOffset;
+
+ SelectionModifierCursorController() {
+ Resources res = mContext.getResources();
+ mStartDrawable = res.getDrawable(com.android.internal.R.drawable.selection_start_handle);
+ mEndDrawable = res.getDrawable(com.android.internal.R.drawable.selection_end_handle);
+ }
- mBounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - 0.5 -
- cursorControllerDrawableWidth / 2.0);
- mBounds.top = mLayout.getLineTop(line + 1);
+ public void show() {
+ updateDrawablesPositions();
+ // Has to be done after updatePosition, so that previous position invalidate
+ // in only done if necessary.
+ mIsVisible = true;
+ mFadeOutTimerStart = -1;
+ if (mInsertionPointCursorController != null) {
+ mInsertionPointCursorController.hide();
+ }
+ }
- // Move cursor controller a little bit up when editing the last line of text
- // (or a single line) so that it is visible and easier to grab.
- if (line == mLayout.getLineCount() - 1) {
- mBounds.top -= Math.max(0,
- cursorControllerDrawableHeight / 2 - getExtendedPaddingBottom());
+ public void hide() {
+ if (mIsVisible && (mFadeOutTimerStart < 0)) {
+ mFadeOutTimerStart = System.currentTimeMillis();
+ postInvalidate(mStartDrawable);
+ postInvalidate(mEndDrawable);
}
+ }
- mBounds.right = mBounds.left + cursorControllerDrawableWidth;
- mBounds.bottom = mBounds.top + cursorControllerDrawableHeight;
+ public void draw(Canvas canvas) {
+ if (mIsVisible) {
+ if (mFadeOutTimerStart >= 0) {
+ int time = (int) (System.currentTimeMillis() - mFadeOutTimerStart);
+ if (time <= FADE_OUT_DURATION) {
+ final int alpha = 255 * (FADE_OUT_DURATION - time) / FADE_OUT_DURATION;
+ mStartDrawable.setAlpha(alpha);
+ mEndDrawable.setAlpha(alpha);
+ postInvalidateDelayed(30, mStartDrawable);
+ postInvalidateDelayed(30, mEndDrawable);
+ } else {
+ mStartDrawable.setAlpha(0);
+ mEndDrawable.setAlpha(0);
+ mIsVisible = false;
+ }
+ }
+ mStartDrawable.draw(canvas);
+ mEndDrawable.draw(canvas);
+ }
+ }
- convertFromViewportToContentCoordinates(mBounds);
- mDrawable.setBounds(mBounds);
+ public void updatePosition(int offset) {
+ int selectionStart = getSelectionStart();
+ int selectionEnd = getSelectionEnd();
- mFadeOutTimerStart = System.currentTimeMillis();
- mDrawable.setAlpha(255);
+ // Handle the case where start and end are swapped, making sure start <= end
+ if (mStartIsDragged) {
+ if (offset <= selectionEnd) {
+ selectionStart = offset;
+ } else {
+ selectionStart = selectionEnd;
+ selectionEnd = offset;
+ mStartIsDragged = false;
+ }
+ } else {
+ if (offset >= selectionStart) {
+ selectionEnd = offset;
+ } else {
+ selectionEnd = selectionStart;
+ selectionStart = offset;
+ mStartIsDragged = true;
+ }
+ }
- postInvalidate(mBounds.left, mBounds.top, mBounds.right, mBounds.bottom);
+ Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
+ updateDrawablesPositions();
}
- public void onTouchEvent(MotionEvent event) {
- if (isFocused() && isTextEditable()) {
- if (event.getActionMasked() == MotionEvent.ACTION_DOWN && mIsVisible) {
- final int x = (int) event.getX();
- final int y = (int) event.getY();
-
- // Simulate a 'fat finger' to ease grabbing of the controller.
- // Expand according to controller image size instead of using density.
- // Assume controller imager has a sensible size, proportionnal to density.
- final int cursorControllerDrawableWidth = mDrawable.getIntrinsicWidth();
- final int cursorControllerDrawableHeight = mDrawable.getIntrinsicHeight();
- final Rect fingerRect = new Rect(
- x - cursorControllerDrawableWidth / 2,
- y - cursorControllerDrawableHeight,
- x + cursorControllerDrawableWidth / 2,
- y);
-
- if (Rect.intersects(mBounds, fingerRect)) {
- show();
-
- if (mMovement instanceof ArrowKeyMovementMethod) {
- ((ArrowKeyMovementMethod)mMovement).setCursorController(this);
- }
+ private void updateDrawablesPositions() {
+ if (mIsVisible) {
+ // Clear previous cursor controller before bounds are updated
+ postInvalidate(mStartDrawable);
+ postInvalidate(mEndDrawable);
+ }
+
+ final int selectionStart = getSelectionStart();
+ final int selectionEnd = getSelectionEnd();
+
+ if ((selectionStart < 0) || (selectionEnd < 0)) {
+ // Should never happen, safety check.
+ Log.w(LOG_TAG, "Update selection controller position called with no cursor");
+ mIsVisible = false;
+ return;
+ }
+
+ positionDrawableUnderCursor(selectionStart, mStartDrawable);
+ positionDrawableUnderCursor(selectionEnd, mEndDrawable);
- if (mParent != null) {
- // Prevent possible scrollView parent from scrolling, so that
- // we can use auto-scrolling.
- mParent.requestDisallowInterceptTouchEvent(true);
+ mStartDrawable.setAlpha(255);
+ mEndDrawable.setAlpha(255);
+ }
- Resources res = mContext.getResources();
- final int verticalOffset = res.getDimensionPixelOffset(
- com.android.internal.R.dimen.cursor_controller_vertical_offset);
+ public void onTouchEvent(MotionEvent event) {
+ if (isFocused() && isTextEditable() &&
+ (event.getActionMasked() == MotionEvent.ACTION_DOWN)) {
+ final int x = (int) event.getX();
+ final int y = (int) event.getY();
+
+ // Remember finger down position, to be able to start selection on that point
+ mTouchOffset = getOffset(x, y);
+
+ if (mIsVisible) {
+ if (mMovement instanceof ArrowKeyMovementMethod) {
+ boolean isOnStart = fingerIsOnDrawable(x, y, mStartDrawable);
+ boolean isOnEnd = fingerIsOnDrawable(x, y, mEndDrawable);
+ if (isOnStart || isOnEnd) {
+ if (mParent != null) {
+ // Prevent possible scrollView parent from scrolling, so that
+ // we can use auto-scrolling.
+ mParent.requestDisallowInterceptTouchEvent(true);
+ }
- mOffsetX = (mBounds.left + mBounds.right) / 2 - x;
- mOffsetY = mBounds.top - verticalOffset - y;
+ // Start handle will be dragged in case BOTH controller are under finger
+ mStartIsDragged = isOnStart;
+ final Rect bounds =
+ (mStartIsDragged ? mStartDrawable : mEndDrawable).getBounds();
+ mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
+ mOffsetY = bounds.top - mCursorControllerVerticalOffset - y;
- mOnDownTimerStart = System.currentTimeMillis();
+ ((ArrowKeyMovementMethod)mMovement).setCursorController(this);
}
}
- } else if (event.getActionMasked() == MotionEvent.ACTION_UP) {
- int time = (int) (System.currentTimeMillis() - mOnDownTimerStart);
-
- if (mIsVisible && (time <= ViewConfiguration.getTapTimeout())) {
- // A tap on the controller is not grabbed, move the cursor instead
- final int x = (int) event.getX();
- final int y = (int) event.getY();
-
- Layout layout = getLayout();
- int line = layout.getLineForVertical(y);
- int offset = layout.getOffsetForHorizontal(line, x);
- Selection.setSelection((Spannable) mText, offset);
- // Modified by cancelLongPress and prevents the cursor from changing
- mScrolled = false;
- }
}
}
}
- public int getOffsetX() {
+ public int getTouchOffset() {
+ return mTouchOffset;
+ }
+
+ public float getOffsetX() {
return mOffsetX;
}
- public int getOffsetY() {
+ public float getOffsetY() {
return mOffsetY;
}
+
+ /**
+ * @return true iff this controller is currently used to move the selection start.
+ */
+ public boolean isSelectionStartDragged() {
+ return mIsVisible && mStartIsDragged;
+ }
+ }
+
+ // Helper methods used by CursorController implementations
+
+ private void positionDrawableUnderCursor(final int offset, Drawable drawable) {
+ final int drawableWidth = drawable.getIntrinsicWidth();
+ final int drawableHeight = drawable.getIntrinsicHeight();
+ final int line = mLayout.getLineForOffset(offset);
+
+ final Rect bounds = sCursorControllerTempRect;
+ bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - 0.5 - drawableWidth / 2.0);
+ bounds.top = mLayout.getLineTop(line + 1);
+
+ // Move cursor controller a little bit up when editing the last line of text
+ // (or a single line) so that it is visible and easier to grab.
+ if (line == mLayout.getLineCount() - 1) {
+ bounds.top -= Math.max(0, drawableHeight / 2 - getExtendedPaddingBottom());
+ }
+
+ bounds.right = bounds.left + drawableWidth;
+ bounds.bottom = bounds.top + drawableHeight;
+
+ convertFromViewportToContentCoordinates(bounds);
+ drawable.setBounds(bounds);
+ postInvalidate(bounds.left, bounds.top, bounds.right, bounds.bottom);
+ }
+
+ private boolean fingerIsOnDrawable(float x, float y, Drawable drawable) {
+ // Simulate a 'fat finger' to ease grabbing of the controller.
+ // Expands according to controller image size instead of using density.
+ // Assumes controller imager has a sensible size, proportionnal to density.
+ final int drawableWidth = drawable.getIntrinsicWidth();
+ final int drawableHeight = drawable.getIntrinsicHeight();
+ final Rect fingerRect = sCursorControllerTempRect;
+ fingerRect.set((int) (x - drawableWidth / 2.0),
+ (int) (y - drawableHeight),
+ (int) (x + drawableWidth / 2.0),
+ (int) y);
+ return Rect.intersects(drawable.getBounds(), fingerRect);
+ }
+
+ private void postInvalidate(Drawable drawable) {
+ final Rect bounds = drawable.getBounds();
+ postInvalidate(bounds.left, bounds.top, bounds.right, bounds.bottom);
+ }
+
+ private void postInvalidateDelayed(long delay, Drawable drawable) {
+ final Rect bounds = drawable.getBounds();
+ postInvalidateDelayed(delay, bounds.left, bounds.top, bounds.right, bounds.bottom);
}
@ViewDebug.ExportedProperty
@@ -7624,15 +7976,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private final TextPaint mTextPaint;
private boolean mUserSetTextScaleX;
private final Paint mHighlightPaint;
- private int mHighlightColor = 0xFFBBDDFF;
+ private int mHighlightColor = 0xD077A14B;
private Layout mLayout;
private long mShowCursor;
private Blink mBlink;
private boolean mCursorVisible = true;
- // Cursor Controller. Null when disabled.
+ // Cursor Controllers. Null when disabled.
private CursorController mInsertionPointCursorController;
+ private CursorController mSelectionModifierCursorController;
+ // Stored once and for all.
+ private int mCursorControllerVerticalOffset;
+ // Created once and shared by different CursorController helper methods.
+ private static Rect sCursorControllerTempRect;
private boolean mSelectAllOnFocus = false;
diff --git a/core/res/res/drawable-hdpi/selection_end_handle.png b/core/res/res/drawable-hdpi/selection_end_handle.png
new file mode 100644
index 0000000..624ab58
--- /dev/null
+++ b/core/res/res/drawable-hdpi/selection_end_handle.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/selection_start_handle.png b/core/res/res/drawable-hdpi/selection_start_handle.png
new file mode 100644
index 0000000..7d6f24c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/selection_start_handle.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/selection_end_handle.png b/core/res/res/drawable-mdpi/selection_end_handle.png
new file mode 100644
index 0000000..7e075eb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/selection_end_handle.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/selection_start_handle.png b/core/res/res/drawable-mdpi/selection_start_handle.png
new file mode 100644
index 0000000..d8022f7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/selection_start_handle.png
Binary files differ
diff --git a/core/res/res/layout/list_content.xml b/core/res/res/layout/list_content.xml
index 6f9f1e0..1414032 100644
--- a/core/res/res/layout/list_content.xml
+++ b/core/res/res/layout/list_content.xml
@@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-/* //device/apps/common/assets/res/layout/list_content.xml
-**
-** Copyright 2006, The Android Open Source Project
+/* Copyright 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.
@@ -17,8 +15,42 @@
** limitations under the License.
*/
-->
-<ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:drawSelectorOnTop="false"
- />
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout android:id="@+id/progressContainer"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ android:gravity="center">
+
+ <ProgressBar style="?android:attr/progressBarStyleLarge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:text="@string/loading"
+ android:paddingTop="4dip"
+ android:singleLine="true" />
+
+ </LinearLayout>
+
+ <FrameLayout android:id="@+id/listContainer"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ListView android:id="@android:id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:drawSelectorOnTop="false" />
+ <TextView android:id="@+android:id/internalEmpty"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+ </FrameLayout>
+
+</FrameLayout>
diff --git a/core/res/res/layout/list_content_rich.xml b/core/res/res/layout/list_content_rich.xml
deleted file mode 100644
index 1414032..0000000
--- a/core/res/res/layout/list_content_rich.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* Copyright 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.
-*/
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout android:id="@+id/progressContainer"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone"
- android:gravity="center">
-
- <ProgressBar style="?android:attr/progressBarStyleLarge"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:text="@string/loading"
- android:paddingTop="4dip"
- android:singleLine="true" />
-
- </LinearLayout>
-
- <FrameLayout android:id="@+id/listContainer"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <ListView android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:drawSelectorOnTop="false" />
- <TextView android:id="@+android:id/internalEmpty"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:textAppearance="?android:attr/textAppearanceLarge" />
- </FrameLayout>
-
-</FrameLayout>
diff --git a/core/res/res/layout/list_content_simple.xml b/core/res/res/layout/list_content_simple.xml
new file mode 100644
index 0000000..6f9f1e0
--- /dev/null
+++ b/core/res/res/layout/list_content_simple.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/layout/list_content.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:drawSelectorOnTop="false"
+ />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 8b9a4ae..d0be554 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -869,8 +869,11 @@
<public type="drawable" name="stat_sys_download" id="0x01080081" />
<public type="drawable" name="stat_sys_download_done" id="0x01080082" />
<public type="drawable" name="stat_sys_headset" id="0x01080083" />
+ <!-- @deprecated Replaced by a private asset in the phone app. -->
<public type="drawable" name="stat_sys_phone_call" id="0x01080084" />
+ <!-- @deprecated Replaced by a private asset in the phone app. -->
<public type="drawable" name="stat_sys_phone_call_forward" id="0x01080085" />
+ <!-- @deprecated Replaced by a private asset in the phone app. -->
<public type="drawable" name="stat_sys_phone_call_on_hold" id="0x01080086" />
<public type="drawable" name="stat_sys_speakerphone" id="0x01080087" />
<public type="drawable" name="stat_sys_upload" id="0x01080088" />
@@ -1132,7 +1135,9 @@
<public type="style" name="Widget.ProgressBar.Large.Inverse" id="0x0103005c" />
<public type="style" name="Widget.ProgressBar.Small.Inverse" id="0x0103005d" />
+ <!-- @deprecated Replaced by a private asset in the phone app. -->
<public type="drawable" name="stat_sys_vp_phone_call" id="0x010800a7" />
+ <!-- @deprecated Replaced by a private asset in the phone app. -->
<public type="drawable" name="stat_sys_vp_phone_call_on_hold" id="0x010800a8" />
<public type="anim" name="anticipate_interpolator" id="0x010a0007" />
@@ -1310,4 +1315,11 @@
<public type="style" name="Widget.Spinner.DropDown" />
<public type="style" name="Widget.ActionButton" />
+ <!-- Standard content view for a {@link android.app.ListFragment}.
+ If you are implementing a subclass of ListFragment with your
+ own customized content, you can include this layout in that
+ content to still retain all of the standard functionality of
+ the base class. -->
+ <public type="layout" name="list_content" />
+
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 449b56c..3c09a89 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -626,7 +626,7 @@
<style name="TextAppearance">
<item name="android:textColor">?textColorPrimary</item>
- <item name="android:textColorHighlight">#FFFF9200</item>
+ <item name="android:textColorHighlight">#D077A14B</item>
<item name="android:textColorHint">?textColorHint</item>
<item name="android:textColorLink">#5C5CFF</item>
<item name="android:textSize">16sp</item>