summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/accounts/AccountManager.java2
-rw-r--r--core/java/android/speech/tts/SynthesisCallback.java5
-rwxr-xr-xcore/java/android/speech/tts/TextToSpeech.java35
-rw-r--r--core/java/android/text/method/DigitsKeyListener.java39
-rw-r--r--core/java/android/text/style/SuggestionSpan.java49
-rwxr-xr-xcore/java/android/util/PropertyValueModel.java143
-rwxr-xr-xcore/java/android/util/ValueModel.java74
-rw-r--r--core/java/android/view/View.java83
-rw-r--r--core/java/android/view/ViewGroup.java197
-rw-r--r--core/java/android/view/ViewRootImpl.java58
-rw-r--r--core/java/android/webkit/EventLogTags.logtags1
-rw-r--r--core/java/android/webkit/WebSettings.java35
-rw-r--r--core/java/android/webkit/WebSettingsClassic.java4
-rw-r--r--core/java/android/webkit/WebView.java6
-rw-r--r--core/java/android/webkit/WebViewClassic.java5
-rw-r--r--core/java/android/webkit/WebViewProvider.java2
-rw-r--r--core/java/android/widget/CheckBox.java23
-rw-r--r--core/java/android/widget/EditText.java23
-rw-r--r--core/java/android/widget/Editor.java13
-rw-r--r--core/java/android/widget/GridLayout.java77
-rw-r--r--core/java/android/widget/ImageView.java13
-rw-r--r--core/java/android/widget/LinearLayout.java28
-rw-r--r--core/java/android/widget/RelativeLayout.java22
-rw-r--r--core/java/android/widget/SeekBar.java20
-rw-r--r--core/java/android/widget/TableLayout.java2
-rw-r--r--core/java/android/widget/TableRow.java2
-rw-r--r--core/java/android/widget/TextView.java33
-rwxr-xr-xcore/java/android/widget/ValueEditor.java53
28 files changed, 864 insertions, 183 deletions
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index f3c6566..0df2949 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -1824,7 +1824,7 @@ public class AccountManager {
* Returns an intent to an {@link Activity} that prompts the user to choose from a list of
* accounts.
* The caller will then typically start the activity by calling
- * <code>startActivityWithResult(intent, ...);</code>.
+ * <code>startActivityForResult(intent, ...);</code>.
* <p>
* On success the activity returns a Bundle with the account name and type specified using
* keys {@link #KEY_ACCOUNT_NAME} and {@link #KEY_ACCOUNT_TYPE}.
diff --git a/core/java/android/speech/tts/SynthesisCallback.java b/core/java/android/speech/tts/SynthesisCallback.java
index d70c371..f98bb09 100644
--- a/core/java/android/speech/tts/SynthesisCallback.java
+++ b/core/java/android/speech/tts/SynthesisCallback.java
@@ -22,10 +22,11 @@ package android.speech.tts;
* {@link #start}, then {@link #audioAvailable} until all audio has been provided, then finally
* {@link #done}.
*
- *
* {@link #error} can be called at any stage in the synthesis process to
* indicate that an error has occurred, but if the call is made after a call
* to {@link #done}, it might be discarded.
+ *
+ * After {@link #start} been called, {@link #done} must be called regardless of errors.
*/
public interface SynthesisCallback {
/**
@@ -72,6 +73,8 @@ public interface SynthesisCallback {
* This method should only be called on the synthesis thread,
* while in {@link TextToSpeechService#onSynthesizeText}.
*
+ * This method has to be called if {@link #start} was called.
+ *
* @return {@link TextToSpeech#SUCCESS} or {@link TextToSpeech#ERROR}.
*/
public int done();
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 5e367cb..9d570fc 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -793,8 +793,13 @@ public class TextToSpeech {
}
/**
- * Speaks the string using the specified queuing strategy and speech
- * parameters.
+ * Speaks the string using the specified queuing strategy and speech parameters.
+ * This method is asynchronous, i.e. the method just adds the request to the queue of TTS
+ * requests and then returns. The synthesis might not have finished (or even started!) at the
+ * time when this method returns. In order to reliably detect errors during synthesis,
+ * we recommend setting an utterance progress listener (see
+ * {@link #setOnUtteranceProgressListener}) and using the
+ * {@link Engine#KEY_PARAM_UTTERANCE_ID} parameter.
*
* @param text The string of text to be spoken.
* @param queueMode The queuing strategy to use, {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
@@ -809,7 +814,7 @@ public class TextToSpeech {
* the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
* engine named "com.svox.pico" if it is being used.
*
- * @return {@link #ERROR} or {@link #SUCCESS}.
+ * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the speak operation.
*/
public int speak(final String text, final int queueMode, final HashMap<String, String> params) {
return runAction(new Action<Integer>() {
@@ -830,6 +835,12 @@ public class TextToSpeech {
* Plays the earcon using the specified queueing mode and parameters.
* The earcon must already have been added with {@link #addEarcon(String, String)} or
* {@link #addEarcon(String, String, int)}.
+ * This method is asynchronous, i.e. the method just adds the request to the queue of TTS
+ * requests and then returns. The synthesis might not have finished (or even started!) at the
+ * time when this method returns. In order to reliably detect errors during synthesis,
+ * we recommend setting an utterance progress listener (see
+ * {@link #setOnUtteranceProgressListener}) and using the
+ * {@link Engine#KEY_PARAM_UTTERANCE_ID} parameter.
*
* @param earcon The earcon that should be played
* @param queueMode {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
@@ -842,7 +853,7 @@ public class TextToSpeech {
* the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
* engine named "com.svox.pico" if it is being used.
*
- * @return {@link #ERROR} or {@link #SUCCESS}.
+ * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation.
*/
public int playEarcon(final String earcon, final int queueMode,
final HashMap<String, String> params) {
@@ -862,6 +873,12 @@ public class TextToSpeech {
/**
* Plays silence for the specified amount of time using the specified
* queue mode.
+ * This method is asynchronous, i.e. the method just adds the request to the queue of TTS
+ * requests and then returns. The synthesis might not have finished (or even started!) at the
+ * time when this method returns. In order to reliably detect errors during synthesis,
+ * we recommend setting an utterance progress listener (see
+ * {@link #setOnUtteranceProgressListener}) and using the
+ * {@link Engine#KEY_PARAM_UTTERANCE_ID} parameter.
*
* @param durationInMs The duration of the silence.
* @param queueMode {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
@@ -873,7 +890,7 @@ public class TextToSpeech {
* the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
* engine named "com.svox.pico" if it is being used.
*
- * @return {@link #ERROR} or {@link #SUCCESS}.
+ * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilence operation.
*/
public int playSilence(final long durationInMs, final int queueMode,
final HashMap<String, String> params) {
@@ -1089,6 +1106,12 @@ public class TextToSpeech {
/**
* Synthesizes the given text to a file using the specified parameters.
+ * This method is asynchronous, i.e. the method just adds the request to the queue of TTS
+ * requests and then returns. The synthesis might not have finished (or even started!) at the
+ * time when this method returns. In order to reliably detect errors during synthesis,
+ * we recommend setting an utterance progress listener (see
+ * {@link #setOnUtteranceProgressListener}) and using the
+ * {@link Engine#KEY_PARAM_UTTERANCE_ID} parameter.
*
* @param text The text that should be synthesized
* @param params Parameters for the request. Can be null.
@@ -1101,7 +1124,7 @@ public class TextToSpeech {
* @param filename Absolute file filename to write the generated audio data to.It should be
* something like "/sdcard/myappsounds/mysound.wav".
*
- * @return {@link #ERROR} or {@link #SUCCESS}.
+ * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation.
*/
public int synthesizeToFile(final String text, final HashMap<String, String> params,
final String filename) {
diff --git a/core/java/android/text/method/DigitsKeyListener.java b/core/java/android/text/method/DigitsKeyListener.java
index 3d9daed..c95df46 100644
--- a/core/java/android/text/method/DigitsKeyListener.java
+++ b/core/java/android/text/method/DigitsKeyListener.java
@@ -49,13 +49,22 @@ public class DigitsKeyListener extends NumberKeyListener
* @see KeyEvent#getMatch
* @see #getAcceptedChars
*/
- private static final char[][] CHARACTERS = new char[][] {
- new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' },
- new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' },
- new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.' },
- new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.' },
+ private static final char[][] CHARACTERS = {
+ { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' },
+ { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+' },
+ { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.' },
+ { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+', '.' },
};
+ private static boolean isSignChar(final char c) {
+ return c == '-' || c == '+';
+ }
+
+ // TODO: Needs internationalization
+ private static boolean isDecimalPointChar(final char c) {
+ return c == '.';
+ }
+
/**
* Allocates a DigitsKeyListener that accepts the digits 0 through 9.
*/
@@ -145,32 +154,32 @@ public class DigitsKeyListener extends NumberKeyListener
int dlen = dest.length();
/*
- * Find out if the existing text has '-' or '.' characters.
+ * Find out if the existing text has a sign or decimal point characters.
*/
for (int i = 0; i < dstart; i++) {
char c = dest.charAt(i);
- if (c == '-') {
+ if (isSignChar(c)) {
sign = i;
- } else if (c == '.') {
+ } else if (isDecimalPointChar(c)) {
decimal = i;
}
}
for (int i = dend; i < dlen; i++) {
char c = dest.charAt(i);
- if (c == '-') {
- return ""; // Nothing can be inserted in front of a '-'.
- } else if (c == '.') {
+ if (isSignChar(c)) {
+ return ""; // Nothing can be inserted in front of a sign character.
+ } else if (isDecimalPointChar(c)) {
decimal = i;
}
}
/*
* If it does, we must strip them out from the source.
- * In addition, '-' must be the very first character,
- * and nothing can be inserted before an existing '-'.
+ * In addition, a sign character must be the very first character,
+ * and nothing can be inserted before an existing sign character.
* Go in reverse order so the offsets are stable.
*/
@@ -180,7 +189,7 @@ public class DigitsKeyListener extends NumberKeyListener
char c = source.charAt(i);
boolean strip = false;
- if (c == '-') {
+ if (isSignChar(c)) {
if (i != start || dstart != 0) {
strip = true;
} else if (sign >= 0) {
@@ -188,7 +197,7 @@ public class DigitsKeyListener extends NumberKeyListener
} else {
sign = i;
}
- } else if (c == '.') {
+ } else if (isDecimalPointChar(c)) {
if (decimal >= 0) {
strip = true;
} else {
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 5dc206f..0ec7e84 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -17,6 +17,7 @@
package android.text.style;
import android.content.Context;
+import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Parcel;
@@ -26,6 +27,7 @@ import android.text.ParcelableSpan;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.Log;
+import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import java.util.Arrays;
@@ -45,6 +47,8 @@ import java.util.Locale;
*/
public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
+ private static final String TAG = "SuggestionSpan";
+
/**
* Sets this flag if the suggestions should be easily accessible with few interactions.
* This flag should be set for every suggestions that the user is likely to use.
@@ -82,6 +86,7 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
private final String[] mSuggestions;
private final String mLocaleString;
private final String mNotificationTargetClassName;
+ private final String mNotificationTargetPackageName;
private final int mHashCode;
private float mEasyCorrectUnderlineThickness;
@@ -134,6 +139,12 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
mLocaleString = "";
}
+ if (context != null) {
+ mNotificationTargetPackageName = context.getPackageName();
+ } else {
+ mNotificationTargetPackageName = null;
+ }
+
if (notificationTargetClass != null) {
mNotificationTargetClassName = notificationTargetClass.getCanonicalName();
} else {
@@ -185,6 +196,7 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
mFlags = src.readInt();
mLocaleString = src.readString();
mNotificationTargetClassName = src.readString();
+ mNotificationTargetPackageName = src.readString();
mHashCode = src.readInt();
mEasyCorrectUnderlineColor = src.readInt();
mEasyCorrectUnderlineThickness = src.readFloat();
@@ -240,6 +252,7 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
dest.writeInt(mFlags);
dest.writeString(mLocaleString);
dest.writeString(mNotificationTargetClassName);
+ dest.writeString(mNotificationTargetPackageName);
dest.writeInt(mHashCode);
dest.writeInt(mEasyCorrectUnderlineColor);
dest.writeFloat(mEasyCorrectUnderlineThickness);
@@ -325,4 +338,40 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
}
return 0;
}
+
+ /**
+ * Notifies a suggestion selection.
+ *
+ * @hide
+ */
+ public void notifySelection(Context context, String original, int index) {
+ final Intent intent = new Intent();
+
+ if (context == null || mNotificationTargetClassName == null) {
+ return;
+ }
+ // Ensures that only a class in the original IME package will receive the
+ // notification.
+ if (mSuggestions == null || index < 0 || index >= mSuggestions.length) {
+ Log.w(TAG, "Unable to notify the suggestion as the index is out of range index=" + index
+ + " length=" + mSuggestions.length);
+ return;
+ }
+
+ // The package name is not mandatory (legacy from JB), and if the package name
+ // is missing, we try to notify the suggestion through the input method manager.
+ if (mNotificationTargetPackageName != null) {
+ intent.setClassName(mNotificationTargetPackageName, mNotificationTargetClassName);
+ intent.setAction(SuggestionSpan.ACTION_SUGGESTION_PICKED);
+ intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE, original);
+ intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER, mSuggestions[index]);
+ intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_HASHCODE, hashCode());
+ context.sendBroadcast(intent);
+ } else {
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm != null) {
+ imm.notifySuggestionPicked(this, original, index);
+ }
+ }
+ }
}
diff --git a/core/java/android/util/PropertyValueModel.java b/core/java/android/util/PropertyValueModel.java
new file mode 100755
index 0000000..eb9c47d
--- /dev/null
+++ b/core/java/android/util/PropertyValueModel.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+package android.util;
+
+/**
+ * A value model for a {@link Property property} of a host object. This class can be used for
+ * both reflective and non-reflective property implementations.
+ *
+ * @param <H> the host type, where the host is the object that holds this property
+ * @param <T> the value type
+ *
+ * @see Property
+ * @see ValueModel
+ */
+public class PropertyValueModel<H, T> extends ValueModel<T> {
+ private final H mHost;
+ private final Property<H, T> mProperty;
+
+ private PropertyValueModel(H host, Property<H, T> property) {
+ mProperty = property;
+ mHost = host;
+ }
+
+ /**
+ * Returns the host.
+ *
+ * @return the host
+ */
+ public H getHost() {
+ return mHost;
+ }
+
+ /**
+ * Returns the property.
+ *
+ * @return the property
+ */
+ public Property<H, T> getProperty() {
+ return mProperty;
+ }
+
+ @Override
+ public Class<T> getType() {
+ return mProperty.getType();
+ }
+
+ @Override
+ public T get() {
+ return mProperty.get(mHost);
+ }
+
+ @Override
+ public void set(T value) {
+ mProperty.set(mHost, value);
+ }
+
+ /**
+ * Return an appropriate PropertyValueModel for this host and property.
+ *
+ * @param host the host
+ * @param property the property
+ * @return the value model
+ */
+ public static <H, T> PropertyValueModel<H, T> of(H host, Property<H, T> property) {
+ return new PropertyValueModel<H, T>(host, property);
+ }
+
+ /**
+ * Return a PropertyValueModel for this {@code host} and a
+ * reflective property, constructed from this {@code propertyType} and {@code propertyName}.
+ *
+ * @param host
+ * @param propertyType the property type
+ * @param propertyName the property name
+ * @return a value model with this host and a reflective property with this type and name
+ *
+ * @see Property#of
+ */
+ public static <H, T> PropertyValueModel<H, T> of(H host, Class<T> propertyType,
+ String propertyName) {
+ return of(host, Property.of((Class<H>) host.getClass(), propertyType, propertyName));
+ }
+
+ private static Class getNullaryMethodReturnType(Class c, String name) {
+ try {
+ return c.getMethod(name).getReturnType();
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+ }
+
+ private static Class getFieldType(Class c, String name) {
+ try {
+ return c.getField(name).getType();
+ } catch (NoSuchFieldException e) {
+ return null;
+ }
+ }
+
+ private static String capitalize(String name) {
+ if (name.isEmpty()) {
+ return name;
+ }
+ return Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ }
+
+ /**
+ * Return a PropertyValueModel for this {@code host} and and {@code propertyName}.
+ *
+ * @param host the host
+ * @param propertyName the property name
+ * @return a value model with this host and a reflective property with this name
+ */
+ public static PropertyValueModel of(Object host, String propertyName) {
+ Class clazz = host.getClass();
+ String suffix = capitalize(propertyName);
+ Class propertyType = getNullaryMethodReturnType(clazz, "get" + suffix);
+ if (propertyType == null) {
+ propertyType = getNullaryMethodReturnType(clazz, "is" + suffix);
+ }
+ if (propertyType == null) {
+ propertyType = getFieldType(clazz, propertyName);
+ }
+ if (propertyType == null) {
+ throw new NoSuchPropertyException(propertyName);
+ }
+ return of(host, propertyType, propertyName);
+ }
+}
diff --git a/core/java/android/util/ValueModel.java b/core/java/android/util/ValueModel.java
new file mode 100755
index 0000000..4789682
--- /dev/null
+++ b/core/java/android/util/ValueModel.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+package android.util;
+
+/**
+ * A ValueModel is an abstraction for a 'slot' or place in memory in which a value
+ * may be stored and retrieved. A common implementation of ValueModel is a regular property of
+ * an object, whose value may be retrieved by calling the appropriate <em>getter</em>
+ * method and set by calling the corresponding <em>setter</em> method.
+ *
+ * @param <T> the value type
+ *
+ * @see PropertyValueModel
+ */
+public abstract class ValueModel<T> {
+ /**
+ * The empty model should be used in place of {@code null} to indicate that a
+ * model has not been set. The empty model has no value and does nothing when it is set.
+ */
+ public static final ValueModel EMPTY = new ValueModel() {
+ @Override
+ public Class getType() {
+ return Object.class;
+ }
+
+ @Override
+ public Object get() {
+ return null;
+ }
+
+ @Override
+ public void set(Object value) {
+
+ }
+ };
+
+ protected ValueModel() {
+ }
+
+ /**
+ * Returns the type of this property.
+ *
+ * @return the property type
+ */
+ public abstract Class<T> getType();
+
+ /**
+ * Returns the value of this property.
+ *
+ * @return the property value
+ */
+ public abstract T get();
+
+ /**
+ * Sets the value of this property.
+ *
+ * @param value the new value for this property
+ */
+ public abstract void set(T value);
+} \ No newline at end of file
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b36db7f..79a545f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -13951,6 +13951,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Return true if o is a ViewGroup that is laying out using optical bounds.
+ * @hide
+ */
+ public static boolean isLayoutModeOptical(Object o) {
+ return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
+ }
+
+ private boolean setOpticalFrame(int left, int top, int right, int bottom) {
+ Insets parentInsets = mParent instanceof View ?
+ ((View) mParent).getOpticalInsets() : Insets.NONE;
+ Insets childInsets = getOpticalInsets();
+ return setFrame(
+ left + parentInsets.left - childInsets.left,
+ top + parentInsets.top - childInsets.top,
+ right + parentInsets.left + childInsets.right,
+ bottom + parentInsets.top + childInsets.bottom);
+ }
+
+ /**
* Assign a size and position to a view and all of its
* descendants
*
@@ -13976,7 +13995,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
int oldT = mTop;
int oldB = mBottom;
int oldR = mRight;
- boolean changed = setFrame(l, t, r, b);
+ boolean changed = isLayoutModeOptical(mParent) ?
+ setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
onLayout(changed, l, t, r, b);
mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
@@ -14790,6 +14810,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
}
+ Insets computeOpticalInsets() {
+ return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
+ }
+
/**
* @hide
*/
@@ -14813,19 +14837,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public Insets getOpticalInsets() {
if (mLayoutInsets == null) {
- mLayoutInsets = (mBackground == null) ? Insets.NONE : mBackground.getLayoutInsets();
+ mLayoutInsets = computeOpticalInsets();
}
return mLayoutInsets;
}
/**
- * @hide
- */
- public void setLayoutInsets(Insets layoutInsets) {
- mLayoutInsets = layoutInsets;
- }
-
- /**
* Changes the selection state of this view. A view can be selected or not.
* Note that selection is not the same as focus. Views are typically
* selected in the context of an AdapterView like ListView or GridView;
@@ -15432,11 +15449,34 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Returns whether the view hierarchy is currently undergoing a layout pass. This
+ * information is useful to avoid situations such as calling {@link #requestLayout()} during
+ * a layout pass.
+ *
+ * @return whether the view hierarchy is currently undergoing a layout pass
+ */
+ public boolean isInLayout() {
+ ViewRootImpl viewRoot = getViewRootImpl();
+ return (viewRoot != null && viewRoot.isInLayout());
+ }
+
+ /**
* Call this when something has changed which has invalidated the
* layout of this view. This will schedule a layout pass of the view
- * tree.
+ * tree. This should not be called while the view hierarchy is currently in a layout
+ * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
+ * end of the current layout pass (and then layout will run again) or after the current
+ * frame is drawn and the next layout occurs.
+ *
+ * <p>Subclasses which override this method should call the superclass method to
+ * handle possible request-during-layout errors correctly.</p>
*/
public void requestLayout() {
+ ViewRootImpl viewRoot = getViewRootImpl();
+ if (viewRoot != null && viewRoot.isInLayout()) {
+ viewRoot.requestLayoutDuringLayout(this);
+ return;
+ }
mPrivateFlags |= PFLAG_FORCE_LAYOUT;
mPrivateFlags |= PFLAG_INVALIDATED;
@@ -15476,6 +15516,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #onMeasure(int, int)
*/
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
+ boolean optical = isLayoutModeOptical(this);
+ if (optical != isLayoutModeOptical(mParent)) {
+ Insets insets = getOpticalInsets();
+ int oWidth = insets.left + insets.right;
+ int oHeight = insets.top + insets.bottom;
+ widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth);
+ heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
+ }
if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
widthMeasureSpec != mOldWidthMeasureSpec ||
heightMeasureSpec != mOldHeightMeasureSpec) {
@@ -15567,6 +15615,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@link #MEASURED_STATE_TOO_SMALL}.
*/
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
+ boolean optical = isLayoutModeOptical(this);
+ if (optical != isLayoutModeOptical(mParent)) {
+ Insets insets = getOpticalInsets();
+ int opticalWidth = insets.left + insets.right;
+ int opticalHeight = insets.top + insets.bottom;
+
+ measuredWidth += optical ? opticalWidth : -opticalWidth;
+ measuredHeight += optical ? opticalHeight : -opticalHeight;
+ }
mMeasuredWidth = measuredWidth;
mMeasuredHeight = measuredHeight;
@@ -17233,7 +17290,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the measure specification based on size and mode
*/
public static int makeMeasureSpec(int size, int mode) {
- return size + mode;
+ return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
/**
@@ -17258,6 +17315,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return (measureSpec & ~MODE_MASK);
}
+ static int adjust(int measureSpec, int delta) {
+ return makeMeasureSpec(getSize(measureSpec + delta), getMode(measureSpec));
+ }
+
/**
* Returns a String representation of the specified measure
* specification.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index dabdf5a..146fe2d 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -23,9 +23,11 @@ import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.DashPathEffect;
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.PathEffect;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -83,6 +85,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
private static final String TAG = "ViewGroup";
private static final boolean DBG = false;
+ /** @hide */
+ public static boolean DEBUG_DRAW = false;
/**
* Views which have been hidden or removed which need to be animated on
@@ -180,10 +184,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
})
protected int mGroupFlags;
- /*
- * The layout mode: either {@link #CLIP_BOUNDS} or {@link #OPTICAL_BOUNDS}
+ /**
+ * Either {@link #LAYOUT_MODE_CLIP_BOUNDS} or {@link #LAYOUT_MODE_OPTICAL_BOUNDS}.
*/
- private int mLayoutMode = CLIP_BOUNDS;
+ private int mLayoutMode = DEFAULT_LAYOUT_MODE;
/**
* NOTE: If you change the flags below make sure to reflect the changes
@@ -356,20 +360,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* This constant is a {@link #setLayoutMode(int) layoutMode}.
* Clip bounds are the raw values of {@link #getLeft() left}, {@link #getTop() top},
* {@link #getRight() right} and {@link #getBottom() bottom}.
- *
- * @hide
*/
- public static final int CLIP_BOUNDS = 0;
+ public static final int LAYOUT_MODE_CLIP_BOUNDS = 0;
/**
* This constant is a {@link #setLayoutMode(int) layoutMode}.
* Optical bounds describe where a widget appears to be. They sit inside the clip
* bounds which need to cover a larger area to allow other effects,
* such as shadows and glows, to be drawn.
- *
- * @hide
*/
- public static final int OPTICAL_BOUNDS = 1;
+ public static final int LAYOUT_MODE_OPTICAL_BOUNDS = 1;
+
+ /** @hide */
+ public static int DEFAULT_LAYOUT_MODE = LAYOUT_MODE_CLIP_BOUNDS;
/**
* We clip to padding when FLAG_CLIP_TO_PADDING and FLAG_PADDING_NOT_NULL
@@ -434,7 +437,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
private boolean debugDraw() {
- return mAttachInfo != null && mAttachInfo.mDebugLayout;
+ return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
}
private void initViewGroup() {
@@ -504,6 +507,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
setLayoutTransition(new LayoutTransition());
}
break;
+ case R.styleable.ViewGroup_layoutMode:
+ setLayoutMode(a.getInt(attr, DEFAULT_LAYOUT_MODE));
+ break;
}
}
@@ -2420,7 +2426,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
for (int i = 0; i < count; i++) {
final View child = children[i];
child.dispatchAttachedToWindow(info,
- visibility | (child.mViewFlags&VISIBILITY_MASK));
+ visibility | (child.mViewFlags & VISIBILITY_MASK));
}
}
@@ -2682,20 +2688,89 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return b;
}
- private static void drawRect(Canvas canvas, int x1, int y1, int x2, int y2, int color) {
- Paint paint = getDebugPaint();
- paint.setColor(color);
+ /** Return true if this ViewGroup is laying out using optical bounds. */
+ boolean isLayoutModeOptical() {
+ return mLayoutMode == LAYOUT_MODE_OPTICAL_BOUNDS;
+ }
+
+ Insets computeOpticalInsets() {
+ if (isLayoutModeOptical()) {
+ int left = 0;
+ int top = 0;
+ int right = 0;
+ int bottom = 0;
+ for (int i = 0; i < mChildrenCount; i++) {
+ View child = getChildAt(i);
+ if (child.getVisibility() == VISIBLE) {
+ Insets insets = child.getOpticalInsets();
+ left = Math.max(left, insets.left);
+ top = Math.max(top, insets.top);
+ right = Math.max(right, insets.right);
+ bottom = Math.max(bottom, insets.bottom);
+ }
+ }
+ return Insets.of(left, top, right, bottom);
+ } else {
+ return Insets.NONE;
+ }
+ }
+
+ private static void fillRect(Canvas canvas, Paint paint, int x1, int y1, int x2, int y2) {
+ if (x1 != x2 && y1 != y2) {
+ if (x1 > x2) {
+ int tmp = x1; x1 = x2; x2 = tmp;
+ }
+ if (y1 > y2) {
+ int tmp = y1; y1 = y2; y2 = tmp;
+ }
+ canvas.drawRect(x1, y1, x2, y2, paint);
+ }
+ }
+
+ private static int sign(int x) {
+ return (x >= 0) ? 1 : -1;
+ }
- canvas.drawLines(getDebugLines(x1, y1, x2, y2), paint);
+ private static void drawCorner(Canvas c, Paint paint, int x1, int y1, int dx, int dy, int lw) {
+ fillRect(c, paint, x1, y1, x1 + dx, y1 + lw * sign(dy));
+ fillRect(c, paint, x1, y1, x1 + lw * sign(dx), y1 + dy);
+ }
+
+ private int dipsToPixels(int dips) {
+ float scale = getContext().getResources().getDisplayMetrics().density;
+ return (int) (dips * scale + 0.5f);
+ }
+
+ private void drawRectCorners(Canvas canvas, int x1, int y1, int x2, int y2, Paint paint,
+ int lineLength, int lineWidth) {
+ drawCorner(canvas, paint, x1, y1, lineLength, lineLength, lineWidth);
+ drawCorner(canvas, paint, x1, y2, lineLength, -lineLength, lineWidth);
+ drawCorner(canvas, paint, x2, y1, -lineLength, lineLength, lineWidth);
+ drawCorner(canvas, paint, x2, y2, -lineLength, -lineLength, lineWidth);
+ }
+
+ private static void fillDifference(Canvas canvas,
+ int x2, int y2, int x3, int y3,
+ int dx1, int dy1, int dx2, int dy2, Paint paint) {
+ int x1 = x2 - dx1;
+ int y1 = y2 - dy1;
+
+ int x4 = x3 + dx2;
+ int y4 = y3 + dy2;
+
+ fillRect(canvas, paint, x1, y1, x4, y2);
+ fillRect(canvas, paint, x1, y2, x2, y3);
+ fillRect(canvas, paint, x3, y2, x4, y3);
+ fillRect(canvas, paint, x1, y3, x4, y4);
}
/**
* @hide
*/
- protected void onDebugDrawMargins(Canvas canvas) {
+ protected void onDebugDrawMargins(Canvas canvas, Paint paint) {
for (int i = 0; i < getChildCount(); i++) {
View c = getChildAt(i);
- c.getLayoutParams().onDebugDraw(c, canvas);
+ c.getLayoutParams().onDebugDraw(c, canvas, paint);
}
}
@@ -2703,26 +2778,45 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @hide
*/
protected void onDebugDraw(Canvas canvas) {
+ Paint paint = getDebugPaint();
+
// Draw optical bounds
- if (getLayoutMode() == OPTICAL_BOUNDS) {
+ {
+ paint.setColor(Color.RED);
+ paint.setStyle(Paint.Style.STROKE);
+
for (int i = 0; i < getChildCount(); i++) {
View c = getChildAt(i);
Insets insets = c.getOpticalInsets();
- drawRect(canvas,
- c.getLeft() + insets.left,
- c.getTop() + insets.top,
- c.getRight() - insets.right,
- c.getBottom() - insets.bottom, Color.RED);
+
+ drawRect(canvas, paint,
+ c.getLeft() + insets.left,
+ c.getTop() + insets.top,
+ c.getRight() - insets.right - 1,
+ c.getBottom() - insets.bottom - 1);
}
}
// Draw margins
- onDebugDrawMargins(canvas);
+ {
+ paint.setColor(Color.argb(63, 255, 0, 255));
+ paint.setStyle(Paint.Style.FILL);
- // Draw bounds
- for (int i = 0; i < getChildCount(); i++) {
- View c = getChildAt(i);
- drawRect(canvas, c.getLeft(), c.getTop(), c.getRight(), c.getBottom(), Color.BLUE);
+ onDebugDrawMargins(canvas, paint);
+ }
+
+ // Draw clip bounds
+ {
+ paint.setColor(Color.rgb(63, 127, 255));
+ paint.setStyle(Paint.Style.FILL);
+
+ int lineLength = dipsToPixels(8);
+ int lineWidth = dipsToPixels(1);
+ for (int i = 0; i < getChildCount(); i++) {
+ View c = getChildAt(i);
+ drawRectCorners(canvas, c.getLeft(), c.getTop(), c.getRight(), c.getBottom(),
+ paint, lineLength, lineWidth);
+ }
}
}
@@ -4613,13 +4707,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
/**
* Returns the basis of alignment during layout operations on this view group:
- * either {@link #CLIP_BOUNDS} or {@link #OPTICAL_BOUNDS}.
+ * either {@link #LAYOUT_MODE_CLIP_BOUNDS} or {@link #LAYOUT_MODE_OPTICAL_BOUNDS}.
*
* @return the layout mode to use during layout operations
*
* @see #setLayoutMode(int)
- *
- * @hide
*/
public int getLayoutMode() {
return mLayoutMode;
@@ -4627,15 +4719,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
/**
* Sets the basis of alignment during the layout of this view group.
- * Valid values are either {@link #CLIP_BOUNDS} or {@link #OPTICAL_BOUNDS}.
+ * Valid values are either {@link #LAYOUT_MODE_CLIP_BOUNDS} or
+ * {@link #LAYOUT_MODE_OPTICAL_BOUNDS}.
* <p>
- * The default is {@link #CLIP_BOUNDS}.
+ * The default is {@link #LAYOUT_MODE_CLIP_BOUNDS}.
*
* @param layoutMode the layout mode to use during layout operations
*
* @see #getLayoutMode()
- *
- * @hide
*/
public void setLayoutMode(int layoutMode) {
if (mLayoutMode != layoutMode) {
@@ -5670,7 +5761,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*
* @hide
*/
- public void onDebugDraw(View view, Canvas canvas) {
+ public void onDebugDraw(View view, Canvas canvas, Paint paint) {
}
/**
@@ -6023,12 +6114,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @hide
*/
@Override
- public void onDebugDraw(View view, Canvas canvas) {
- drawRect(canvas,
- view.getLeft() - leftMargin,
- view.getTop() - topMargin,
- view.getRight() + rightMargin,
- view.getBottom() + bottomMargin, Color.MAGENTA);
+ public void onDebugDraw(View view, Canvas canvas, Paint paint) {
+ Insets oi = isLayoutModeOptical(view.mParent) ? view.getOpticalInsets() : Insets.NONE;
+
+ fillDifference(canvas,
+ view.getLeft() + oi.left,
+ view.getTop() + oi.top,
+ view.getRight() - oi.right,
+ view.getBottom() - oi.bottom,
+ leftMargin,
+ topMargin,
+ rightMargin,
+ bottomMargin,
+ paint);
}
}
@@ -6362,14 +6460,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return sDebugPaint;
}
- private static float[] getDebugLines(int x1, int y1, int x2, int y2) {
+ private void drawRect(Canvas canvas, Paint paint, int x1, int y1, int x2, int y2) {
if (sDebugLines== null) {
sDebugLines = new float[16];
}
- x2--;
- y2--;
-
sDebugLines[0] = x1;
sDebugLines[1] = y1;
sDebugLines[2] = x2;
@@ -6378,18 +6473,18 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
sDebugLines[4] = x2;
sDebugLines[5] = y1;
sDebugLines[6] = x2;
- sDebugLines[7] = y2 + 1;
+ sDebugLines[7] = y2;
- sDebugLines[8] = x2 + 1;
+ sDebugLines[8] = x2;
sDebugLines[9] = y2;
sDebugLines[10] = x1;
sDebugLines[11] = y2;
- sDebugLines[12] = x1;
- sDebugLines[13] = y2;
+ sDebugLines[12] = x1;
+ sDebugLines[13] = y2;
sDebugLines[14] = x1;
sDebugLines[15] = y1;
- return sDebugLines;
+ canvas.drawLines(sDebugLines, paint);
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 62bf691..51edc08 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -319,6 +319,11 @@ public final class ViewRootImpl implements ViewParent,
private final int mDensity;
private final int mNoncompatDensity;
+ private boolean mInLayout = false;
+ ArrayList<View> mLayoutRequesters = new ArrayList<View>();
+ boolean mHandlingLayoutInLayoutRequest = false;
+
+
/**
* Consistency verifier for debugging purposes.
*/
@@ -1873,9 +1878,49 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ /**
+ * Called by {@link android.view.View#isInLayout()} to determine whether the view hierarchy
+ * is currently undergoing a layout pass.
+ *
+ * @return whether the view hierarchy is currently undergoing a layout pass
+ */
+ boolean isInLayout() {
+ return mInLayout;
+ }
+
+ /**
+ * Called by {@link android.view.View#requestLayout()} if the view hiearchy is currently
+ * undergoing a layout pass. requestLayout() should not be called during layout, but if it
+ * is called anyway, we handle the situation here rather than leave the hierarchy in an
+ * indeterminate state. The solution is to queue up all requests during layout, apply those
+ * requests as soon as layout is complete, and then run layout once more immediately. If
+ * more requestLayout() calls are received during that second layout pass, we post those
+ * requests to the next frame, to avoid possible infinite loops.
+ *
+ * @param view the view that requested the layout.
+ */
+ void requestLayoutDuringLayout(final View view) {
+ if (!mHandlingLayoutInLayoutRequest) {
+ if (!mLayoutRequesters.contains(view)) {
+ Log.w("View", "requestLayout() called by " + view + " during layout pass");
+ mLayoutRequesters.add(view);
+ }
+ } else {
+ Log.w("View", "requestLayout() called by " + view + " during second layout pass: " +
+ "posting to next frame");
+ view.post(new Runnable() {
+ @Override
+ public void run() {
+ view.requestLayout();
+ }
+ });
+ }
+ }
+
private void performLayout() {
mLayoutRequested = false;
mScrollMayChange = true;
+ mInLayout = true;
final View host = mView;
if (DEBUG_ORIENTATION || DEBUG_LAYOUT) {
@@ -1886,9 +1931,22 @@ public final class ViewRootImpl implements ViewParent,
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "layout");
try {
host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
+ int numViewsRequestingLayout = mLayoutRequesters.size();
+ if (numViewsRequestingLayout > 0) {
+ // requestLayout() was called during layout: unusual, but try to handle correctly
+ mHandlingLayoutInLayoutRequest = true;
+ for (int i = 0; i < numViewsRequestingLayout; ++i) {
+ mLayoutRequesters.get(i).requestLayout();
+ }
+ // Now run layout one more time
+ host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
+ mHandlingLayoutInLayoutRequest = false;
+ mLayoutRequesters.clear();
+ }
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
+ mInLayout = false;
}
public void requestTransparentRegion(View child) {
diff --git a/core/java/android/webkit/EventLogTags.logtags b/core/java/android/webkit/EventLogTags.logtags
index 082a437..b0b5493 100644
--- a/core/java/android/webkit/EventLogTags.logtags
+++ b/core/java/android/webkit/EventLogTags.logtags
@@ -8,4 +8,3 @@ option java_package android.webkit;
# 70103- used by the browser app itself
70150 browser_snap_center
-70151 browser_text_size_change (oldSize|1|5), (newSize|1|5)
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index aa68904..7f6fa1a 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -89,6 +89,14 @@ public abstract class WebSettings {
ZoomDensity(int size) {
value = size;
}
+
+ /**
+ * @hide Only for use by WebViewProvider implementations
+ */
+ public int getValue() {
+ return value;
+ }
+
int value;
}
@@ -936,6 +944,9 @@ public abstract class WebSettings {
* access to content from other file scheme URLs. See
* {@link #setAllowFileAccessFromFileURLs}. To enable the most restrictive,
* and therefore secure policy, this setting should be disabled.
+ * Note that this setting affects only JavaScript access to file scheme
+ * resources. Other access to such resources, for example, from image HTML
+ * elements, is unaffected.
* <p>
* The default value is true for API level
* {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below,
@@ -953,6 +964,9 @@ public abstract class WebSettings {
* enable the most restrictive, and therefore secure policy, this setting
* should be disabled. Note that the value of this setting is ignored if
* the value of {@link #getAllowUniversalAccessFromFileURLs} is true.
+ * Note too, that this setting affects only JavaScript access to file scheme
+ * resources. Other access to such resources, for example, from image HTML
+ * elements, is unaffected.
* <p>
* The default value is true for API level
* {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below,
@@ -1121,9 +1135,22 @@ public abstract class WebSettings {
}
/**
- * Sets whether Geolocation is enabled. The default is true. See also
- * {@link #setGeolocationDatabasePath} for how to correctly set up
- * Geolocation.
+ * Sets whether Geolocation is enabled. The default is true.
+ * <p>
+ * Please note that in order for the Geolocation API to be usable
+ * by a page in the WebView, the following requirements must be met:
+ * <ul>
+ * <li>an application must have permission to access the device location,
+ * see {@link android.Manifest.permission#ACCESS_COARSE_LOCATION},
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION};
+ * <li>an application must provide an implementation of the
+ * {@link WebChromeClient#onGeolocationPermissionsShowPrompt} callback
+ * to receive notifications that a page is requesting access to location
+ * via the JavaScript Geolocation API.
+ * </ul>
+ * <p>
+ * As an option, it is possible to store previous locations and web origin
+ * permissions in a database. See {@link #setGeolocationDatabasePath}.
*
* @param flag whether Geolocation should be enabled
*/
@@ -1295,7 +1322,7 @@ public abstract class WebSettings {
* and content is re-validated as needed. When navigating back, content is
* not revalidated, instead the content is just retrieved from the cache.
* This method allows the client to override this behavior by specifying
- * one of {@link #LOAD_DEFAULT}, {@link #LOAD_NORMAL},
+ * one of {@link #LOAD_DEFAULT},
* {@link #LOAD_CACHE_ELSE_NETWORK}, {@link #LOAD_NO_CACHE} or
* {@link #LOAD_CACHE_ONLY}. The default value is {@link #LOAD_DEFAULT}.
*
diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java
index 1bbe7bb..e3d095f 100644
--- a/core/java/android/webkit/WebSettingsClassic.java
+++ b/core/java/android/webkit/WebSettingsClassic.java
@@ -647,10 +647,6 @@ public class WebSettingsClassic extends WebSettings {
@Override
public synchronized void setTextZoom(int textZoom) {
if (mTextSize != textZoom) {
- if (WebViewClassic.mLogEvent) {
- EventLog.writeEvent(EventLogTags.BROWSER_TEXT_SIZE_CHANGE,
- mTextSize, textZoom);
- }
mTextSize = textZoom;
postSync();
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6df7820..6aadaf9 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2137,4 +2137,10 @@ public class WebView extends AbsoluteLayout
super.setLayerType(layerType, paint);
mProvider.getViewDelegate().setLayerType(layerType, paint);
}
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ mProvider.getViewDelegate().preDispatchDraw(canvas);
+ super.dispatchDraw(canvas);
+ }
}
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 0f8966e..ff3087e 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -8557,6 +8557,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
updateHwAccelerated();
}
+ @Override
+ public void preDispatchDraw(Canvas canvas) {
+ // no-op for WebViewClassic.
+ }
+
private void updateHwAccelerated() {
if (mNativeClass == 0) {
return;
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index c9f9fbd..1020634 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -341,6 +341,8 @@ public interface WebViewProvider {
public void setBackgroundColor(int color);
public void setLayerType(int layerType, Paint paint);
+
+ public void preDispatchDraw(Canvas canvas);
}
interface ScrollDelegate {
diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java
index f1804f8..41ab5f2 100644
--- a/core/java/android/widget/CheckBox.java
+++ b/core/java/android/widget/CheckBox.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.util.AttributeSet;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.util.ValueModel;
/**
@@ -55,7 +56,9 @@ import android.view.accessibility.AccessibilityNodeInfo;
* {@link android.R.styleable#View View Attributes}
* </p>
*/
-public class CheckBox extends CompoundButton {
+public class CheckBox extends CompoundButton implements ValueEditor<Boolean> {
+ private ValueModel<Boolean> mValueModel = ValueModel.EMPTY;
+
public CheckBox(Context context) {
this(context, null);
}
@@ -79,4 +82,22 @@ public class CheckBox extends CompoundButton {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(CheckBox.class.getName());
}
+
+ @Override
+ public ValueModel<Boolean> getValueModel() {
+ return mValueModel;
+ }
+
+ @Override
+ public void setValueModel(ValueModel<Boolean> valueModel) {
+ mValueModel = valueModel;
+ setChecked(mValueModel.get());
+ }
+
+ @Override
+ public boolean performClick() {
+ boolean handled = super.performClick();
+ mValueModel.set(isChecked());
+ return handled;
+ }
}
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 57e51c2..ec81214 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -17,6 +17,7 @@
package android.widget;
import android.content.Context;
+import android.graphics.Rect;
import android.text.Editable;
import android.text.Selection;
import android.text.Spannable;
@@ -24,6 +25,7 @@ import android.text.TextUtils;
import android.text.method.ArrowKeyMovementMethod;
import android.text.method.MovementMethod;
import android.util.AttributeSet;
+import android.util.ValueModel;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -47,7 +49,9 @@ import android.view.accessibility.AccessibilityNodeInfo;
* {@link android.R.styleable#TextView TextView Attributes},
* {@link android.R.styleable#View View Attributes}
*/
-public class EditText extends TextView {
+public class EditText extends TextView implements ValueEditor<CharSequence> {
+ private ValueModel<CharSequence> mValueModel = ValueModel.EMPTY;
+
public EditText(Context context) {
this(context, null);
}
@@ -128,4 +132,21 @@ public class EditText extends TextView {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(EditText.class.getName());
}
+
+ @Override
+ public ValueModel<CharSequence> getValueModel() {
+ return mValueModel;
+ }
+
+ @Override
+ public void setValueModel(ValueModel<CharSequence> valueModel) {
+ mValueModel = valueModel;
+ setText(mValueModel.get());
+ }
+
+ @Override
+ void sendAfterTextChanged(Editable text) {
+ super.sendAfterTextChanged(text);
+ mValueModel.set(text);
+ }
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 19b825c..8180890 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2612,15 +2612,10 @@ public class Editor {
suggestionStart, suggestionEnd).toString();
mTextView.replaceText_internal(spanStart, spanEnd, suggestion);
- // Notify source IME of the suggestion pick. Do this before swaping texts.
- if (!TextUtils.isEmpty(
- suggestionInfo.suggestionSpan.getNotificationTargetClassName())) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- imm.notifySuggestionPicked(suggestionInfo.suggestionSpan, originalText,
- suggestionInfo.suggestionIndex);
- }
- }
+ // Notify source IME of the suggestion pick. Do this before
+ // swaping texts.
+ suggestionInfo.suggestionSpan.notifySelection(
+ mTextView.getContext(), originalText, suggestionInfo.suggestionIndex);
// Swap text content between actual text and Suggestion span
String[] suggestions = suggestionInfo.suggestionSpan.getSuggestions();
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 772d748..85ed8db 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -605,7 +605,7 @@ public class GridLayout extends ViewGroup {
}
private int getDefaultMargin(View c, boolean isAtEdge, boolean horizontal, boolean leading) {
- return isAtEdge ? DEFAULT_CONTAINER_MARGIN : getDefaultMargin(c, horizontal, leading);
+ return /*isAtEdge ? DEFAULT_CONTAINER_MARGIN :*/ getDefaultMargin(c, horizontal, leading);
}
private int getDefaultMargin(View c, LayoutParams p, boolean horizontal, boolean leading) {
@@ -824,13 +824,11 @@ public class GridLayout extends ViewGroup {
// Draw grid
private void drawLine(Canvas graphics, int x1, int y1, int x2, int y2, Paint paint) {
- int dx = getPaddingLeft();
- int dy = getPaddingTop();
if (isLayoutRtl()) {
int width = getWidth();
- graphics.drawLine(width - dx - x1, dy + y1, width - dx - x2, dy + y2, paint);
+ graphics.drawLine(width - x1, y1, width - x2, y2, paint);
} else {
- graphics.drawLine(dx + x1, dy + y1, dx + x2, dy + y2, paint);
+ graphics.drawLine(x1, y1, x2, y2, paint);
}
}
@@ -838,18 +836,17 @@ public class GridLayout extends ViewGroup {
* @hide
*/
@Override
- protected void onDebugDrawMargins(Canvas canvas) {
+ protected void onDebugDrawMargins(Canvas canvas, Paint paint) {
// Apply defaults, so as to remove UNDEFINED values
LayoutParams lp = new LayoutParams();
for (int i = 0; i < getChildCount(); i++) {
View c = getChildAt(i);
- Insets insets = getLayoutMode() == OPTICAL_BOUNDS ? c.getOpticalInsets() : Insets.NONE;
lp.setMargins(
- getMargin1(c, true, true) - insets.left,
- getMargin1(c, false, true) - insets.top,
- getMargin1(c, true, false) - insets.right,
- getMargin1(c, false, false) - insets.bottom);
- lp.onDebugDraw(c, canvas);
+ getMargin1(c, true, true),
+ getMargin1(c, false, true),
+ getMargin1(c, true, false),
+ getMargin1(c, false, false));
+ lp.onDebugDraw(c, canvas, paint);
}
}
@@ -858,26 +855,30 @@ public class GridLayout extends ViewGroup {
*/
@Override
protected void onDebugDraw(Canvas canvas) {
- int height = getHeight() - getPaddingTop() - getPaddingBottom();
- int width = getWidth() - getPaddingLeft() - getPaddingRight();
-
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.argb(50, 255, 255, 255));
+ Insets insets = getOpticalInsets();
+
+ int top = getPaddingTop() + insets.top;
+ int left = getPaddingLeft() + insets.left;
+ int right = getWidth() - getPaddingRight() - insets.right;
+ int bottom = getHeight() - getPaddingBottom() - insets.bottom;
+
int[] xs = horizontalAxis.locations;
if (xs != null) {
for (int i = 0, length = xs.length; i < length; i++) {
- int x = xs[i];
- drawLine(canvas, x, 0, x, height - 1, paint);
+ int x = left + xs[i];
+ drawLine(canvas, x, top, x, bottom, paint);
}
}
int[] ys = verticalAxis.locations;
if (ys != null) {
for (int i = 0, length = ys.length; i < length; i++) {
- int y = ys[i];
- drawLine(canvas, 0, y, width - 1, y, paint);
+ int y = top + ys[i];
+ drawLine(canvas, left, y, right, y, paint);
}
}
@@ -1013,12 +1014,7 @@ public class GridLayout extends ViewGroup {
}
private int getMeasurement(View c, boolean horizontal) {
- int result = horizontal ? c.getMeasuredWidth() : c.getMeasuredHeight();
- if (getLayoutMode() == OPTICAL_BOUNDS) {
- Insets insets = c.getOpticalInsets();
- return result - (horizontal ? insets.left + insets.right : insets.top + insets.bottom);
- }
- return result;
+ return horizontal ? c.getMeasuredWidth() : c.getMeasuredHeight();
}
final int getMeasurementIncludingMargin(View c, boolean horizontal) {
@@ -1124,14 +1120,6 @@ public class GridLayout extends ViewGroup {
targetWidth - width - paddingRight - rightMargin - dx;
int cy = paddingTop + y1 + gravityOffsetY + alignmentOffsetY + topMargin;
- boolean useLayoutBounds = getLayoutMode() == OPTICAL_BOUNDS;
- if (useLayoutBounds) {
- Insets insets = c.getOpticalInsets();
- cx -= insets.left;
- cy -= insets.top;
- width += (insets.left + insets.right);
- height += (insets.top + insets.bottom);
- }
if (width != c.getMeasuredWidth() || height != c.getMeasuredHeight()) {
c.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY));
}
@@ -2418,6 +2406,8 @@ public class GridLayout extends ViewGroup {
* <li> {@code spec.span = [start, start + size]} </li>
* <li> {@code spec.alignment = alignment} </li>
* </ul>
+ * <p>
+ * To leave the start index undefined, use the value {@link #UNDEFINED}.
*
* @param start the start
* @param size the size
@@ -2433,9 +2423,13 @@ public class GridLayout extends ViewGroup {
* <li> {@code spec.span = [start, start + 1]} </li>
* <li> {@code spec.alignment = alignment} </li>
* </ul>
+ * <p>
+ * To leave the start index undefined, use the value {@link #UNDEFINED}.
*
* @param start the start index
* @param alignment the alignment
+ *
+ * @see #spec(int, int, Alignment)
*/
public static Spec spec(int start, Alignment alignment) {
return spec(start, 1, alignment);
@@ -2446,9 +2440,13 @@ public class GridLayout extends ViewGroup {
* <ul>
* <li> {@code spec.span = [start, start + size]} </li>
* </ul>
+ * <p>
+ * To leave the start index undefined, use the value {@link #UNDEFINED}.
*
* @param start the start
* @param size the size
+ *
+ * @see #spec(int, Alignment)
*/
public static Spec spec(int start, int size) {
return spec(start, size, UNDEFINED_ALIGNMENT);
@@ -2459,8 +2457,12 @@ public class GridLayout extends ViewGroup {
* <ul>
* <li> {@code spec.span = [start, start + 1]} </li>
* </ul>
+ * <p>
+ * To leave the start index undefined, use the value {@link #UNDEFINED}.
*
* @param start the start index
+ *
+ * @see #spec(int, int)
*/
public static Spec spec(int start) {
return spec(start, 1);
@@ -2654,14 +2656,7 @@ public class GridLayout extends ViewGroup {
@Override
public int getAlignmentValue(View view, int viewSize, int mode) {
int baseline = view.getBaseline();
- if (baseline == -1) {
- return UNDEFINED;
- } else {
- if (mode == OPTICAL_BOUNDS) {
- return baseline - view.getOpticalInsets().top;
- }
- return baseline;
- }
+ return baseline == -1 ? UNDEFINED : baseline;
}
@Override
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 87396fb..1d465ce 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -789,6 +789,12 @@ public class ImageView extends View {
if (resizeWidth) {
int newWidth = (int)(desiredAspect * (heightSize - ptop - pbottom)) +
pleft + pright;
+
+ // Allow the width to outgrow its original estimate if height is fixed.
+ if (!resizeHeight) {
+ widthSize = resolveAdjustedSize(newWidth, mMaxWidth, widthMeasureSpec);
+ }
+
if (newWidth <= widthSize) {
widthSize = newWidth;
done = true;
@@ -799,6 +805,13 @@ public class ImageView extends View {
if (!done && resizeHeight) {
int newHeight = (int)((widthSize - pleft - pright) / desiredAspect) +
ptop + pbottom;
+
+ // Allow the height to outgrow its original estimate if width is fixed.
+ if (!resizeWidth) {
+ heightSize = resolveAdjustedSize(newHeight, mMaxHeight,
+ heightMeasureSpec);
+ }
+
if (newHeight <= heightSize) {
heightSize = newHeight;
}
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 83c15bb..abf2756 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -1437,9 +1437,9 @@ public class LinearLayout extends ViewGroup {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (mOrientation == VERTICAL) {
- layoutVertical();
+ layoutVertical(l, t, r, b);
} else {
- layoutHorizontal();
+ layoutHorizontal(l, t, r, b);
}
}
@@ -1450,15 +1450,19 @@ public class LinearLayout extends ViewGroup {
* @see #getOrientation()
* @see #setOrientation(int)
* @see #onLayout(boolean, int, int, int, int)
+ * @param left
+ * @param top
+ * @param right
+ * @param bottom
*/
- void layoutVertical() {
+ void layoutVertical(int left, int top, int right, int bottom) {
final int paddingLeft = mPaddingLeft;
int childTop;
int childLeft;
// Where right end of child should go
- final int width = mRight - mLeft;
+ final int width = right - left;
int childRight = width - mPaddingRight;
// Space available for child
@@ -1472,12 +1476,12 @@ public class LinearLayout extends ViewGroup {
switch (majorGravity) {
case Gravity.BOTTOM:
// mTotalLength contains the padding already
- childTop = mPaddingTop + mBottom - mTop - mTotalLength;
+ childTop = mPaddingTop + bottom - top - mTotalLength;
break;
// mTotalLength contains the padding already
case Gravity.CENTER_VERTICAL:
- childTop = mPaddingTop + (mBottom - mTop - mTotalLength) / 2;
+ childTop = mPaddingTop + (bottom - top - mTotalLength) / 2;
break;
case Gravity.TOP:
@@ -1540,8 +1544,12 @@ public class LinearLayout extends ViewGroup {
* @see #getOrientation()
* @see #setOrientation(int)
* @see #onLayout(boolean, int, int, int, int)
+ * @param left
+ * @param top
+ * @param right
+ * @param bottom
*/
- void layoutHorizontal() {
+ void layoutHorizontal(int left, int top, int right, int bottom) {
final boolean isLayoutRtl = isLayoutRtl();
final int paddingTop = mPaddingTop;
@@ -1549,7 +1557,7 @@ public class LinearLayout extends ViewGroup {
int childLeft;
// Where bottom of child should go
- final int height = mBottom - mTop;
+ final int height = bottom - top;
int childBottom = height - mPaddingBottom;
// Space available for child
@@ -1569,12 +1577,12 @@ public class LinearLayout extends ViewGroup {
switch (Gravity.getAbsoluteGravity(majorGravity, layoutDirection)) {
case Gravity.RIGHT:
// mTotalLength contains the padding already
- childLeft = mPaddingLeft + mRight - mLeft - mTotalLength;
+ childLeft = mPaddingLeft + right - left - mTotalLength;
break;
case Gravity.CENTER_HORIZONTAL:
// mTotalLength contains the padding already
- childLeft = mPaddingLeft + (mRight - mLeft - mTotalLength) / 2;
+ childLeft = mPaddingLeft + (right - left - mTotalLength) / 2;
break;
case Gravity.LEFT:
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index ace26f3..de5b369 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -369,10 +369,10 @@ public class RelativeLayout extends ViewGroup {
int width = 0;
int height = 0;
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+ final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
// Record our dimensions if they are known;
if (widthMode != MeasureSpec.UNSPECIFIED) {
@@ -638,7 +638,12 @@ public class RelativeLayout extends ViewGroup {
mPaddingLeft, mPaddingRight,
myWidth);
int childHeightMeasureSpec;
- if (params.width == LayoutParams.MATCH_PARENT) {
+ if (myHeight < 0) {
+ // Negative values in a mySize/myWidth/myWidth value in RelativeLayout measurement
+ // is code for, "we got an unspecified mode in the RelativeLayout's measurespec."
+ // Carry it forward.
+ childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ } else if (params.width == LayoutParams.MATCH_PARENT) {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.EXACTLY);
} else {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.AT_MOST);
@@ -665,6 +670,13 @@ public class RelativeLayout extends ViewGroup {
private int getChildMeasureSpec(int childStart, int childEnd,
int childSize, int startMargin, int endMargin, int startPadding,
int endPadding, int mySize) {
+ if (mySize < 0) {
+ // Negative values in a mySize/myWidth/myWidth value in RelativeLayout measurement
+ // is code for, "we got an unspecified mode in the RelativeLayout's measurespec."
+ // Carry it forward.
+ return MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ }
+
int childSpecMode = 0;
int childSpecSize = 0;
diff --git a/core/java/android/widget/SeekBar.java b/core/java/android/widget/SeekBar.java
index 2737f94..a6486a8 100644
--- a/core/java/android/widget/SeekBar.java
+++ b/core/java/android/widget/SeekBar.java
@@ -18,6 +18,7 @@ package android.widget;
import android.content.Context;
import android.util.AttributeSet;
+import android.util.ValueModel;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -33,7 +34,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
*
* @attr ref android.R.styleable#SeekBar_thumb
*/
-public class SeekBar extends AbsSeekBar {
+public class SeekBar extends AbsSeekBar implements ValueEditor<Integer> {
/**
* A callback that notifies clients when the progress level has been
@@ -69,8 +70,9 @@ public class SeekBar extends AbsSeekBar {
void onStopTrackingTouch(SeekBar seekBar);
}
+ private ValueModel<Integer> mValueModel = ValueModel.EMPTY;
private OnSeekBarChangeListener mOnSeekBarChangeListener;
-
+
public SeekBar(Context context) {
this(context, null);
}
@@ -89,9 +91,23 @@ public class SeekBar extends AbsSeekBar {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser);
+ if (fromUser) {
+ mValueModel.set(getProgress());
+ }
}
}
+ @Override
+ public ValueModel<Integer> getValueModel() {
+ return mValueModel;
+ }
+
+ @Override
+ public void setValueModel(ValueModel<Integer> valueModel) {
+ mValueModel = valueModel;
+ setProgress(mValueModel.get());
+ }
+
/**
* Sets a listener to receive notifications of changes to the SeekBar's progress level. Also
* provides notifications of when the user starts and stops a touch gesture within the SeekBar.
diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java
index 399b4fa..f4b2ce0 100644
--- a/core/java/android/widget/TableLayout.java
+++ b/core/java/android/widget/TableLayout.java
@@ -445,7 +445,7 @@ public class TableLayout extends LinearLayout {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// enforce vertical layout
- layoutVertical();
+ layoutVertical(l, t, r, b);
}
/**
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index 68ffd73..a8cc406 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -120,7 +120,7 @@ public class TableRow extends LinearLayout {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// enforce horizontal layout
- layoutHorizontal();
+ layoutHorizontal(l, t, r, b);
}
/**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 8e5ff40..8d00444 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -26,6 +26,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Canvas;
+import android.graphics.Insets;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
@@ -4220,6 +4221,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
/////////////////////////////////////////////////////////////////////////
+ private int getBoxHeight(Layout l) {
+ Insets opticalInsets = isLayoutModeOptical(mParent) ? getOpticalInsets() : Insets.NONE;
+ int padding = (l == mHintLayout) ?
+ getCompoundPaddingTop() + getCompoundPaddingBottom() :
+ getExtendedPaddingTop() + getExtendedPaddingBottom();
+ return getMeasuredHeight() - padding + opticalInsets.top + opticalInsets.bottom;
+ }
+
int getVerticalOffset(boolean forceNormal) {
int voffset = 0;
final int gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
@@ -4230,15 +4239,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
if (gravity != Gravity.TOP) {
- int boxht;
-
- if (l == mHintLayout) {
- boxht = getMeasuredHeight() - getCompoundPaddingTop() -
- getCompoundPaddingBottom();
- } else {
- boxht = getMeasuredHeight() - getExtendedPaddingTop() -
- getExtendedPaddingBottom();
- }
+ int boxht = getBoxHeight(l);
int textht = l.getHeight();
if (textht < boxht) {
@@ -4261,15 +4262,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
if (gravity != Gravity.BOTTOM) {
- int boxht;
-
- if (l == mHintLayout) {
- boxht = getMeasuredHeight() - getCompoundPaddingTop() -
- getCompoundPaddingBottom();
- } else {
- boxht = getMeasuredHeight() - getExtendedPaddingTop() -
- getExtendedPaddingBottom();
- }
+ int boxht = getBoxHeight(l);
int textht = l.getHeight();
if (textht < boxht) {
@@ -5005,6 +4998,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
voffset = getVerticalOffset(true);
}
+ if (isLayoutModeOptical(mParent)) {
+ voffset -= getOpticalInsets().top;
+ }
+
return getExtendedPaddingTop() + voffset + mLayout.getLineBaseline(0);
}
diff --git a/core/java/android/widget/ValueEditor.java b/core/java/android/widget/ValueEditor.java
new file mode 100755
index 0000000..2b91abf
--- /dev/null
+++ b/core/java/android/widget/ValueEditor.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+package android.widget;
+
+import android.util.ValueModel;
+
+/**
+ * An interface for editors of simple values. Classes implementing this interface are normally
+ * UI controls (subclasses of {@link android.view.View View}) that can provide a suitable
+ * user interface to display and edit values of the specified type. This interface is
+ * intended to describe editors for simple types, like {@code boolean}, {@code int} or
+ * {@code String}, where the values themselves are immutable.
+ * <p>
+ * For example, {@link android.widget.CheckBox CheckBox} implements
+ * this interface for the Boolean type as it is capable of providing an appropriate
+ * mechanism for displaying and changing the value of a Boolean property.
+ *
+ * @param <T> the value type that this editor supports
+ */
+public interface ValueEditor<T> {
+ /**
+ * Return the last value model that was set. If no value model has been set, the editor
+ * should return the value {@link android.util.ValueModel#EMPTY}.
+ *
+ * @return the value model
+ */
+ public ValueModel<T> getValueModel();
+
+ /**
+ * Sets the value model for this editor. When the value model is set, the editor should
+ * retrieve the value from the value model, using {@link android.util.ValueModel#get()},
+ * and set its internal state accordingly. Likewise, when the editor's internal state changes
+ * it should update the value model by calling {@link android.util.ValueModel#set(T)}
+ * with the appropriate value.
+ *
+ * @param valueModel the new value model for this editor.
+ */
+ public void setValueModel(ValueModel<T> valueModel);
+}