diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/java/android/view | |
parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
download | frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/android/view')
90 files changed, 0 insertions, 36457 deletions
diff --git a/core/java/android/view/AbsSavedState.java b/core/java/android/view/AbsSavedState.java deleted file mode 100644 index 840d7c1..0000000 --- a/core/java/android/view/AbsSavedState.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * A {@link Parcelable} implementation that should be used by inheritance - * hierarchies to ensure the state of all classes along the chain is saved. - */ -public abstract class AbsSavedState implements Parcelable { - public static final AbsSavedState EMPTY_STATE = new AbsSavedState() {}; - - private final Parcelable mSuperState; - - /** - * Constructor used to make the EMPTY_STATE singleton - */ - private AbsSavedState() { - mSuperState = null; - } - - /** - * Constructor called by derived classes when creating their SavedState objects - * - * @param superState The state of the superclass of this view - */ - protected AbsSavedState(Parcelable superState) { - if (superState == null) { - throw new IllegalArgumentException("superState must not be null"); - } - mSuperState = superState != EMPTY_STATE ? superState : null; - } - - /** - * Constructor used when reading from a parcel. Reads the state of the superclass. - * - * @param source - */ - protected AbsSavedState(Parcel source) { - // FIXME need class loader - Parcelable superState = (Parcelable) source.readParcelable(null); - - mSuperState = superState != null ? superState : EMPTY_STATE; - } - - final public Parcelable getSuperState() { - return mSuperState; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeParcelable(mSuperState, flags); - } - - public static final Parcelable.Creator<AbsSavedState> CREATOR - = new Parcelable.Creator<AbsSavedState>() { - - public AbsSavedState createFromParcel(Parcel in) { - Parcelable superState = (Parcelable) in.readParcelable(null); - if (superState != null) { - throw new IllegalStateException("superState must be null"); - } - return EMPTY_STATE; - } - - public AbsSavedState[] newArray(int size) { - return new AbsSavedState[size]; - } - }; -} diff --git a/core/java/android/view/ContextMenu.java b/core/java/android/view/ContextMenu.java deleted file mode 100644 index dd1d7db..0000000 --- a/core/java/android/view/ContextMenu.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2007 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.view; - -import android.app.Activity; -import android.graphics.drawable.Drawable; -import android.widget.AdapterView; - -/** - * Extension of {@link Menu} for context menus providing functionality to modify - * the header of the context menu. - * <p> - * Context menus do not support item shortcuts and item icons. - * <p> - * To show a context menu on long click, most clients will want to call - * {@link Activity#registerForContextMenu} and override - * {@link Activity#onCreateContextMenu}. - */ -public interface ContextMenu extends Menu { - /** - * Sets the context menu header's title to the title given in <var>titleRes</var> - * resource identifier. - * - * @param titleRes The string resource identifier used for the title. - * @return This ContextMenu so additional setters can be called. - */ - public ContextMenu setHeaderTitle(int titleRes); - - /** - * Sets the context menu header's title to the title given in <var>title</var>. - * - * @param title The character sequence used for the title. - * @return This ContextMenu so additional setters can be called. - */ - public ContextMenu setHeaderTitle(CharSequence title); - - /** - * Sets the context menu header's icon to the icon given in <var>iconRes</var> - * resource id. - * - * @param iconRes The resource identifier used for the icon. - * @return This ContextMenu so additional setters can be called. - */ - public ContextMenu setHeaderIcon(int iconRes); - - /** - * Sets the context menu header's icon to the icon given in <var>icon</var> - * {@link Drawable}. - * - * @param icon The {@link Drawable} used for the icon. - * @return This ContextMenu so additional setters can be called. - */ - public ContextMenu setHeaderIcon(Drawable icon); - - /** - * Sets the header of the context menu to the {@link View} given in - * <var>view</var>. This replaces the header title and icon (and those - * replace this). - * - * @param view The {@link View} used for the header. - * @return This ContextMenu so additional setters can be called. - */ - public ContextMenu setHeaderView(View view); - - /** - * Clears the header of the context menu. - */ - public void clearHeader(); - - /** - * Additional information regarding the creation of the context menu. For example, - * {@link AdapterView}s use this to pass the exact item position within the adapter - * that initiated the context menu. - */ - public interface ContextMenuInfo { - } -} diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java deleted file mode 100644 index 2045a98..0000000 --- a/core/java/android/view/ContextThemeWrapper.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.content.Context; -import android.content.ContextWrapper; -import android.content.res.Resources; - -/** - * A ContextWrapper that allows you to modify the theme from what is in the - * wrapped context. - */ -public class ContextThemeWrapper extends ContextWrapper { - private Context mBase; - private int mThemeResource; - private Resources.Theme mTheme; - private LayoutInflater mInflater; - - public ContextThemeWrapper() { - super(null); - } - - public ContextThemeWrapper(Context base, int themeres) { - super(base); - mBase = base; - mThemeResource = themeres; - } - - @Override protected void attachBaseContext(Context newBase) { - super.attachBaseContext(newBase); - mBase = newBase; - } - - @Override public void setTheme(int resid) { - mThemeResource = resid; - initializeTheme(); - } - - @Override public Resources.Theme getTheme() { - if (mTheme != null) { - return mTheme; - } - - if (mThemeResource == 0) { - mThemeResource = com.android.internal.R.style.Theme; - } - initializeTheme(); - - return mTheme; - } - - @Override public Object getSystemService(String name) { - if (LAYOUT_INFLATER_SERVICE.equals(name)) { - if (mInflater == null) { - mInflater = LayoutInflater.from(mBase).cloneInContext(this); - } - return mInflater; - } - return mBase.getSystemService(name); - } - - /** - * Called by {@link #setTheme} and {@link #getTheme} to apply a theme - * resource to the current Theme object. Can override to change the - * default (simple) behavior. This method will not be called in multiple - * threads simultaneously. - * - * @param theme The Theme object being modified. - * @param resid The theme style resource being applied to <var>theme</var>. - * @param first Set to true if this is the first time a style is being - * applied to <var>theme</var>. - */ - protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) { - theme.applyStyle(resid, true); - } - - private void initializeTheme() { - final boolean first = mTheme == null; - if (first) { - mTheme = getResources().newTheme(); - Resources.Theme theme = mBase.getTheme(); - if (theme != null) { - mTheme.setTo(theme); - } - } - onApplyThemeResource(mTheme, mThemeResource, first); - } -} - diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java deleted file mode 100644 index 09ebeed..0000000 --- a/core/java/android/view/Display.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.util.DisplayMetrics; - -public class Display -{ - /** - * Specify the default Display - */ - public static final int DEFAULT_DISPLAY = 0; - - - /** - * Use the WindowManager interface to create a Display object. - * Display gives you access to some information about a particular display - * connected to the device. - */ - Display(int display) { - // initalize the statics when this class is first instansiated. This is - // done here instead of in the static block because Zygote - synchronized (mStaticInit) { - if (!mInitialized) { - nativeClassInit(); - mInitialized = true; - } - } - mDisplay = display; - init(display); - } - - /** - * @return index of this display. - */ - public int getDisplayId() { - return mDisplay; - } - - /** - * @return the number of displays connected to the device. - */ - native static int getDisplayCount(); - - /** - * @return width of this display in pixels. - */ - native public int getWidth(); - - /** - * @return height of this display in pixels. - */ - native public int getHeight(); - - /** - * @return orientation of this display. - */ - native public int getOrientation(); - - /** - * @return pixel format of this display. - */ - public int getPixelFormat() { - return mPixelFormat; - } - - /** - * @return refresh rate of this display in frames per second. - */ - public float getRefreshRate() { - return mRefreshRate; - } - - /** - * Initialize a DisplayMetrics object from this display's data. - * - * @param outMetrics - */ - public void getMetrics(DisplayMetrics outMetrics) { - outMetrics.widthPixels = getWidth(); - outMetrics.heightPixels = getHeight(); - outMetrics.density = mDensity; - outMetrics.scaledDensity= outMetrics.density; - outMetrics.xdpi = mDpiX; - outMetrics.ydpi = mDpiY; - } - - /* - * We use a class initializer to allow the native code to cache some - * field offsets. - */ - native private static void nativeClassInit(); - - private native void init(int display); - - private int mDisplay; - // Following fields are initialized from native code - private int mPixelFormat; - private float mRefreshRate; - private float mDensity; - private float mDpiX; - private float mDpiY; - - private static final Object mStaticInit = new Object(); - private static boolean mInitialized = false; -} - diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java deleted file mode 100644 index 15fb839..0000000 --- a/core/java/android/view/FocusFinder.java +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright (C) 2007 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.view; - -import android.graphics.Rect; - -import java.util.ArrayList; - -/** - * The algorithm used for finding the next focusable view in a given direction - * from a view that currently has focus. - */ -public class FocusFinder { - - private static ThreadLocal<FocusFinder> tlFocusFinder = - new ThreadLocal<FocusFinder>() { - - protected FocusFinder initialValue() { - return new FocusFinder(); - } - }; - - /** - * Get the focus finder for this thread. - */ - public static FocusFinder getInstance() { - return tlFocusFinder.get(); - } - - Rect mFocusedRect = new Rect(); - Rect mOtherRect = new Rect(); - Rect mBestCandidateRect = new Rect(); - - // enforce thread local access - private FocusFinder() {} - - /** - * Find the next view to take focus in root's descendants, starting from the view - * that currently is focused. - * @param root Contains focused - * @param focused Has focus now. - * @param direction Direction to look. - * @return The next focusable view, or null if none exists. - */ - public final View findNextFocus(ViewGroup root, View focused, int direction) { - - if (focused != null) { - // check for user specified next focus - View userSetNextFocus = focused.findUserSetNextFocus(root, direction); - if (userSetNextFocus != null && - userSetNextFocus.isFocusable() && - (!userSetNextFocus.isInTouchMode() || - userSetNextFocus.isFocusableInTouchMode())) { - return userSetNextFocus; - } - - // fill in interesting rect from focused - focused.getFocusedRect(mFocusedRect); - root.offsetDescendantRectToMyCoords(focused, mFocusedRect); - } else { - // make up a rect at top left or bottom right of root - switch (direction) { - case View.FOCUS_RIGHT: - case View.FOCUS_DOWN: - final int rootTop = root.getScrollY(); - final int rootLeft = root.getScrollX(); - mFocusedRect.set(rootLeft, rootTop, rootLeft, rootTop); - break; - - case View.FOCUS_LEFT: - case View.FOCUS_UP: - final int rootBottom = root.getScrollY() + root.getHeight(); - final int rootRight = root.getScrollX() + root.getWidth(); - mFocusedRect.set(rootRight, rootBottom, - rootRight, rootBottom); - break; - } - } - return findNextFocus(root, focused, mFocusedRect, direction); - } - - /** - * Find the next view to take focus in root's descendants, searching from - * a particular rectangle in root's coordinates. - * @param root Contains focusedRect. - * @param focusedRect The starting point of the search. - * @param direction Direction to look. - * @return The next focusable view, or null if none exists. - */ - public View findNextFocusFromRect(ViewGroup root, Rect focusedRect, int direction) { - return findNextFocus(root, null, focusedRect, direction); - } - - private View findNextFocus(ViewGroup root, View focused, Rect focusedRect, int direction) { - ArrayList<View> focusables = root.getFocusables(direction); - - // initialize the best candidate to something impossible - // (so the first plausible view will become the best choice) - mBestCandidateRect.set(focusedRect); - switch(direction) { - case View.FOCUS_LEFT: - mBestCandidateRect.offset(focusedRect.width() + 1, 0); - break; - case View.FOCUS_RIGHT: - mBestCandidateRect.offset(-(focusedRect.width() + 1), 0); - break; - case View.FOCUS_UP: - mBestCandidateRect.offset(0, focusedRect.height() + 1); - break; - case View.FOCUS_DOWN: - mBestCandidateRect.offset(0, -(focusedRect.height() + 1)); - } - - View closest = null; - - int numFocusables = focusables.size(); - for (int i = 0; i < numFocusables; i++) { - View focusable = focusables.get(i); - - // only interested in other non-root views - if (focusable == focused || focusable == root) continue; - - // get visible bounds of other view in same coordinate system - focusable.getDrawingRect(mOtherRect); - root.offsetDescendantRectToMyCoords(focusable, mOtherRect); - - if (isBetterCandidate(direction, focusedRect, mOtherRect, mBestCandidateRect)) { - mBestCandidateRect.set(mOtherRect); - closest = focusable; - } - } - return closest; - } - - /** - * Is rect1 a better candidate than rect2 for a focus search in a particular - * direction from a source rect? This is the core routine that determines - * the order of focus searching. - * @param direction the direction (up, down, left, right) - * @param source The source we are searching from - * @param rect1 The candidate rectangle - * @param rect2 The current best candidate. - * @return Whether the candidate is the new best. - */ - boolean isBetterCandidate(int direction, Rect source, Rect rect1, Rect rect2) { - - // to be a better candidate, need to at least be a candidate in the first - // place :) - if (!isCandidate(source, rect1, direction)) { - return false; - } - - // we know that rect1 is a candidate.. if rect2 is not a candidate, - // rect1 is better - if (!isCandidate(source, rect2, direction)) { - return true; - } - - // if rect1 is better by beam, it wins - if (beamBeats(direction, source, rect1, rect2)) { - return true; - } - - // if rect2 is better, then rect1 cant' be :) - if (beamBeats(direction, source, rect2, rect1)) { - return false; - } - - // otherwise, do fudge-tastic comparison of the major and minor axis - return (getWeightedDistanceFor( - majorAxisDistance(direction, source, rect1), - minorAxisDistance(direction, source, rect1)) - < getWeightedDistanceFor( - majorAxisDistance(direction, source, rect2), - minorAxisDistance(direction, source, rect2))); - } - - /** - * One rectangle may be another candidate than another by virtue of being - * exclusively in the beam of the source rect. - * @return Whether rect1 is a better candidate than rect2 by virtue of it being in src's - * beam - */ - boolean beamBeats(int direction, Rect source, Rect rect1, Rect rect2) { - final boolean rect1InSrcBeam = beamsOverlap(direction, source, rect1); - final boolean rect2InSrcBeam = beamsOverlap(direction, source, rect2); - - // if rect1 isn't exclusively in the src beam, it doesn't win - if (rect2InSrcBeam || !rect1InSrcBeam) { - return false; - } - - // we know rect1 is in the beam, and rect2 is not - - // if rect1 is to the direction of, and rect2 is not, rect1 wins. - // for example, for direction left, if rect1 is to the left of the source - // and rect2 is below, then we always prefer the in beam rect1, since rect2 - // could be reached by going down. - if (!isToDirectionOf(direction, source, rect2)) { - return true; - } - - // for horizontal directions, being exclusively in beam always wins - if ((direction == View.FOCUS_LEFT || direction == View.FOCUS_RIGHT)) { - return true; - } - - // for vertical directions, beams only beat up to a point: - // now, as long as rect2 isn't completely closer, rect1 wins - // e.g for direction down, completely closer means for rect2's top - // edge to be closer to the source's top edge than rect1's bottom edge. - return (majorAxisDistance(direction, source, rect1) - < majorAxisDistanceToFarEdge(direction, source, rect2)); - } - - /** - * Fudge-factor opportunity: how to calculate distance given major and minor - * axis distances. Warning: this fudge factor is finely tuned, be sure to - * run all focus tests if you dare tweak it. - */ - int getWeightedDistanceFor(int majorAxisDistance, int minorAxisDistance) { - return 13 * majorAxisDistance * majorAxisDistance - + minorAxisDistance * minorAxisDistance; - } - - /** - * Is destRect a candidate for the next focus given the direction? This - * checks whether the dest is at least partially to the direction of (e.g left of) - * from source. - * - * Includes an edge case for an empty rect (which is used in some cases when - * searching from a point on the screen). - */ - boolean isCandidate(Rect srcRect, Rect destRect, int direction) { - switch (direction) { - case View.FOCUS_LEFT: - return (srcRect.right > destRect.right || srcRect.left >= destRect.right) - && srcRect.left > destRect.left; - case View.FOCUS_RIGHT: - return (srcRect.left < destRect.left || srcRect.right <= destRect.left) - && srcRect.right < destRect.right; - case View.FOCUS_UP: - return (srcRect.bottom > destRect.bottom || srcRect.top >= destRect.bottom) - && srcRect.top > destRect.top; - case View.FOCUS_DOWN: - return (srcRect.top < destRect.top || srcRect.bottom <= destRect.top) - && srcRect.bottom < destRect.bottom; - } - throw new IllegalArgumentException("direction must be one of " - + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}."); - } - - - /** - * Do the "beams" w.r.t the given direcition's axos of rect1 and rect2 overlap? - * @param direction the direction (up, down, left, right) - * @param rect1 The first rectangle - * @param rect2 The second rectangle - * @return whether the beams overlap - */ - boolean beamsOverlap(int direction, Rect rect1, Rect rect2) { - switch (direction) { - case View.FOCUS_LEFT: - case View.FOCUS_RIGHT: - return (rect2.bottom >= rect1.top) && (rect2.top <= rect1.bottom); - case View.FOCUS_UP: - case View.FOCUS_DOWN: - return (rect2.right >= rect1.left) && (rect2.left <= rect1.right); - } - throw new IllegalArgumentException("direction must be one of " - + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}."); - } - - /** - * e.g for left, is 'to left of' - */ - boolean isToDirectionOf(int direction, Rect src, Rect dest) { - switch (direction) { - case View.FOCUS_LEFT: - return src.left >= dest.right; - case View.FOCUS_RIGHT: - return src.right <= dest.left; - case View.FOCUS_UP: - return src.top >= dest.bottom; - case View.FOCUS_DOWN: - return src.bottom <= dest.top; - } - throw new IllegalArgumentException("direction must be one of " - + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}."); - } - - /** - * @return The distance from the edge furthest in the given direction - * of source to the edge nearest in the given direction of dest. If the - * dest is not in the direction from source, return 0. - */ - static int majorAxisDistance(int direction, Rect source, Rect dest) { - return Math.max(0, majorAxisDistanceRaw(direction, source, dest)); - } - - static int majorAxisDistanceRaw(int direction, Rect source, Rect dest) { - switch (direction) { - case View.FOCUS_LEFT: - return source.left - dest.right; - case View.FOCUS_RIGHT: - return dest.left - source.right; - case View.FOCUS_UP: - return source.top - dest.bottom; - case View.FOCUS_DOWN: - return dest.top - source.bottom; - } - throw new IllegalArgumentException("direction must be one of " - + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}."); - } - - /** - * @return The distance along the major axis w.r.t the direction from the - * edge of source to the far edge of dest. If the - * dest is not in the direction from source, return 1 (to break ties with - * {@link #majorAxisDistance}). - */ - static int majorAxisDistanceToFarEdge(int direction, Rect source, Rect dest) { - return Math.max(1, majorAxisDistanceToFarEdgeRaw(direction, source, dest)); - } - - static int majorAxisDistanceToFarEdgeRaw(int direction, Rect source, Rect dest) { - switch (direction) { - case View.FOCUS_LEFT: - return source.left - dest.left; - case View.FOCUS_RIGHT: - return dest.right - source.right; - case View.FOCUS_UP: - return source.top - dest.top; - case View.FOCUS_DOWN: - return dest.bottom - source.bottom; - } - throw new IllegalArgumentException("direction must be one of " - + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}."); - } - - /** - * Find the distance on the minor axis w.r.t the direction to the nearest - * edge of the destination rectange. - * @param direction the direction (up, down, left, right) - * @param source The source rect. - * @param dest The destination rect. - * @return The distance. - */ - static int minorAxisDistance(int direction, Rect source, Rect dest) { - switch (direction) { - case View.FOCUS_LEFT: - case View.FOCUS_RIGHT: - // the distance between the center verticals - return Math.abs( - ((source.top + source.height() / 2) - - ((dest.top + dest.height() / 2)))); - case View.FOCUS_UP: - case View.FOCUS_DOWN: - // the distance between the center horizontals - return Math.abs( - ((source.left + source.width() / 2) - - ((dest.left + dest.width() / 2)))); - } - throw new IllegalArgumentException("direction must be one of " - + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}."); - } - - /** - * Find the nearest touchable view to the specified view. - * - * @param root The root of the tree in which to search - * @param x X coordinate from which to start the search - * @param y Y coordinate from which to start the search - * @param direction Direction to look - * @param deltas Offset from the <x, y> to the edge of the nearest view. Note that this array - * may already be populated with values. - * @return The nearest touchable view, or null if none exists. - */ - public View findNearestTouchable(ViewGroup root, int x, int y, int direction, int[] deltas) { - ArrayList<View> touchables = root.getTouchables(); - int minDistance = Integer.MAX_VALUE; - View closest = null; - - int numTouchables = touchables.size(); - - int edgeSlop = ViewConfiguration.get(root.mContext).getScaledEdgeSlop(); - - Rect closestBounds = new Rect(); - Rect touchableBounds = mOtherRect; - - for (int i = 0; i < numTouchables; i++) { - View touchable = touchables.get(i); - - // get visible bounds of other view in same coordinate system - touchable.getDrawingRect(touchableBounds); - - root.offsetRectBetweenParentAndChild(touchable, touchableBounds, true, true); - - if (!isTouchCandidate(x, y, touchableBounds, direction)) { - continue; - } - - int distance = Integer.MAX_VALUE; - - switch (direction) { - case View.FOCUS_LEFT: - distance = x - touchableBounds.right + 1; - break; - case View.FOCUS_RIGHT: - distance = touchableBounds.left; - break; - case View.FOCUS_UP: - distance = y - touchableBounds.bottom + 1; - break; - case View.FOCUS_DOWN: - distance = touchableBounds.top; - break; - } - - if (distance < edgeSlop) { - // Give preference to innermost views - if (closest == null || - closestBounds.contains(touchableBounds) || - (!touchableBounds.contains(closestBounds) && distance < minDistance)) { - minDistance = distance; - closest = touchable; - closestBounds.set(touchableBounds); - switch (direction) { - case View.FOCUS_LEFT: - deltas[0] = -distance; - break; - case View.FOCUS_RIGHT: - deltas[0] = distance; - break; - case View.FOCUS_UP: - deltas[1] = -distance; - break; - case View.FOCUS_DOWN: - deltas[1] = distance; - break; - } - } - } - } - return closest; - } - - - /** - * Is destRect a candidate for the next touch given the direction? - */ - private boolean isTouchCandidate(int x, int y, Rect destRect, int direction) { - switch (direction) { - case View.FOCUS_LEFT: - return destRect.left <= x && destRect.top <= y && y <= destRect.bottom; - case View.FOCUS_RIGHT: - return destRect.left >= x && destRect.top <= y && y <= destRect.bottom; - case View.FOCUS_UP: - return destRect.top <= y && destRect.left <= x && x <= destRect.right; - case View.FOCUS_DOWN: - return destRect.top >= y && destRect.left <= x && x <= destRect.right; - } - throw new IllegalArgumentException("direction must be one of " - + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}."); - } -} diff --git a/core/java/android/view/FocusFinderHelper.java b/core/java/android/view/FocusFinderHelper.java deleted file mode 100644 index 69dc056..0000000 --- a/core/java/android/view/FocusFinderHelper.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2008 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.view; - -import android.graphics.Rect; - -/** - * A helper class that allows unit tests to access FocusFinder methods. - * @hide - */ -public class FocusFinderHelper { - - private FocusFinder mFocusFinder; - - /** - * Wrap the FocusFinder object - */ - public FocusFinderHelper(FocusFinder focusFinder) { - mFocusFinder = focusFinder; - } - - public boolean isBetterCandidate(int direction, Rect source, Rect rect1, Rect rect2) { - return mFocusFinder.isBetterCandidate(direction, source, rect1, rect2); - } - - public boolean beamBeats(int direction, Rect source, Rect rect1, Rect rect2) { - return mFocusFinder.beamBeats(direction, source, rect1, rect2); - } - - public boolean isCandidate(Rect srcRect, Rect destRect, int direction) { - return mFocusFinder.isCandidate(srcRect, destRect, direction); - } - - public boolean beamsOverlap(int direction, Rect rect1, Rect rect2) { - return mFocusFinder.beamsOverlap(direction, rect1, rect2); - } - - public static int majorAxisDistance(int direction, Rect source, Rect dest) { - return FocusFinder.majorAxisDistance(direction, source, dest); - } - - public static int majorAxisDistanceToFarEdge(int direction, Rect source, Rect dest) { - return FocusFinder.majorAxisDistanceToFarEdge(direction, source, dest); - } -} diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java deleted file mode 100644 index 679c683..0000000 --- a/core/java/android/view/GestureDetector.java +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright (C) 2008 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.view; - -import android.os.Handler; -import android.os.Message; -import android.content.Context; - -/** - * Detects various gestures and events using the supplied {@link MotionEvent}s. - * The {@link OnGestureListener} callback will notify users when a particular - * motion event has occurred. This class should only be used with {@link MotionEvent}s - * reported via touch (don't use for trackball events). - * - * To use this class: - * <ul> - * <li>Create an instance of the {@code GestureDetector} for your {@link View} - * <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call - * {@link #onTouchEvent(MotionEvent)}. The methods defined in your callback - * will be executed when the events occur. - * </ul> - */ -public class GestureDetector { - /** - * The listener that is used to notify when gestures occur. - * If you want to listen for all the different gestures then implement - * this interface. If you only want to listen for a subset it might - * be easier to extend {@link SimpleOnGestureListener}. - */ - public interface OnGestureListener { - - /** - * Notified when a tap occurs with the down {@link MotionEvent} - * that triggered it. This will be triggered immediately for - * every down event. All other events should be preceded by this. - * - * @param e The down motion event. - */ - boolean onDown(MotionEvent e); - - /** - * The user has performed a down {@link MotionEvent} and not performed - * a move or up yet. This event is commonly used to provide visual - * feedback to the user to let them know that their action has been - * recognized i.e. highlight an element. - * - * @param e The down motion event - */ - void onShowPress(MotionEvent e); - - /** - * Notified when a tap occurs with the up {@link MotionEvent} - * that triggered it. - * - * @param e The up motion event that completed the first tap - * @return true if the event is consumed, else false - */ - boolean onSingleTapUp(MotionEvent e); - - /** - * Notified when a scroll occurs with the initial on down {@link MotionEvent} and the - * current move {@link MotionEvent}. The distance in x and y is also supplied for - * convenience. - * - * @param e1 The first down motion event that started the scrolling. - * @param e2 The move motion event that triggered the current onScroll. - * @param distanceX The distance along the X axis that has been scrolled since the last - * call to onScroll. This is NOT the distance between {@code e1} - * and {@code e2}. - * @param distanceY The distance along the Y axis that has been scrolled since the last - * call to onScroll. This is NOT the distance between {@code e1} - * and {@code e2}. - * @return true if the event is consumed, else false - */ - boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY); - - /** - * Notified when a long press occurs with the initial on down {@link MotionEvent} - * that trigged it. - * - * @param e The initial on down motion event that started the longpress. - */ - void onLongPress(MotionEvent e); - - /** - * Notified of a fling event when it occurs with the initial on down {@link MotionEvent} - * and the matching up {@link MotionEvent}. The calculated velocity is supplied along - * the x and y axis in pixels per second. - * - * @param e1 The first down motion event that started the fling. - * @param e2 The move motion event that triggered the current onFling. - * @param velocityX The velocity of this fling measured in pixels per second - * along the x axis. - * @param velocityY The velocity of this fling measured in pixels per second - * along the y axis. - * @return true if the event is consumed, else false - */ - boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY); - } - - /** - * @hide pending API council - */ - public interface OnDoubleTapListener { - boolean onSingleTapConfirmed(MotionEvent e); - boolean onDoubleTapEvent(MotionEvent e); - } - - /** - * A convenience class to extend when you only want to listen for a - * subset of all the gestures. This implements all methods in the - * {@link OnGestureListener} but does nothing and return {@code false} - * for all applicable methods. - */ - public static class SimpleOnGestureListener implements OnGestureListener { - public boolean onSingleTapUp(MotionEvent e) { - return false; - } - - public void onLongPress(MotionEvent e) { - } - - public boolean onScroll(MotionEvent e1, MotionEvent e2, - float distanceX, float distanceY) { - return false; - } - - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, - float velocityY) { - return false; - } - - public void onShowPress(MotionEvent e) { - } - - public boolean onDown(MotionEvent e) { - return false; - } - } - - // TODO: ViewConfiguration - private int mBiggerTouchSlopSquare = 20 * 20; - - private int mTouchSlopSquare; - private int mDoubleTapSlopSquare; - private int mMinimumFlingVelocity; - - private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout(); - private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout(); - // TODO make new double-tap timeout, and define its events (i.e. either time - // between down-down or time between up-down) - private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout(); - - // constants for Message.what used by GestureHandler below - private static final int SHOW_PRESS = 1; - private static final int LONG_PRESS = 2; - private static final int TAP = 3; - - private final Handler mHandler; - private final OnGestureListener mListener; - private OnDoubleTapListener mDoubleTapListener; - - private boolean mStillDown; - private boolean mInLongPress; - private boolean mAlwaysInTapRegion; - private boolean mAlwaysInBiggerTapRegion; - - private MotionEvent mCurrentDownEvent; - private MotionEvent mPreviousUpEvent; - - /** - * True when the user is still touching for the second tap (down, move, and - * up events). Can only be true if there is a double tap listener attached. - */ - private boolean mIsDoubleTapping; - - private float mLastMotionY; - private float mLastMotionX; - - private boolean mIsLongpressEnabled; - - /** - * Determines speed during touch scrolling - */ - private VelocityTracker mVelocityTracker; - - private class GestureHandler extends Handler { - GestureHandler() { - super(); - } - - GestureHandler(Handler handler) { - super(handler.getLooper()); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case SHOW_PRESS: - mListener.onShowPress(mCurrentDownEvent); - break; - - case LONG_PRESS: - dispatchLongPress(); - break; - - case TAP: - // If the user's finger is still down, do not count it as a tap - if (mDoubleTapListener != null && !mStillDown) { - mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent); - } - break; - - default: - throw new RuntimeException("Unknown message " + msg); //never - } - } - } - - /** - * Creates a GestureDetector with the supplied listener. - * This variant of the constructor should be used from a non-UI thread - * (as it allows specifying the Handler). - * - * @param listener the listener invoked for all the callbacks, this must - * not be null. - * @param handler the handler to use - * - * @throws NullPointerException if either {@code listener} or - * {@code handler} is null. - * - * @deprecated Use {@link #GestureDetector(android.content.Context, - * android.view.GestureDetector.OnGestureListener, android.os.Handler)} instead. - */ - @Deprecated - public GestureDetector(OnGestureListener listener, Handler handler) { - this(null, listener, handler); - } - - /** - * Creates a GestureDetector with the supplied listener. - * You may only use this constructor from a UI thread (this is the usual situation). - * @see android.os.Handler#Handler() - * - * @param listener the listener invoked for all the callbacks, this must - * not be null. - * - * @throws NullPointerException if {@code listener} is null. - * - * @deprecated Use {@link #GestureDetector(android.content.Context, - * android.view.GestureDetector.OnGestureListener)} instead. - */ - @Deprecated - public GestureDetector(OnGestureListener listener) { - this(null, listener, null); - } - - /** - * Creates a GestureDetector with the supplied listener. - * You may only use this constructor from a UI thread (this is the usual situation). - * @see android.os.Handler#Handler() - * - * @param context the application's context - * @param listener the listener invoked for all the callbacks, this must - * not be null. - * - * @throws NullPointerException if {@code listener} is null. - */ - public GestureDetector(Context context, OnGestureListener listener) { - this(context, listener, null); - } - - /** - * Creates a GestureDetector with the supplied listener. - * You may only use this constructor from a UI thread (this is the usual situation). - * @see android.os.Handler#Handler() - * - * @param context the application's context - * @param listener the listener invoked for all the callbacks, this must - * not be null. - * @param handler the handler to use - * - * @throws NullPointerException if {@code listener} is null. - */ - public GestureDetector(Context context, OnGestureListener listener, Handler handler) { - if (handler != null) { - mHandler = new GestureHandler(handler); - } else { - mHandler = new GestureHandler(); - } - mListener = listener; - init(context); - } - - private void init(Context context) { - if (mListener == null) { - throw new NullPointerException("OnGestureListener must not be null"); - } - mIsLongpressEnabled = true; - - // Fallback to support pre-donuts releases - int touchSlop, doubleTapSlop; - if (context == null) { - //noinspection deprecation - touchSlop = ViewConfiguration.getTouchSlop(); - doubleTapSlop = ViewConfiguration.getDoubleTapSlop(); - //noinspection deprecation - mMinimumFlingVelocity = ViewConfiguration.getMinimumFlingVelocity(); - } else { - final ViewConfiguration configuration = ViewConfiguration.get(context); - touchSlop = configuration.getScaledTouchSlop(); - doubleTapSlop = configuration.getScaledDoubleTapSlop(); - mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity(); - } - mTouchSlopSquare = touchSlop * touchSlop; - mDoubleTapSlopSquare = doubleTapSlop * doubleTapSlop; - } - - /** - * @hide pending API council - * @param onDoubleTapListener - */ - public void setOnDoubleTapListener(OnDoubleTapListener onDoubleTapListener) { - mDoubleTapListener = onDoubleTapListener; - } - - /** - * Set whether longpress is enabled, if this is enabled when a user - * presses and holds down you get a longpress event and nothing further. - * If it's disabled the user can press and hold down and then later - * moved their finger and you will get scroll events. By default - * longpress is enabled. - * - * @param isLongpressEnabled whether longpress should be enabled. - */ - public void setIsLongpressEnabled(boolean isLongpressEnabled) { - mIsLongpressEnabled = isLongpressEnabled; - } - - /** - * @return true if longpress is enabled, else false. - */ - public boolean isLongpressEnabled() { - return mIsLongpressEnabled; - } - - /** - * Analyzes the given motion event and if applicable triggers the - * appropriate callbacks on the {@link OnGestureListener} supplied. - * - * @param ev The current motion event. - * @return true if the {@link OnGestureListener} consumed the event, - * else false. - */ - public boolean onTouchEvent(MotionEvent ev) { - final int action = ev.getAction(); - final float y = ev.getY(); - final float x = ev.getX(); - - if (mVelocityTracker == null) { - mVelocityTracker = VelocityTracker.obtain(); - } - mVelocityTracker.addMovement(ev); - - boolean handled = false; - - switch (action) { - case MotionEvent.ACTION_DOWN: - if (mDoubleTapListener != null) { - boolean hadTapMessage = mHandler.hasMessages(TAP); - if (hadTapMessage) mHandler.removeMessages(TAP); - if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) && hadTapMessage && - isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) { - // This is a second tap - mIsDoubleTapping = true; - handled = mDoubleTapListener.onDoubleTapEvent(ev); - } else { - // This is a first tap - mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT); - } - } - - mLastMotionX = x; - mLastMotionY = y; - mCurrentDownEvent = MotionEvent.obtain(ev); - mAlwaysInTapRegion = true; - mAlwaysInBiggerTapRegion = true; - mStillDown = true; - mInLongPress = false; - - if (mIsLongpressEnabled) { - mHandler.removeMessages(LONG_PRESS); - mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime() - + TAP_TIMEOUT + LONGPRESS_TIMEOUT); - } - mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT); - handled |= mListener.onDown(ev); - break; - - case MotionEvent.ACTION_MOVE: - if (mInLongPress) { - break; - } - final float scrollX = mLastMotionX - x; - final float scrollY = mLastMotionY - y; - if (mIsDoubleTapping) { - handled = mDoubleTapListener.onDoubleTapEvent(ev); - } else if (mAlwaysInTapRegion) { - final int deltaX = (int) (x - mCurrentDownEvent.getX()); - final int deltaY = (int) (y - mCurrentDownEvent.getY()); - int distance = (deltaX * deltaX) + (deltaY * deltaY); - if (distance > mTouchSlopSquare) { - handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY); - mLastMotionX = x; - mLastMotionY = y; - mAlwaysInTapRegion = false; - mHandler.removeMessages(TAP); - mHandler.removeMessages(SHOW_PRESS); - mHandler.removeMessages(LONG_PRESS); - } - if (distance > mBiggerTouchSlopSquare) { - mAlwaysInBiggerTapRegion = false; - } - } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) { - handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY); - mLastMotionX = x; - mLastMotionY = y; - } - break; - - case MotionEvent.ACTION_UP: - mStillDown = false; - MotionEvent currentUpEvent = MotionEvent.obtain(ev); - if (mIsDoubleTapping) { - handled = mDoubleTapListener.onDoubleTapEvent(ev); - mIsDoubleTapping = false; - break; - } else if (mInLongPress) { - mHandler.removeMessages(TAP); - mInLongPress = false; - break; - } - if (mAlwaysInTapRegion) { - handled = mListener.onSingleTapUp(ev); - } else { - - // A fling must travel the minimum tap distance - final VelocityTracker velocityTracker = mVelocityTracker; - velocityTracker.computeCurrentVelocity(1000); - final float velocityY = velocityTracker.getYVelocity(); - final float velocityX = velocityTracker.getXVelocity(); - - if ((Math.abs(velocityY) > mMinimumFlingVelocity) - || (Math.abs(velocityX) > mMinimumFlingVelocity)){ - handled = mListener.onFling(mCurrentDownEvent, currentUpEvent, velocityX, velocityY); - } - } - mPreviousUpEvent = MotionEvent.obtain(ev); - mVelocityTracker.recycle(); - mVelocityTracker = null; - mHandler.removeMessages(SHOW_PRESS); - mHandler.removeMessages(LONG_PRESS); - break; - case MotionEvent.ACTION_CANCEL: - mHandler.removeMessages(SHOW_PRESS); - mHandler.removeMessages(LONG_PRESS); - mHandler.removeMessages(TAP); - mVelocityTracker.recycle(); - mVelocityTracker = null; - mStillDown = false; - if (mInLongPress) { - mInLongPress = false; - break; - } - } - return handled; - } - - private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp, - MotionEvent secondDown) { - if (!mAlwaysInBiggerTapRegion) { - return false; - } - - if (secondDown.getEventTime() - firstUp.getEventTime() > DOUBLE_TAP_TIMEOUT) { - return false; - } - - int deltaX = (int) firstDown.getX() - (int) secondDown.getX(); - int deltaY = (int) firstDown.getY() - (int) secondDown.getY(); - return (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare); - } - - private void dispatchLongPress() { - mHandler.removeMessages(TAP); - mInLongPress = true; - mListener.onLongPress(mCurrentDownEvent); - } -} diff --git a/core/java/android/view/Gravity.java b/core/java/android/view/Gravity.java deleted file mode 100644 index 36d8ce6..0000000 --- a/core/java/android/view/Gravity.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; -import android.graphics.Rect; - -/** - * Standard constants and tools for placing an object within a potentially - * larger container. - */ -public class Gravity -{ - /** Constant indicating that no gravity has been set **/ - public static final int NO_GRAVITY = 0x0000; - - /** Raw bit indicating the gravity for an axis has been specified. */ - public static final int AXIS_SPECIFIED = 0x0001; - - /** Raw bit controlling how the left/top edge is placed. */ - public static final int AXIS_PULL_BEFORE = 0x0002; - /** Raw bit controlling how the right/bottom edge is placed. */ - public static final int AXIS_PULL_AFTER = 0x0004; - /** Raw bit controlling whether the right/bottom edge is clipped to its - * container, based on the gravity direction being applied. */ - public static final int AXIS_CLIP = 0x0008; - - /** Bits defining the horizontal axis. */ - public static final int AXIS_X_SHIFT = 0; - /** Bits defining the vertical axis. */ - public static final int AXIS_Y_SHIFT = 4; - - /** Push object to the top of its container, not changing its size. */ - public static final int TOP = (AXIS_PULL_BEFORE|AXIS_SPECIFIED)<<AXIS_Y_SHIFT; - /** Push object to the bottom of its container, not changing its size. */ - public static final int BOTTOM = (AXIS_PULL_AFTER|AXIS_SPECIFIED)<<AXIS_Y_SHIFT; - /** Push object to the left of its container, not changing its size. */ - public static final int LEFT = (AXIS_PULL_BEFORE|AXIS_SPECIFIED)<<AXIS_X_SHIFT; - /** Push object to the right of its container, not changing its size. */ - public static final int RIGHT = (AXIS_PULL_AFTER|AXIS_SPECIFIED)<<AXIS_X_SHIFT; - - /** Place object in the vertical center of its container, not changing its - * size. */ - public static final int CENTER_VERTICAL = AXIS_SPECIFIED<<AXIS_Y_SHIFT; - /** Grow the vertical size of the object if needed so it completely fills - * its container. */ - public static final int FILL_VERTICAL = TOP|BOTTOM; - - /** Place object in the horizontal center of its container, not changing its - * size. */ - public static final int CENTER_HORIZONTAL = AXIS_SPECIFIED<<AXIS_X_SHIFT; - /** Grow the horizontal size of the object if needed so it completely fills - * its container. */ - public static final int FILL_HORIZONTAL = LEFT|RIGHT; - - /** Place the object in the center of its container in both the vertical - * and horizontal axis, not changing its size. */ - public static final int CENTER = CENTER_VERTICAL|CENTER_HORIZONTAL; - - /** Grow the horizontal and vertical size of the object if needed so it - * completely fills its container. */ - public static final int FILL = FILL_VERTICAL|FILL_HORIZONTAL; - - /** Flag to clip the edges of the object to its container along the - * vertical axis. */ - public static final int CLIP_VERTICAL = AXIS_CLIP<<AXIS_Y_SHIFT; - - /** Flag to clip the edges of the object to its container along the - * horizontal axis. */ - public static final int CLIP_HORIZONTAL = AXIS_CLIP<<AXIS_X_SHIFT; - - /** - * Binary mask to get the horizontal gravity of a gravity. - */ - public static final int HORIZONTAL_GRAVITY_MASK = (AXIS_SPECIFIED | - AXIS_PULL_BEFORE | AXIS_PULL_AFTER) << AXIS_X_SHIFT; - /** - * Binary mask to get the vertical gravity of a gravity. - */ - public static final int VERTICAL_GRAVITY_MASK = (AXIS_SPECIFIED | - AXIS_PULL_BEFORE | AXIS_PULL_AFTER) << AXIS_Y_SHIFT; - - /** Special constant to enable clipping to an overall display along the - * vertical dimension. This is not applied by default by - * {@link #apply(int, int, int, Rect, int, int, Rect)}; you must do so - * yourself by calling {@link #applyDisplay}. - */ - public static final int DISPLAY_CLIP_VERTICAL = 0x10000000; - - /** Special constant to enable clipping to an overall display along the - * horizontal dimension. This is not applied by default by - * {@link #apply(int, int, int, Rect, int, int, Rect)}; you must do so - * yourself by calling {@link #applyDisplay}. - */ - public static final int DISPLAY_CLIP_HORIZONTAL = 0x01000000; - - /** - * Apply a gravity constant to an object. - * - * @param gravity The desired placement of the object, as defined by the - * constants in this class. - * @param w The horizontal size of the object. - * @param h The vertical size of the object. - * @param container The frame of the containing space, in which the object - * will be placed. Should be large enough to contain the - * width and height of the object. - * @param outRect Receives the computed frame of the object in its - * container. - */ - public static void apply(int gravity, int w, int h, Rect container, - Rect outRect) { - apply(gravity, w, h, container, 0, 0, outRect); - } - - /** - * Apply a gravity constant to an object. - * - * @param gravity The desired placement of the object, as defined by the - * constants in this class. - * @param w The horizontal size of the object. - * @param h The vertical size of the object. - * @param container The frame of the containing space, in which the object - * will be placed. Should be large enough to contain the - * width and height of the object. - * @param xAdj Offset to apply to the X axis. If gravity is LEFT this - * pushes it to the right; if gravity is RIGHT it pushes it to - * the left; if gravity is CENTER_HORIZONTAL it pushes it to the - * right or left; otherwise it is ignored. - * @param yAdj Offset to apply to the Y axis. If gravity is TOP this pushes - * it down; if gravity is BOTTOM it pushes it up; if gravity is - * CENTER_VERTICAL it pushes it down or up; otherwise it is - * ignored. - * @param outRect Receives the computed frame of the object in its - * container. - */ - public static void apply(int gravity, int w, int h, Rect container, - int xAdj, int yAdj, Rect outRect) { - switch (gravity&((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_X_SHIFT)) { - case 0: - outRect.left = container.left - + ((container.right - container.left - w)/2) + xAdj; - outRect.right = outRect.left + w; - if ((gravity&(AXIS_CLIP<<AXIS_X_SHIFT)) - == (AXIS_CLIP<<AXIS_X_SHIFT)) { - if (outRect.left < container.left) { - outRect.left = container.left; - } - if (outRect.right > container.right) { - outRect.right = container.right; - } - } - break; - case AXIS_PULL_BEFORE<<AXIS_X_SHIFT: - outRect.left = container.left + xAdj; - outRect.right = outRect.left + w; - if ((gravity&(AXIS_CLIP<<AXIS_X_SHIFT)) - == (AXIS_CLIP<<AXIS_X_SHIFT)) { - if (outRect.right > container.right) { - outRect.right = container.right; - } - } - break; - case AXIS_PULL_AFTER<<AXIS_X_SHIFT: - outRect.right = container.right - xAdj; - outRect.left = outRect.right - w; - if ((gravity&(AXIS_CLIP<<AXIS_X_SHIFT)) - == (AXIS_CLIP<<AXIS_X_SHIFT)) { - if (outRect.left < container.left) { - outRect.left = container.left; - } - } - break; - default: - outRect.left = container.left + xAdj; - outRect.right = container.right + xAdj; - break; - } - - switch (gravity&((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_Y_SHIFT)) { - case 0: - outRect.top = container.top - + ((container.bottom - container.top - h)/2) + yAdj; - outRect.bottom = outRect.top + h; - if ((gravity&(AXIS_CLIP<<AXIS_Y_SHIFT)) - == (AXIS_CLIP<<AXIS_Y_SHIFT)) { - if (outRect.top < container.top) { - outRect.top = container.top; - } - if (outRect.bottom > container.bottom) { - outRect.bottom = container.bottom; - } - } - break; - case AXIS_PULL_BEFORE<<AXIS_Y_SHIFT: - outRect.top = container.top + yAdj; - outRect.bottom = outRect.top + h; - if ((gravity&(AXIS_CLIP<<AXIS_Y_SHIFT)) - == (AXIS_CLIP<<AXIS_Y_SHIFT)) { - if (outRect.bottom > container.bottom) { - outRect.bottom = container.bottom; - } - } - break; - case AXIS_PULL_AFTER<<AXIS_Y_SHIFT: - outRect.bottom = container.bottom - yAdj; - outRect.top = outRect.bottom - h; - if ((gravity&(AXIS_CLIP<<AXIS_Y_SHIFT)) - == (AXIS_CLIP<<AXIS_Y_SHIFT)) { - if (outRect.top < container.top) { - outRect.top = container.top; - } - } - break; - default: - outRect.top = container.top + yAdj; - outRect.bottom = container.bottom + yAdj; - break; - } - } - - /** - * Apply addition gravity behavior based on the overall "display" that an - * object exists in. This can be used after - * {@link #apply(int, int, int, Rect, int, int, Rect)} to place the object - * within a visible display. By default this moves or clips the object - * to be visible in the display; the gravity flags - * {@link #DISPLAY_CLIP_HORIZONTAL} and {@link #DISPLAY_CLIP_VERTICAL} - * can be used to change this behavior. - * - * @param gravity Gravity constants to modify the placement within the - * display. - * @param display The rectangle of the display in which the object is - * being placed. - * @param inoutObj Supplies the current object position; returns with it - * modified if needed to fit in the display. - */ - public static void applyDisplay(int gravity, Rect display, Rect inoutObj) { - if ((gravity&DISPLAY_CLIP_VERTICAL) != 0) { - if (inoutObj.top < display.top) inoutObj.top = display.top; - if (inoutObj.bottom > display.bottom) inoutObj.bottom = display.bottom; - } else { - int off = 0; - if (inoutObj.top < display.top) off = display.top-inoutObj.top; - else if (inoutObj.bottom > display.bottom) off = display.bottom-inoutObj.bottom; - if (off != 0) { - if (inoutObj.height() > (display.bottom-display.top)) { - inoutObj.top = display.top; - inoutObj.bottom = display.bottom; - } else { - inoutObj.top += off; - inoutObj.bottom += off; - } - } - } - - if ((gravity&DISPLAY_CLIP_HORIZONTAL) != 0) { - if (inoutObj.left < display.left) inoutObj.left = display.left; - if (inoutObj.right > display.right) inoutObj.right = display.right; - } else { - int off = 0; - if (inoutObj.left < display.left) off = display.left-inoutObj.left; - else if (inoutObj.right > display.right) off = display.right-inoutObj.right; - if (off != 0) { - if (inoutObj.width() > (display.right-display.left)) { - inoutObj.left = display.left; - inoutObj.right = display.right; - } else { - inoutObj.left += off; - inoutObj.right += off; - } - } - } - } - - /** - * <p>Indicate whether the supplied gravity has a vertical pull.</p> - * - * @param gravity the gravity to check for vertical pull - * @return true if the supplied gravity has a vertical pull - */ - public static boolean isVertical(int gravity) { - return gravity > 0 && (gravity & VERTICAL_GRAVITY_MASK) != 0; - } - - /** - * <p>Indicate whether the supplied gravity has an horizontal pull.</p> - * - * @param gravity the gravity to check for horizontal pull - * @return true if the supplied gravity has an horizontal pull - */ - public static boolean isHorizontal(int gravity) { - return gravity > 0 && (gravity & HORIZONTAL_GRAVITY_MASK) != 0; - } -} diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java deleted file mode 100644 index cc3563c..0000000 --- a/core/java/android/view/HapticFeedbackConstants.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2009 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.view; - -/** - * Constants to be used to perform haptic feedback effects via - * {@link View#performHapticFeedback(int)} - */ -public class HapticFeedbackConstants { - - private HapticFeedbackConstants() {} - - public static final int LONG_PRESS = 0; - - /** @hide pending API council */ - public static final int ZOOM_RING_TICK = 1; - - /** - * Flag for {@link View#performHapticFeedback(int, int) - * View.performHapticFeedback(int, int)}: Ignore the setting in the - * view for whether to perform haptic feedback, do it always. - */ - public static final int FLAG_IGNORE_VIEW_SETTING = 0x0001; - - /** - * Flag for {@link View#performHapticFeedback(int, int) - * View.performHapticFeedback(int, int)}: Ignore the global setting - * for whether to perform haptic feedback, do it always. - */ - public static final int FLAG_IGNORE_GLOBAL_SETTING = 0x0002; -} diff --git a/core/java/android/view/IApplicationToken.aidl b/core/java/android/view/IApplicationToken.aidl deleted file mode 100644 index 6bff5b3..0000000 --- a/core/java/android/view/IApplicationToken.aidl +++ /dev/null @@ -1,28 +0,0 @@ -/* //device/java/android/android/view/IApplicationToken.aidl -** -** Copyright 2007, 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.view; - -/** {@hide} */ -interface IApplicationToken -{ - void windowsVisible(); - void windowsGone(); - boolean keyDispatchingTimedOut(); - long getKeyDispatchingTimeout(); -} - diff --git a/core/java/android/view/IOnKeyguardExitResult.aidl b/core/java/android/view/IOnKeyguardExitResult.aidl deleted file mode 100644 index 47d5220..0000000 --- a/core/java/android/view/IOnKeyguardExitResult.aidl +++ /dev/null @@ -1,25 +0,0 @@ -/* //device/java/android/android/hardware/ISensorListener.aidl -** -** Copyright 2008, 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.view; - -/** @hide */ -oneway interface IOnKeyguardExitResult { - - void onKeyguardExitResult(boolean success); - -} diff --git a/core/java/android/view/IRotationWatcher.aidl b/core/java/android/view/IRotationWatcher.aidl deleted file mode 100644 index 2c83642..0000000 --- a/core/java/android/view/IRotationWatcher.aidl +++ /dev/null @@ -1,25 +0,0 @@ -/* //device/java/android/android/hardware/ISensorListener.aidl -** -** Copyright 2008, 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.view; - -/** - * {@hide} - */ -oneway interface IRotationWatcher { - void onRotationChanged(int rotation); -} diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl deleted file mode 100644 index 99d5c0c..0000000 --- a/core/java/android/view/IWindow.aidl +++ /dev/null @@ -1,59 +0,0 @@ -/* //device/java/android/android/view/IWindow.aidl -** -** Copyright 2007, 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.view; - -import android.graphics.Rect; -import android.view.KeyEvent; -import android.view.MotionEvent; - -import android.os.ParcelFileDescriptor; - -/** - * API back to a client window that the Window Manager uses to inform it of - * interesting things happening. - * - * {@hide} - */ -oneway interface IWindow { - /** - * ===== NOTICE ===== - * The first method must remain the first method. Scripts - * and tools rely on their transaction number to work properly. - */ - - /** - * Invoked by the view server to tell a window to execute the specified - * command. Any response from the receiver must be sent through the - * specified file descriptor. - */ - void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor); - - void resized(int w, int h, in Rect coveredInsets, in Rect visibleInsets, - boolean reportDraw); - void dispatchKey(in KeyEvent event); - void dispatchPointer(in MotionEvent event, long eventTime); - void dispatchTrackball(in MotionEvent event, long eventTime); - void dispatchAppVisibility(boolean visible); - void dispatchGetNewSurface(); - - /** - * Tell the window that it is either gaining or losing focus. Keep it up - * to date on the current state showing navigational focus (touch mode) too. - */ - void windowFocusChanged(boolean hasFocus, boolean inTouchMode); -} diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl deleted file mode 100644 index a856b24..0000000 --- a/core/java/android/view/IWindowManager.aidl +++ /dev/null @@ -1,136 +0,0 @@ -/* //device/java/android/android/view/IWindowManager.aidl -** -** 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. -*/ - -package android.view; - -import com.android.internal.view.IInputContext; -import com.android.internal.view.IInputMethodClient; - -import android.content.res.Configuration; -import android.view.IApplicationToken; -import android.view.IOnKeyguardExitResult; -import android.view.IRotationWatcher; -import android.view.IWindowSession; -import android.view.KeyEvent; -import android.view.MotionEvent; - -/** - * System private interface to the window manager. - * - * {@hide} - */ -interface IWindowManager -{ - /** - * ===== NOTICE ===== - * The first three methods must remain the first three methods. Scripts - * and tools rely on their transaction number to work properly. - */ - // This is used for debugging - boolean startViewServer(int port); // Transaction #1 - boolean stopViewServer(); // Transaction #2 - boolean isViewServerRunning(); // Transaction #3 - - IWindowSession openSession(in IInputMethodClient client, - in IInputContext inputContext); - boolean inputMethodClientHasFocus(IInputMethodClient client); - - // These can only be called when injecting events to your own window, - // or by holding the INJECT_EVENTS permission. - boolean injectKeyEvent(in KeyEvent ev, boolean sync); - boolean injectPointerEvent(in MotionEvent ev, boolean sync); - boolean injectTrackballEvent(in MotionEvent ev, boolean sync); - - // These can only be called when holding the MANAGE_APP_TOKENS permission. - void pauseKeyDispatching(IBinder token); - void resumeKeyDispatching(IBinder token); - void setEventDispatching(boolean enabled); - void addAppToken(int addPos, IApplicationToken token, - int groupId, int requestedOrientation, boolean fullscreen); - void setAppGroupId(IBinder token, int groupId); - Configuration updateOrientationFromAppTokens(IBinder freezeThisOneIfNeeded); - void setAppOrientation(IApplicationToken token, int requestedOrientation); - int getAppOrientation(IApplicationToken token); - void setFocusedApp(IBinder token, boolean moveFocusNow); - void prepareAppTransition(int transit); - int getPendingAppTransition(); - void executeAppTransition(); - void setAppStartingWindow(IBinder token, String pkg, int theme, - CharSequence nonLocalizedLabel, int labelRes, - int icon, IBinder transferFrom, boolean createIfNeeded); - void setAppWillBeHidden(IBinder token); - void setAppVisibility(IBinder token, boolean visible); - void startAppFreezingScreen(IBinder token, int configChanges); - void stopAppFreezingScreen(IBinder token, boolean force); - void removeAppToken(IBinder token); - void moveAppToken(int index, IBinder token); - void moveAppTokensToTop(in List<IBinder> tokens); - void moveAppTokensToBottom(in List<IBinder> tokens); - void addWindowToken(IBinder token, int type); - void removeWindowToken(IBinder token); - - // these require DISABLE_KEYGUARD permission - void disableKeyguard(IBinder token, String tag); - void reenableKeyguard(IBinder token); - void exitKeyguardSecurely(IOnKeyguardExitResult callback); - boolean inKeyguardRestrictedInputMode(); - - - // These can only be called with the SET_ANIMATON_SCALE permission. - float getAnimationScale(int which); - float[] getAnimationScales(); - void setAnimationScale(int which, float scale); - void setAnimationScales(in float[] scales); - - // These require the READ_INPUT_STATE permission. - int getSwitchState(int sw); - int getSwitchStateForDevice(int devid, int sw); - int getScancodeState(int sw); - int getScancodeStateForDevice(int devid, int sw); - int getKeycodeState(int sw); - int getKeycodeStateForDevice(int devid, int sw); - - // Report whether the hardware supports the given keys; returns true if successful - boolean hasKeys(in int[] keycodes, inout boolean[] keyExists); - - // For testing - void setInTouchMode(boolean showFocus); - - // These can only be called with the SET_ORIENTATION permission. - /** - * Change the current screen rotation, constants as per - * {@link android.view.Surface}. - * @param rotation the intended rotation. - * @param alwaysSendConfiguration Flag to force a new configuration to - * be evaluated. This can be used when there are other parameters in - * configuration that are changing. - * {@link android.view.Surface}. - */ - void setRotation(int rotation, boolean alwaysSendConfiguration); - - /** - * Retrieve the current screen orientation, constants as per - * {@link android.view.Surface}. - */ - int getRotation(); - - /** - * Watch the rotation of the screen. Returns the current rotation, - * calls back when it changes. - */ - int watchRotation(IRotationWatcher watcher); -} diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl deleted file mode 100644 index 1156856..0000000 --- a/core/java/android/view/IWindowSession.aidl +++ /dev/null @@ -1,111 +0,0 @@ -/* //device/java/android/android/view/IWindowSession.aidl -** -** 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. -*/ - -package android.view; - -import android.graphics.Rect; -import android.graphics.Region; -import android.view.IWindow; -import android.view.MotionEvent; -import android.view.WindowManager; -import android.view.Surface; - -/** - * System private per-application interface to the window manager. - * - * {@hide} - */ -interface IWindowSession { - int add(IWindow window, in WindowManager.LayoutParams attrs, - in int viewVisibility, out Rect outContentInsets); - void remove(IWindow window); - - /** - * Change the parameters of a window. You supply the - * new parameters, it returns the new frame of the window on screen (the - * position should be ignored) and surface of the window. The surface - * will be invalid if the window is currently hidden, else you can use it - * to draw the window's contents. - * - * @param window The window being modified. - * @param attrs If non-null, new attributes to apply to the window. - * @param requestedWidth The width the window wants to be. - * @param requestedHeight The height the window wants to be. - * @param viewVisibility Window root view's visibility. - * @param insetsPending Set to true if the client will be later giving - * internal insets; as a result, the window will not impact other window - * layouts until the insets are given. - * @param outFrame Rect in which is placed the new position/size on - * screen. - * @param outContentInsets Rect in which is placed the offsets from - * <var>outFrame</var> in which the content of the window should be - * placed. This can be used to modify the window layout to ensure its - * contents are visible to the user, taking into account system windows - * like the status bar or a soft keyboard. - * @param outVisibleInsets Rect in which is placed the offsets from - * <var>outFrame</var> in which the window is actually completely visible - * to the user. This can be used to temporarily scroll the window's - * contents to make sure the user can see it. This is different than - * <var>outContentInsets</var> in that these insets change transiently, - * so complex relayout of the window should not happen based on them. - * @param outSurface Object in which is placed the new display surface. - * - * @return int Result flags: {@link WindowManagerImpl#RELAYOUT_SHOW_FOCUS}, - * {@link WindowManagerImpl#RELAYOUT_FIRST_TIME}. - */ - int relayout(IWindow window, in WindowManager.LayoutParams attrs, - int requestedWidth, int requestedHeight, int viewVisibility, - boolean insetsPending, out Rect outFrame, out Rect outContentInsets, - out Rect outVisibleInsets, out Surface outSurface); - - /** - * Give the window manager a hint of the part of the window that is - * completely transparent, allowing it to work with the surface flinger - * to optimize compositing of this part of the window. - */ - void setTransparentRegion(IWindow window, in Region region); - - /** - * Tell the window manager about the content and visible insets of the - * given window, which can be used to adjust the <var>outContentInsets</var> - * and <var>outVisibleInsets</var> values returned by - * {@link #relayout relayout()} for windows behind this one. - * - * @param touchableInsets Controls which part of the window inside of its - * frame can receive pointer events, as defined by - * {@link android.view.ViewTreeObserver.InternalInsetsInfo}. - */ - void setInsets(IWindow window, int touchableInsets, in Rect contentInsets, - in Rect visibleInsets); - - /** - * Return the current display size in which the window is being laid out, - * accounting for screen decorations around it. - */ - void getDisplayFrame(IWindow window, out Rect outDisplayFrame); - - void finishDrawing(IWindow window); - - void finishKey(IWindow window); - MotionEvent getPendingPointerMove(IWindow window); - MotionEvent getPendingTrackballMove(IWindow window); - - void setInTouchMode(boolean showFocus); - boolean getInTouchMode(); - - boolean performHapticFeedback(IWindow window, int effectId, boolean always); -} diff --git a/core/java/android/view/InflateException.java b/core/java/android/view/InflateException.java deleted file mode 100644 index 7b39d33..0000000 --- a/core/java/android/view/InflateException.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2007 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.view; - -/** - * This exception is thrown by an inflater on error conditions. - */ -public class InflateException extends RuntimeException { - - public InflateException() { - super(); - } - - public InflateException(String detailMessage, Throwable throwable) { - super(detailMessage, throwable); - } - - public InflateException(String detailMessage) { - super(detailMessage); - } - - public InflateException(Throwable throwable) { - super(throwable); - } - -} diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java deleted file mode 100644 index 25958aa..0000000 --- a/core/java/android/view/KeyCharacterMap.java +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright (C) 2007 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.view; - -import android.text.method.MetaKeyKeyListener; -import android.util.SparseIntArray; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.SystemClock; -import android.util.SparseArray; - -import java.lang.Character; -import java.lang.ref.WeakReference; - -public class KeyCharacterMap -{ - /** - * The id of the device's primary built in keyboard is always 0. - */ - public static final int BUILT_IN_KEYBOARD = 0; - - /** A numeric (12-key) keyboard. */ - public static final int NUMERIC = 1; - - /** A keyboard with all the letters, but with more than one letter - * per key. */ - public static final int PREDICTIVE = 2; - - /** A keyboard with all the letters, and maybe some numbers. */ - public static final int ALPHA = 3; - - /** - * This private-use character is used to trigger Unicode character - * input by hex digits. - */ - public static final char HEX_INPUT = '\uEF00'; - - /** - * This private-use character is used to bring up a character picker for - * miscellaneous symbols. - */ - public static final char PICKER_DIALOG_INPUT = '\uEF01'; - - private static Object sLock = new Object(); - private static SparseArray<WeakReference<KeyCharacterMap>> sInstances - = new SparseArray<WeakReference<KeyCharacterMap>>(); - - public static KeyCharacterMap load(int keyboard) - { - synchronized (sLock) { - KeyCharacterMap result; - WeakReference<KeyCharacterMap> ref = sInstances.get(keyboard); - if (ref != null) { - result = ref.get(); - if (result != null) { - return result; - } - } - result = new KeyCharacterMap(keyboard); - sInstances.put(keyboard, new WeakReference<KeyCharacterMap>(result)); - return result; - } - } - - private KeyCharacterMap(int keyboardDevice) - { - mKeyboardDevice = keyboardDevice; - mPointer = ctor_native(keyboardDevice); - } - - /** - * <p> - * Returns the Unicode character that the specified key would produce - * when the specified meta bits (see {@link MetaKeyKeyListener}) - * were active. - * </p><p> - * Returns 0 if the key is not one that is used to type Unicode - * characters. - * </p><p> - * If the return value has bit {@link #COMBINING_ACCENT} set, the - * key is a "dead key" that should be combined with another to - * actually produce a character -- see {@link #getDeadChar} -- - * after masking with {@link #COMBINING_ACCENT_MASK}. - * </p> - */ - public int get(int keyCode, int meta) - { - if ((meta & MetaKeyKeyListener.META_CAP_LOCKED) != 0) { - meta |= KeyEvent.META_SHIFT_ON; - } - if ((meta & MetaKeyKeyListener.META_ALT_LOCKED) != 0) { - meta |= KeyEvent.META_ALT_ON; - } - - // Ignore caps lock on keys where alt and shift have the same effect. - if ((meta & MetaKeyKeyListener.META_CAP_LOCKED) != 0) { - if (get_native(mPointer, keyCode, KeyEvent.META_SHIFT_ON) == - get_native(mPointer, keyCode, KeyEvent.META_ALT_ON)) { - meta &= ~KeyEvent.META_SHIFT_ON; - } - } - - int ret = get_native(mPointer, keyCode, meta); - int map = COMBINING.get(ret); - - if (map != 0) { - return map; - } else { - return ret; - } - } - - /** - * Gets the number or symbol associated with the key. The character value - * is returned, not the numeric value. If the key is not a number, but is - * a symbol, the symbol is retuned. - */ - public char getNumber(int keyCode) - { - return getNumber_native(mPointer, keyCode); - } - - /** - * The same as {@link #getMatch(int,char[],int) getMatch(keyCode, chars, 0)}. - */ - public char getMatch(int keyCode, char[] chars) - { - return getMatch(keyCode, chars, 0); - } - - /** - * If one of the chars in the array can be generated by keyCode, - * return the char; otherwise return '\0'. - * @param keyCode the key code to look at - * @param chars the characters to try to find - * @param modifiers the modifier bits to prefer. If any of these bits - * are set, if there are multiple choices, that could - * work, the one for this modifier will be set. - */ - public char getMatch(int keyCode, char[] chars, int modifiers) - { - if (chars == null) { - // catch it here instead of in native - throw new NullPointerException(); - } - return getMatch_native(mPointer, keyCode, chars, modifiers); - } - - /** - * Get the primary character for this key. In other words, the label - * that is physically printed on it. - */ - public char getDisplayLabel(int keyCode) - { - return getDisplayLabel_native(mPointer, keyCode); - } - - /** - * Get the character that is produced by putting accent on the character - * c. - * For example, getDeadChar('`', 'e') returns è. - */ - public static int getDeadChar(int accent, int c) - { - return DEAD.get((accent << 16) | c); - } - - public static class KeyData { - public static final int META_LENGTH = 4; - - /** - * The display label (see {@link #getDisplayLabel}). - */ - public char displayLabel; - /** - * The "number" value (see {@link #getNumber}). - */ - public char number; - /** - * The character that will be generated in various meta states - * (the same ones used for {@link #get} and defined as - * {@link KeyEvent#META_SHIFT_ON} and {@link KeyEvent#META_ALT_ON}). - * <table> - * <tr><th>Index</th><th align="left">Value</th></tr> - * <tr><td>0</td><td>no modifiers</td></tr> - * <tr><td>1</td><td>caps</td></tr> - * <tr><td>2</td><td>alt</td></tr> - * <tr><td>3</td><td>caps + alt</td></tr> - * </table> - */ - public char[] meta = new char[META_LENGTH]; - } - - /** - * Get the characters conversion data for a given keyCode. - * - * @param keyCode the keyCode to look for - * @param results a {@link KeyData} that will be filled with the results. - * - * @return whether the key was mapped or not. If the key was not mapped, - * results is not modified. - */ - public boolean getKeyData(int keyCode, KeyData results) - { - if (results.meta.length >= KeyData.META_LENGTH) { - return getKeyData_native(mPointer, keyCode, results); - } else { - throw new IndexOutOfBoundsException("results.meta.length must be >= " + - KeyData.META_LENGTH); - } - } - - /** - * Get an array of KeyEvent objects that if put into the input stream - * could plausibly generate the provided sequence of characters. It is - * not guaranteed that the sequence is the only way to generate these - * events or that it is optimal. - * - * @return an array of KeyEvent objects, or null if the given char array - * can not be generated using the current key character map. - */ - public KeyEvent[] getEvents(char[] chars) - { - if (chars == null) { - throw new NullPointerException(); - } - - long[] keys = getEvents_native(mPointer, chars); - if (keys == null) { - return null; - } - - // how big should the array be - int len = keys.length*2; - int N = keys.length; - for (int i=0; i<N; i++) { - int mods = (int)(keys[i] >> 32); - if ((mods & KeyEvent.META_ALT_ON) != 0) { - len += 2; - } - if ((mods & KeyEvent.META_SHIFT_ON) != 0) { - len += 2; - } - if ((mods & KeyEvent.META_SYM_ON) != 0) { - len += 2; - } - } - - // create the events - KeyEvent[] rv = new KeyEvent[len]; - int index = 0; - long now = SystemClock.uptimeMillis(); - int device = mKeyboardDevice; - for (int i=0; i<N; i++) { - int mods = (int)(keys[i] >> 32); - int meta = 0; - - if ((mods & KeyEvent.META_ALT_ON) != 0) { - meta |= KeyEvent.META_ALT_ON; - rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, - KeyEvent.KEYCODE_ALT_LEFT, 0, meta, device, 0); - index++; - } - if ((mods & KeyEvent.META_SHIFT_ON) != 0) { - meta |= KeyEvent.META_SHIFT_ON; - rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, - KeyEvent.KEYCODE_SHIFT_LEFT, 0, meta, device, 0); - index++; - } - if ((mods & KeyEvent.META_SYM_ON) != 0) { - meta |= KeyEvent.META_SYM_ON; - rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, - KeyEvent.KEYCODE_SYM, 0, meta, device, 0); - index++; - } - - int key = (int)(keys[i]); - rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, - key, 0, meta, device, 0); - index++; - rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_UP, - key, 0, meta, device, 0); - index++; - - if ((mods & KeyEvent.META_ALT_ON) != 0) { - meta &= ~KeyEvent.META_ALT_ON; - rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_UP, - KeyEvent.KEYCODE_ALT_LEFT, 0, meta, device, 0); - index++; - } - if ((mods & KeyEvent.META_SHIFT_ON) != 0) { - meta &= ~KeyEvent.META_SHIFT_ON; - rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_UP, - KeyEvent.KEYCODE_SHIFT_LEFT, 0, meta, device, 0); - index++; - } - if ((mods & KeyEvent.META_SYM_ON) != 0) { - meta &= ~KeyEvent.META_SYM_ON; - rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_UP, - KeyEvent.KEYCODE_SYM, 0, meta, device, 0); - index++; - } - } - - return rv; - } - - /** - * Does this character key produce a glyph? - */ - public boolean isPrintingKey(int keyCode) - { - int type = Character.getType(get(keyCode, 0)); - - switch (type) - { - case Character.SPACE_SEPARATOR: - case Character.LINE_SEPARATOR: - case Character.PARAGRAPH_SEPARATOR: - case Character.CONTROL: - case Character.FORMAT: - return false; - default: - return true; - } - } - - protected void finalize() throws Throwable - { - dtor_native(mPointer); - } - - /** - * Returns {@link #NUMERIC}, {@link #PREDICTIVE} or {@link #ALPHA}. - */ - public int getKeyboardType() - { - return getKeyboardType_native(mPointer); - } - - /** - * Queries the framework about whether any physical keys exist on the - * device that are capable of producing the given key codes. - */ - public static boolean deviceHasKey(int keyCode) { - int[] codeArray = new int[1]; - codeArray[0] = keyCode; - boolean[] ret = deviceHasKeys(codeArray); - return ret[0]; - } - - public static boolean[] deviceHasKeys(int[] keyCodes) { - boolean[] ret = new boolean[keyCodes.length]; - IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); - try { - wm.hasKeys(keyCodes, ret); - } catch (RemoteException e) { - // no fallback; just return the empty array - } - return ret; - } - - private int mPointer; - private int mKeyboardDevice; - - private static native int ctor_native(int id); - private static native void dtor_native(int ptr); - private static native char get_native(int ptr, int keycode, - int meta); - private static native char getNumber_native(int ptr, int keycode); - private static native char getMatch_native(int ptr, int keycode, - char[] chars, int modifiers); - private static native char getDisplayLabel_native(int ptr, int keycode); - private static native boolean getKeyData_native(int ptr, int keycode, - KeyData results); - private static native int getKeyboardType_native(int ptr); - private static native long[] getEvents_native(int ptr, char[] str); - - /** - * Maps Unicode combining diacritical to display-form dead key - * (display character shifted left 16 bits). - */ - private static SparseIntArray COMBINING = new SparseIntArray(); - - /** - * Maps combinations of (display-form) dead key and second character - * to combined output character. - */ - private static SparseIntArray DEAD = new SparseIntArray(); - - /* - * TODO: Change the table format to support full 21-bit-wide - * accent characters and combined characters if ever necessary. - */ - private static final int ACUTE = '\u00B4' << 16; - private static final int GRAVE = '`' << 16; - private static final int CIRCUMFLEX = '^' << 16; - private static final int TILDE = '~' << 16; - private static final int UMLAUT = '\u00A8' << 16; - - /* - * This bit will be set in the return value of {@link #get(int, int)} if the - * key is a "dead key." - */ - public static final int COMBINING_ACCENT = 0x80000000; - /** - * Mask the return value from {@link #get(int, int)} with this value to get - * a printable representation of the accent character of a "dead key." - */ - public static final int COMBINING_ACCENT_MASK = 0x7FFFFFFF; - - static { - COMBINING.put('\u0300', (GRAVE >> 16) | COMBINING_ACCENT); - COMBINING.put('\u0301', (ACUTE >> 16) | COMBINING_ACCENT); - COMBINING.put('\u0302', (CIRCUMFLEX >> 16) | COMBINING_ACCENT); - COMBINING.put('\u0303', (TILDE >> 16) | COMBINING_ACCENT); - COMBINING.put('\u0308', (UMLAUT >> 16) | COMBINING_ACCENT); - - DEAD.put(ACUTE | 'A', '\u00C1'); - DEAD.put(ACUTE | 'C', '\u0106'); - DEAD.put(ACUTE | 'E', '\u00C9'); - DEAD.put(ACUTE | 'G', '\u01F4'); - DEAD.put(ACUTE | 'I', '\u00CD'); - DEAD.put(ACUTE | 'K', '\u1E30'); - DEAD.put(ACUTE | 'L', '\u0139'); - DEAD.put(ACUTE | 'M', '\u1E3E'); - DEAD.put(ACUTE | 'N', '\u0143'); - DEAD.put(ACUTE | 'O', '\u00D3'); - DEAD.put(ACUTE | 'P', '\u1E54'); - DEAD.put(ACUTE | 'R', '\u0154'); - DEAD.put(ACUTE | 'S', '\u015A'); - DEAD.put(ACUTE | 'U', '\u00DA'); - DEAD.put(ACUTE | 'W', '\u1E82'); - DEAD.put(ACUTE | 'Y', '\u00DD'); - DEAD.put(ACUTE | 'Z', '\u0179'); - DEAD.put(ACUTE | 'a', '\u00E1'); - DEAD.put(ACUTE | 'c', '\u0107'); - DEAD.put(ACUTE | 'e', '\u00E9'); - DEAD.put(ACUTE | 'g', '\u01F5'); - DEAD.put(ACUTE | 'i', '\u00ED'); - DEAD.put(ACUTE | 'k', '\u1E31'); - DEAD.put(ACUTE | 'l', '\u013A'); - DEAD.put(ACUTE | 'm', '\u1E3F'); - DEAD.put(ACUTE | 'n', '\u0144'); - DEAD.put(ACUTE | 'o', '\u00F3'); - DEAD.put(ACUTE | 'p', '\u1E55'); - DEAD.put(ACUTE | 'r', '\u0155'); - DEAD.put(ACUTE | 's', '\u015B'); - DEAD.put(ACUTE | 'u', '\u00FA'); - DEAD.put(ACUTE | 'w', '\u1E83'); - DEAD.put(ACUTE | 'y', '\u00FD'); - DEAD.put(ACUTE | 'z', '\u017A'); - DEAD.put(CIRCUMFLEX | 'A', '\u00C2'); - DEAD.put(CIRCUMFLEX | 'C', '\u0108'); - DEAD.put(CIRCUMFLEX | 'E', '\u00CA'); - DEAD.put(CIRCUMFLEX | 'G', '\u011C'); - DEAD.put(CIRCUMFLEX | 'H', '\u0124'); - DEAD.put(CIRCUMFLEX | 'I', '\u00CE'); - DEAD.put(CIRCUMFLEX | 'J', '\u0134'); - DEAD.put(CIRCUMFLEX | 'O', '\u00D4'); - DEAD.put(CIRCUMFLEX | 'S', '\u015C'); - DEAD.put(CIRCUMFLEX | 'U', '\u00DB'); - DEAD.put(CIRCUMFLEX | 'W', '\u0174'); - DEAD.put(CIRCUMFLEX | 'Y', '\u0176'); - DEAD.put(CIRCUMFLEX | 'Z', '\u1E90'); - DEAD.put(CIRCUMFLEX | 'a', '\u00E2'); - DEAD.put(CIRCUMFLEX | 'c', '\u0109'); - DEAD.put(CIRCUMFLEX | 'e', '\u00EA'); - DEAD.put(CIRCUMFLEX | 'g', '\u011D'); - DEAD.put(CIRCUMFLEX | 'h', '\u0125'); - DEAD.put(CIRCUMFLEX | 'i', '\u00EE'); - DEAD.put(CIRCUMFLEX | 'j', '\u0135'); - DEAD.put(CIRCUMFLEX | 'o', '\u00F4'); - DEAD.put(CIRCUMFLEX | 's', '\u015D'); - DEAD.put(CIRCUMFLEX | 'u', '\u00FB'); - DEAD.put(CIRCUMFLEX | 'w', '\u0175'); - DEAD.put(CIRCUMFLEX | 'y', '\u0177'); - DEAD.put(CIRCUMFLEX | 'z', '\u1E91'); - DEAD.put(GRAVE | 'A', '\u00C0'); - DEAD.put(GRAVE | 'E', '\u00C8'); - DEAD.put(GRAVE | 'I', '\u00CC'); - DEAD.put(GRAVE | 'N', '\u01F8'); - DEAD.put(GRAVE | 'O', '\u00D2'); - DEAD.put(GRAVE | 'U', '\u00D9'); - DEAD.put(GRAVE | 'W', '\u1E80'); - DEAD.put(GRAVE | 'Y', '\u1EF2'); - DEAD.put(GRAVE | 'a', '\u00E0'); - DEAD.put(GRAVE | 'e', '\u00E8'); - DEAD.put(GRAVE | 'i', '\u00EC'); - DEAD.put(GRAVE | 'n', '\u01F9'); - DEAD.put(GRAVE | 'o', '\u00F2'); - DEAD.put(GRAVE | 'u', '\u00F9'); - DEAD.put(GRAVE | 'w', '\u1E81'); - DEAD.put(GRAVE | 'y', '\u1EF3'); - DEAD.put(TILDE | 'A', '\u00C3'); - DEAD.put(TILDE | 'E', '\u1EBC'); - DEAD.put(TILDE | 'I', '\u0128'); - DEAD.put(TILDE | 'N', '\u00D1'); - DEAD.put(TILDE | 'O', '\u00D5'); - DEAD.put(TILDE | 'U', '\u0168'); - DEAD.put(TILDE | 'V', '\u1E7C'); - DEAD.put(TILDE | 'Y', '\u1EF8'); - DEAD.put(TILDE | 'a', '\u00E3'); - DEAD.put(TILDE | 'e', '\u1EBD'); - DEAD.put(TILDE | 'i', '\u0129'); - DEAD.put(TILDE | 'n', '\u00F1'); - DEAD.put(TILDE | 'o', '\u00F5'); - DEAD.put(TILDE | 'u', '\u0169'); - DEAD.put(TILDE | 'v', '\u1E7D'); - DEAD.put(TILDE | 'y', '\u1EF9'); - DEAD.put(UMLAUT | 'A', '\u00C4'); - DEAD.put(UMLAUT | 'E', '\u00CB'); - DEAD.put(UMLAUT | 'H', '\u1E26'); - DEAD.put(UMLAUT | 'I', '\u00CF'); - DEAD.put(UMLAUT | 'O', '\u00D6'); - DEAD.put(UMLAUT | 'U', '\u00DC'); - DEAD.put(UMLAUT | 'W', '\u1E84'); - DEAD.put(UMLAUT | 'X', '\u1E8C'); - DEAD.put(UMLAUT | 'Y', '\u0178'); - DEAD.put(UMLAUT | 'a', '\u00E4'); - DEAD.put(UMLAUT | 'e', '\u00EB'); - DEAD.put(UMLAUT | 'h', '\u1E27'); - DEAD.put(UMLAUT | 'i', '\u00EF'); - DEAD.put(UMLAUT | 'o', '\u00F6'); - DEAD.put(UMLAUT | 't', '\u1E97'); - DEAD.put(UMLAUT | 'u', '\u00FC'); - DEAD.put(UMLAUT | 'w', '\u1E85'); - DEAD.put(UMLAUT | 'x', '\u1E8D'); - DEAD.put(UMLAUT | 'y', '\u00FF'); - } -} diff --git a/core/java/android/view/KeyEvent.aidl b/core/java/android/view/KeyEvent.aidl deleted file mode 100644 index dc15ecf..0000000 --- a/core/java/android/view/KeyEvent.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android.view.KeyEvent.aidl -** -** Copyright 2007, 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.view; - -parcelable KeyEvent; diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java deleted file mode 100644 index d6ea91c..0000000 --- a/core/java/android/view/KeyEvent.java +++ /dev/null @@ -1,880 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.os.Parcel; -import android.os.Parcelable; -import android.view.KeyCharacterMap; -import android.view.KeyCharacterMap.KeyData; - -/** - * Contains constants for key events. - */ -public class KeyEvent implements Parcelable { - // key codes - public static final int KEYCODE_UNKNOWN = 0; - public static final int KEYCODE_SOFT_LEFT = 1; - public static final int KEYCODE_SOFT_RIGHT = 2; - public static final int KEYCODE_HOME = 3; - public static final int KEYCODE_BACK = 4; - public static final int KEYCODE_CALL = 5; - public static final int KEYCODE_ENDCALL = 6; - public static final int KEYCODE_0 = 7; - public static final int KEYCODE_1 = 8; - public static final int KEYCODE_2 = 9; - public static final int KEYCODE_3 = 10; - public static final int KEYCODE_4 = 11; - public static final int KEYCODE_5 = 12; - public static final int KEYCODE_6 = 13; - public static final int KEYCODE_7 = 14; - public static final int KEYCODE_8 = 15; - public static final int KEYCODE_9 = 16; - public static final int KEYCODE_STAR = 17; - public static final int KEYCODE_POUND = 18; - public static final int KEYCODE_DPAD_UP = 19; - public static final int KEYCODE_DPAD_DOWN = 20; - public static final int KEYCODE_DPAD_LEFT = 21; - public static final int KEYCODE_DPAD_RIGHT = 22; - public static final int KEYCODE_DPAD_CENTER = 23; - public static final int KEYCODE_VOLUME_UP = 24; - public static final int KEYCODE_VOLUME_DOWN = 25; - public static final int KEYCODE_POWER = 26; - public static final int KEYCODE_CAMERA = 27; - public static final int KEYCODE_CLEAR = 28; - public static final int KEYCODE_A = 29; - public static final int KEYCODE_B = 30; - public static final int KEYCODE_C = 31; - public static final int KEYCODE_D = 32; - public static final int KEYCODE_E = 33; - public static final int KEYCODE_F = 34; - public static final int KEYCODE_G = 35; - public static final int KEYCODE_H = 36; - public static final int KEYCODE_I = 37; - public static final int KEYCODE_J = 38; - public static final int KEYCODE_K = 39; - public static final int KEYCODE_L = 40; - public static final int KEYCODE_M = 41; - public static final int KEYCODE_N = 42; - public static final int KEYCODE_O = 43; - public static final int KEYCODE_P = 44; - public static final int KEYCODE_Q = 45; - public static final int KEYCODE_R = 46; - public static final int KEYCODE_S = 47; - public static final int KEYCODE_T = 48; - public static final int KEYCODE_U = 49; - public static final int KEYCODE_V = 50; - public static final int KEYCODE_W = 51; - public static final int KEYCODE_X = 52; - public static final int KEYCODE_Y = 53; - public static final int KEYCODE_Z = 54; - public static final int KEYCODE_COMMA = 55; - public static final int KEYCODE_PERIOD = 56; - public static final int KEYCODE_ALT_LEFT = 57; - public static final int KEYCODE_ALT_RIGHT = 58; - public static final int KEYCODE_SHIFT_LEFT = 59; - public static final int KEYCODE_SHIFT_RIGHT = 60; - public static final int KEYCODE_TAB = 61; - public static final int KEYCODE_SPACE = 62; - public static final int KEYCODE_SYM = 63; - public static final int KEYCODE_EXPLORER = 64; - public static final int KEYCODE_ENVELOPE = 65; - public static final int KEYCODE_ENTER = 66; - public static final int KEYCODE_DEL = 67; - public static final int KEYCODE_GRAVE = 68; - public static final int KEYCODE_MINUS = 69; - public static final int KEYCODE_EQUALS = 70; - public static final int KEYCODE_LEFT_BRACKET = 71; - public static final int KEYCODE_RIGHT_BRACKET = 72; - public static final int KEYCODE_BACKSLASH = 73; - public static final int KEYCODE_SEMICOLON = 74; - public static final int KEYCODE_APOSTROPHE = 75; - public static final int KEYCODE_SLASH = 76; - public static final int KEYCODE_AT = 77; - public static final int KEYCODE_NUM = 78; - public static final int KEYCODE_HEADSETHOOK = 79; - public static final int KEYCODE_FOCUS = 80; // *Camera* focus - public static final int KEYCODE_PLUS = 81; - public static final int KEYCODE_MENU = 82; - public static final int KEYCODE_NOTIFICATION = 83; - public static final int KEYCODE_SEARCH = 84; - public static final int KEYCODE_PLAYPAUSE = 85; - public static final int KEYCODE_STOP = 86; - public static final int KEYCODE_NEXTSONG = 87; - public static final int KEYCODE_PREVIOUSSONG = 88; - public static final int KEYCODE_REWIND = 89; - public static final int KEYCODE_FORWARD = 90; - public static final int KEYCODE_MUTE = 91; - private static final int LAST_KEYCODE = KEYCODE_MUTE; - - // NOTE: If you add a new keycode here you must also add it to: - // isSystem() - // frameworks/base/include/ui/KeycodeLabels.h - // tools/puppet_master/PuppetMaster/nav_keys.py - // frameworks/base/core/res/res/values/attrs.xml - // commands/monkey/Monkey.java - // emulator? - - /** - * @deprecated There are now more than MAX_KEYCODE keycodes. - * Use {@link #getMaxKeyCode()} instead. - */ - @Deprecated - public static final int MAX_KEYCODE = 84; - - /** - * {@link #getAction} value: the key has been pressed down. - */ - public static final int ACTION_DOWN = 0; - /** - * {@link #getAction} value: the key has been released. - */ - public static final int ACTION_UP = 1; - /** - * {@link #getAction} value: multiple duplicate key events have - * occurred in a row, or a complex string is being delivered. If the - * key code is not {#link {@link #KEYCODE_UNKNOWN} then the - * {#link {@link #getRepeatCount()} method returns the number of times - * the given key code should be executed. - * Otherwise, if the key code {@link #KEYCODE_UNKNOWN}, then - * this is a sequence of characters as returned by {@link #getCharacters}. - */ - public static final int ACTION_MULTIPLE = 2; - - /** - * <p>This mask is used to check whether one of the ALT meta keys is pressed.</p> - * - * @see #isAltPressed() - * @see #getMetaState() - * @see #KEYCODE_ALT_LEFT - * @see #KEYCODE_ALT_RIGHT - */ - public static final int META_ALT_ON = 0x02; - - /** - * <p>This mask is used to check whether the left ALT meta key is pressed.</p> - * - * @see #isAltPressed() - * @see #getMetaState() - * @see #KEYCODE_ALT_LEFT - */ - public static final int META_ALT_LEFT_ON = 0x10; - - /** - * <p>This mask is used to check whether the right the ALT meta key is pressed.</p> - * - * @see #isAltPressed() - * @see #getMetaState() - * @see #KEYCODE_ALT_RIGHT - */ - public static final int META_ALT_RIGHT_ON = 0x20; - - /** - * <p>This mask is used to check whether one of the SHIFT meta keys is pressed.</p> - * - * @see #isShiftPressed() - * @see #getMetaState() - * @see #KEYCODE_SHIFT_LEFT - * @see #KEYCODE_SHIFT_RIGHT - */ - public static final int META_SHIFT_ON = 0x1; - - /** - * <p>This mask is used to check whether the left SHIFT meta key is pressed.</p> - * - * @see #isShiftPressed() - * @see #getMetaState() - * @see #KEYCODE_SHIFT_LEFT - */ - public static final int META_SHIFT_LEFT_ON = 0x40; - - /** - * <p>This mask is used to check whether the right SHIFT meta key is pressed.</p> - * - * @see #isShiftPressed() - * @see #getMetaState() - * @see #KEYCODE_SHIFT_RIGHT - */ - public static final int META_SHIFT_RIGHT_ON = 0x80; - - /** - * <p>This mask is used to check whether the SYM meta key is pressed.</p> - * - * @see #isSymPressed() - * @see #getMetaState() - */ - public static final int META_SYM_ON = 0x4; - - /** - * This mask is set if the device woke because of this key event. - */ - public static final int FLAG_WOKE_HERE = 0x1; - - /** - * This mask is set if the key event was generated by a software keyboard. - */ - public static final int FLAG_SOFT_KEYBOARD = 0x2; - - /** - * Returns the maximum keycode. - */ - public static int getMaxKeyCode() { - return LAST_KEYCODE; - } - - /** - * Get the character that is produced by putting accent on the character - * c. - * For example, getDeadChar('`', 'e') returns è. - */ - public static int getDeadChar(int accent, int c) { - return KeyCharacterMap.getDeadChar(accent, c); - } - - private int mMetaState; - private int mAction; - private int mKeyCode; - private int mScancode; - private int mRepeatCount; - private int mDeviceId; - private int mFlags; - private long mDownTime; - private long mEventTime; - private String mCharacters; - - public interface Callback { - /** - * Called when a key down event has occurred. - * - * @param keyCode The value in event.getKeyCode(). - * @param event Description of the key event. - * - * @return If you handled the event, return true. If you want to allow - * the event to be handled by the next receiver, return false. - */ - boolean onKeyDown(int keyCode, KeyEvent event); - - /** - * Called when a key up event has occurred. - * - * @param keyCode The value in event.getKeyCode(). - * @param event Description of the key event. - * - * @return If you handled the event, return true. If you want to allow - * the event to be handled by the next receiver, return false. - */ - boolean onKeyUp(int keyCode, KeyEvent event); - - /** - * Called when multiple down/up pairs of the same key have occurred - * in a row. - * - * @param keyCode The value in event.getKeyCode(). - * @param count Number of pairs as returned by event.getRepeatCount(). - * @param event Description of the key event. - * - * @return If you handled the event, return true. If you want to allow - * the event to be handled by the next receiver, return false. - */ - boolean onKeyMultiple(int keyCode, int count, KeyEvent event); - } - - /** - * Create a new key event. - * - * @param action Action code: either {@link #ACTION_DOWN}, - * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}. - * @param code The key code. - */ - public KeyEvent(int action, int code) { - mAction = action; - mKeyCode = code; - mRepeatCount = 0; - } - - /** - * Create a new key event. - * - * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis}) - * at which this key code originally went down. - * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis}) - * at which this event happened. - * @param action Action code: either {@link #ACTION_DOWN}, - * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}. - * @param code The key code. - * @param repeat A repeat count for down events (> 0 if this is after the - * initial down) or event count for multiple events. - */ - public KeyEvent(long downTime, long eventTime, int action, - int code, int repeat) { - mDownTime = downTime; - mEventTime = eventTime; - mAction = action; - mKeyCode = code; - mRepeatCount = repeat; - } - - /** - * Create a new key event. - * - * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis}) - * at which this key code originally went down. - * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis}) - * at which this event happened. - * @param action Action code: either {@link #ACTION_DOWN}, - * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}. - * @param code The key code. - * @param repeat A repeat count for down events (> 0 if this is after the - * initial down) or event count for multiple events. - * @param metaState Flags indicating which meta keys are currently pressed. - */ - public KeyEvent(long downTime, long eventTime, int action, - int code, int repeat, int metaState) { - mDownTime = downTime; - mEventTime = eventTime; - mAction = action; - mKeyCode = code; - mRepeatCount = repeat; - mMetaState = metaState; - } - - /** - * Create a new key event. - * - * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis}) - * at which this key code originally went down. - * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis}) - * at which this event happened. - * @param action Action code: either {@link #ACTION_DOWN}, - * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}. - * @param code The key code. - * @param repeat A repeat count for down events (> 0 if this is after the - * initial down) or event count for multiple events. - * @param metaState Flags indicating which meta keys are currently pressed. - * @param device The device ID that generated the key event. - * @param scancode Raw device scan code of the event. - */ - public KeyEvent(long downTime, long eventTime, int action, - int code, int repeat, int metaState, - int device, int scancode) { - mDownTime = downTime; - mEventTime = eventTime; - mAction = action; - mKeyCode = code; - mRepeatCount = repeat; - mMetaState = metaState; - mDeviceId = device; - mScancode = scancode; - } - - /** - * Create a new key event. - * - * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis}) - * at which this key code originally went down. - * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis}) - * at which this event happened. - * @param action Action code: either {@link #ACTION_DOWN}, - * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}. - * @param code The key code. - * @param repeat A repeat count for down events (> 0 if this is after the - * initial down) or event count for multiple events. - * @param metaState Flags indicating which meta keys are currently pressed. - * @param device The device ID that generated the key event. - * @param scancode Raw device scan code of the event. - * @param flags The flags for this key event - */ - public KeyEvent(long downTime, long eventTime, int action, - int code, int repeat, int metaState, - int device, int scancode, int flags) { - mDownTime = downTime; - mEventTime = eventTime; - mAction = action; - mKeyCode = code; - mRepeatCount = repeat; - mMetaState = metaState; - mDeviceId = device; - mScancode = scancode; - mFlags = flags; - } - - /** - * Create a new key event for a string of characters. The key code, - * action, and repeat could will automatically be set to - * {@link #KEYCODE_UNKNOWN}, {@link #ACTION_MULTIPLE}, and 0 for you. - * - * @param time The time (in {@link android.os.SystemClock#uptimeMillis}) - * at which this event occured. - * @param characters The string of characters. - * @param device The device ID that generated the key event. - * @param flags The flags for this key event - */ - public KeyEvent(long time, String characters, int device, int flags) { - mDownTime = time; - mEventTime = time; - mCharacters = characters; - mAction = ACTION_MULTIPLE; - mKeyCode = KEYCODE_UNKNOWN; - mRepeatCount = 0; - mDeviceId = device; - mFlags = flags; - } - - /** - * Copy an existing key event, modifying its time and repeat count. - * - * @param origEvent The existing event to be copied. - * @param eventTime The new event time - * (in {@link android.os.SystemClock#uptimeMillis}) of the event. - * @param newRepeat The new repeat count of the event. - */ - public KeyEvent(KeyEvent origEvent, long eventTime, int newRepeat) { - mDownTime = origEvent.mDownTime; - mEventTime = eventTime; - mAction = origEvent.mAction; - mKeyCode = origEvent.mKeyCode; - mRepeatCount = newRepeat; - mMetaState = origEvent.mMetaState; - mDeviceId = origEvent.mDeviceId; - mScancode = origEvent.mScancode; - mFlags = origEvent.mFlags; - mCharacters = origEvent.mCharacters; - } - - /** - * Copy an existing key event, modifying its action. - * - * @param origEvent The existing event to be copied. - * @param action The new action code of the event. - */ - public KeyEvent(KeyEvent origEvent, int action) { - mDownTime = origEvent.mDownTime; - mEventTime = origEvent.mEventTime; - mAction = action; - mKeyCode = origEvent.mKeyCode; - mRepeatCount = origEvent.mRepeatCount; - mMetaState = origEvent.mMetaState; - mDeviceId = origEvent.mDeviceId; - mScancode = origEvent.mScancode; - mFlags = origEvent.mFlags; - // Don't copy mCharacters, since one way or the other we'll lose it - // when changing the action. - } - - /** - * Don't use in new code, instead explicitly check - * {@link #getAction()}. - * - * @return If the action is ACTION_DOWN, returns true; else false. - * - * @deprecated - * @hide - */ - @Deprecated public final boolean isDown() { - return mAction == ACTION_DOWN; - } - - /** - * Is this a system key? System keys can not be used for menu shortcuts. - * - * TODO: this information should come from a table somewhere. - * TODO: should the dpad keys be here? arguably, because they also shouldn't be menu shortcuts - */ - public final boolean isSystem() { - switch (mKeyCode) { - case KEYCODE_MENU: - case KEYCODE_SOFT_RIGHT: - case KEYCODE_HOME: - case KEYCODE_BACK: - case KEYCODE_CALL: - case KEYCODE_ENDCALL: - case KEYCODE_VOLUME_UP: - case KEYCODE_VOLUME_DOWN: - case KEYCODE_MUTE: - case KEYCODE_POWER: - case KEYCODE_HEADSETHOOK: - case KEYCODE_PLAYPAUSE: - case KEYCODE_STOP: - case KEYCODE_NEXTSONG: - case KEYCODE_PREVIOUSSONG: - case KEYCODE_REWIND: - case KEYCODE_FORWARD: - case KEYCODE_CAMERA: - case KEYCODE_FOCUS: - case KEYCODE_SEARCH: - return true; - default: - return false; - } - } - - - /** - * <p>Returns the state of the meta keys.</p> - * - * @return an integer in which each bit set to 1 represents a pressed - * meta key - * - * @see #isAltPressed() - * @see #isShiftPressed() - * @see #isSymPressed() - * @see #META_ALT_ON - * @see #META_SHIFT_ON - * @see #META_SYM_ON - */ - public final int getMetaState() { - return mMetaState; - } - - /** - * Returns the flags for this key event. - * - * @see #FLAG_WOKE_HERE - */ - public final int getFlags() { - return mFlags; - } - - /** - * Returns true if this key code is a modifier key. - * - * @return whether the provided keyCode is one of - * {@link #KEYCODE_SHIFT_LEFT} {@link #KEYCODE_SHIFT_RIGHT}, - * {@link #KEYCODE_ALT_LEFT}, {@link #KEYCODE_ALT_RIGHT} - * or {@link #KEYCODE_SYM}. - */ - public static boolean isModifierKey(int keyCode) { - return keyCode == KEYCODE_SHIFT_LEFT || keyCode == KEYCODE_SHIFT_RIGHT - || keyCode == KEYCODE_ALT_LEFT || keyCode == KEYCODE_ALT_RIGHT - || keyCode == KEYCODE_SYM; - } - - /** - * <p>Returns the pressed state of the ALT meta key.</p> - * - * @return true if the ALT key is pressed, false otherwise - * - * @see #KEYCODE_ALT_LEFT - * @see #KEYCODE_ALT_RIGHT - * @see #META_ALT_ON - */ - public final boolean isAltPressed() { - return (mMetaState & META_ALT_ON) != 0; - } - - /** - * <p>Returns the pressed state of the SHIFT meta key.</p> - * - * @return true if the SHIFT key is pressed, false otherwise - * - * @see #KEYCODE_SHIFT_LEFT - * @see #KEYCODE_SHIFT_RIGHT - * @see #META_SHIFT_ON - */ - public final boolean isShiftPressed() { - return (mMetaState & META_SHIFT_ON) != 0; - } - - /** - * <p>Returns the pressed state of the SYM meta key.</p> - * - * @return true if the SYM key is pressed, false otherwise - * - * @see #KEYCODE_SYM - * @see #META_SYM_ON - */ - public final boolean isSymPressed() { - return (mMetaState & META_SYM_ON) != 0; - } - - /** - * Retrieve the action of this key event. May be either - * {@link #ACTION_DOWN}, {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}. - * - * @return The event action: ACTION_DOWN, ACTION_UP, or ACTION_MULTIPLE. - */ - public final int getAction() { - return mAction; - } - - /** - * Retrieve the key code of the key event. This is the physical key that - * was pressed, <em>not</em> the Unicode character. - * - * @return The key code of the event. - */ - public final int getKeyCode() { - return mKeyCode; - } - - /** - * For the special case of a {@link #ACTION_MULTIPLE} event with key - * code of {@link #KEYCODE_UNKNOWN}, this is a raw string of characters - * associated with the event. In all other cases it is null. - * - * @return Returns a String of 1 or more characters associated with - * the event. - */ - public final String getCharacters() { - return mCharacters; - } - - /** - * Retrieve the hardware key id of this key event. These values are not - * reliable and vary from device to device. - * - * {@more} - * Mostly this is here for debugging purposes. - */ - public final int getScanCode() { - return mScancode; - } - - /** - * Retrieve the repeat count of the event. For both key up and key down - * events, this is the number of times the key has repeated with the first - * down starting at 0 and counting up from there. For multiple key - * events, this is the number of down/up pairs that have occurred. - * - * @return The number of times the key has repeated. - */ - public final int getRepeatCount() { - return mRepeatCount; - } - - /** - * Retrieve the time of the most recent key down event, - * in the {@link android.os.SystemClock#uptimeMillis} time base. If this - * is a down event, this will be the same as {@link #getEventTime()}. - * Note that when chording keys, this value is the down time of the - * most recently pressed key, which may <em>not</em> be the same physical - * key of this event. - * - * @return Returns the most recent key down time, in the - * {@link android.os.SystemClock#uptimeMillis} time base - */ - public final long getDownTime() { - return mDownTime; - } - - /** - * Retrieve the time this event occurred, - * in the {@link android.os.SystemClock#uptimeMillis} time base. - * - * @return Returns the time this event occurred, - * in the {@link android.os.SystemClock#uptimeMillis} time base. - */ - public final long getEventTime() { - return mEventTime; - } - - /** - * Return the id for the keyboard that this event came from. A device - * id of 0 indicates the event didn't come from a physical device and - * maps to the default keymap. The other numbers are arbitrary and - * you shouldn't depend on the values. - * - * @see KeyCharacterMap#load - */ - public final int getDeviceId() { - return mDeviceId; - } - - /** - * Renamed to {@link #getDeviceId}. - * - * @hide - * @deprecated - */ - public final int getKeyboardDevice() { - return mDeviceId; - } - - /** - * Get the primary character for this key. In other words, the label - * that is physically printed on it. - */ - public char getDisplayLabel() { - return KeyCharacterMap.load(mDeviceId).getDisplayLabel(mKeyCode); - } - - /** - * <p> - * Returns the Unicode character that the key would produce. - * </p><p> - * Returns 0 if the key is not one that is used to type Unicode - * characters. - * </p><p> - * If the return value has bit - * {@link KeyCharacterMap#COMBINING_ACCENT} - * set, the key is a "dead key" that should be combined with another to - * actually produce a character -- see {@link #getDeadChar} -- - * after masking with - * {@link KeyCharacterMap#COMBINING_ACCENT_MASK}. - * </p> - */ - public int getUnicodeChar() { - return getUnicodeChar(mMetaState); - } - - /** - * <p> - * Returns the Unicode character that the key would produce. - * </p><p> - * Returns 0 if the key is not one that is used to type Unicode - * characters. - * </p><p> - * If the return value has bit - * {@link KeyCharacterMap#COMBINING_ACCENT} - * set, the key is a "dead key" that should be combined with another to - * actually produce a character -- see {@link #getDeadChar} -- after masking - * with {@link KeyCharacterMap#COMBINING_ACCENT_MASK}. - * </p> - */ - public int getUnicodeChar(int meta) { - return KeyCharacterMap.load(mDeviceId).get(mKeyCode, meta); - } - - /** - * Get the characters conversion data for the key event.. - * - * @param results a {@link KeyData} that will be filled with the results. - * - * @return whether the key was mapped or not. If the key was not mapped, - * results is not modified. - */ - public boolean getKeyData(KeyData results) { - return KeyCharacterMap.load(mDeviceId).getKeyData(mKeyCode, results); - } - - /** - * The same as {@link #getMatch(char[],int) getMatch(chars, 0)}. - */ - public char getMatch(char[] chars) { - return getMatch(chars, 0); - } - - /** - * If one of the chars in the array can be generated by the keyCode of this - * key event, return the char; otherwise return '\0'. - * @param chars the characters to try to find - * @param modifiers the modifier bits to prefer. If any of these bits - * are set, if there are multiple choices, that could - * work, the one for this modifier will be set. - */ - public char getMatch(char[] chars, int modifiers) { - return KeyCharacterMap.load(mDeviceId).getMatch(mKeyCode, chars, modifiers); - } - - /** - * Gets the number or symbol associated with the key. The character value - * is returned, not the numeric value. If the key is not a number, but is - * a symbol, the symbol is retuned. - */ - public char getNumber() { - return KeyCharacterMap.load(mDeviceId).getNumber(mKeyCode); - } - - /** - * Does the key code of this key produce a glyph? - */ - public boolean isPrintingKey() { - return KeyCharacterMap.load(mDeviceId).isPrintingKey(mKeyCode); - } - - /** - * Deliver this key event to a {@link Callback} interface. If this is - * an ACTION_MULTIPLE event and it is not handled, then an attempt will - * be made to deliver a single normal event. - * - * @param receiver The Callback that will be given the event. - * - * @return The return value from the Callback method that was called. - */ - public final boolean dispatch(Callback receiver) { - switch (mAction) { - case ACTION_DOWN: - return receiver.onKeyDown(mKeyCode, this); - case ACTION_UP: - return receiver.onKeyUp(mKeyCode, this); - case ACTION_MULTIPLE: - final int count = mRepeatCount; - final int code = mKeyCode; - if (receiver.onKeyMultiple(code, count, this)) { - return true; - } - if (code != KeyEvent.KEYCODE_UNKNOWN) { - mAction = ACTION_DOWN; - mRepeatCount = 0; - boolean handled = receiver.onKeyDown(code, this); - if (handled) { - mAction = ACTION_UP; - receiver.onKeyUp(code, this); - } - mAction = ACTION_MULTIPLE; - mRepeatCount = count; - return handled; - } - } - return false; - } - - public String toString() { - return "KeyEvent{action=" + mAction + " code=" + mKeyCode - + " repeat=" + mRepeatCount - + " meta=" + mMetaState + " scancode=" + mScancode - + " mFlags=" + mFlags + "}"; - } - - public static final Parcelable.Creator<KeyEvent> CREATOR - = new Parcelable.Creator<KeyEvent>() { - public KeyEvent createFromParcel(Parcel in) { - return new KeyEvent(in); - } - - public KeyEvent[] newArray(int size) { - return new KeyEvent[size]; - } - }; - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel out, int flags) { - out.writeInt(mAction); - out.writeInt(mKeyCode); - out.writeInt(mRepeatCount); - out.writeInt(mMetaState); - out.writeInt(mDeviceId); - out.writeInt(mScancode); - out.writeInt(mFlags); - out.writeLong(mDownTime); - out.writeLong(mEventTime); - } - - private KeyEvent(Parcel in) { - mAction = in.readInt(); - mKeyCode = in.readInt(); - mRepeatCount = in.readInt(); - mMetaState = in.readInt(); - mDeviceId = in.readInt(); - mScancode = in.readInt(); - mFlags = in.readInt(); - mDownTime = in.readLong(); - mEventTime = in.readLong(); - } -} diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java deleted file mode 100644 index 94acd3f..0000000 --- a/core/java/android/view/LayoutInflater.java +++ /dev/null @@ -1,744 +0,0 @@ -/* - * Copyright (C) 2007 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.view; - -import android.content.Context; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.util.AttributeSet; -import android.util.Xml; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.util.HashMap; - -/** - * This class is used to instantiate layout XML file into its corresponding View - * objects. It is never be used directly -- use - * {@link android.app.Activity#getLayoutInflater()} or - * {@link Context#getSystemService} to retrieve a standard LayoutInflater instance - * that is already hooked up to the current context and correctly configured - * for the device you are running on. For example: - * - * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService - * Context.LAYOUT_INFLATER_SERVICE);</pre> - * - * <p> - * To create a new LayoutInflater with an additional {@link Factory} for your - * own views, you can use {@link #cloneInContext} to clone an existing - * ViewFactory, and then call {@link #setFactory} on it to include your - * Factory. - * - * <p> - * For performance reasons, view inflation relies heavily on pre-processing of - * XML files that is done at build time. Therefore, it is not currently possible - * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime; - * it only works with an XmlPullParser returned from a compiled resource - * (R.<em>something</em> file.) - * - * @see Context#getSystemService - */ -public abstract class LayoutInflater { - private final boolean DEBUG = false; - - /** - * This field should be made private, so it is hidden from the SDK. - * {@hide} - */ - protected final Context mContext; - - // these are optional, set by the caller - private boolean mFactorySet; - private Factory mFactory; - private Filter mFilter; - - private final Object[] mConstructorArgs = new Object[2]; - - private static final Class[] mConstructorSignature = new Class[] { - Context.class, AttributeSet.class}; - - private static final HashMap<String, Constructor> sConstructorMap = - new HashMap<String, Constructor>(); - - private HashMap<String, Boolean> mFilterMap; - - private static final String TAG_MERGE = "merge"; - private static final String TAG_INCLUDE = "include"; - private static final String TAG_REQUEST_FOCUS = "requestFocus"; - - /** - * Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed - * to be inflated. - * - */ - public interface Filter { - /** - * Hook to allow clients of the LayoutInflater to restrict the set of Views - * that are allowed to be inflated. - * - * @param clazz The class object for the View that is about to be inflated - * - * @return True if this class is allowed to be inflated, or false otherwise - */ - boolean onLoadClass(Class clazz); - } - - public interface Factory { - /** - * Hook you can supply that is called when inflating from a LayoutInflater. - * You can use this to customize the tag names available in your XML - * layout files. - * - * <p> - * Note that it is good practice to prefix these custom names with your - * package (i.e., com.coolcompany.apps) to avoid conflicts with system - * names. - * - * @param name Tag name to be inflated. - * @param context The context the view is being created in. - * @param attrs Inflation attributes as specified in XML file. - * - * @return View Newly created view. Return null for the default - * behavior. - */ - public View onCreateView(String name, Context context, AttributeSet attrs); - } - - private static class FactoryMerger implements Factory { - private final Factory mF1, mF2; - - FactoryMerger(Factory f1, Factory f2) { - mF1 = f1; - mF2 = f2; - } - - public View onCreateView(String name, Context context, AttributeSet attrs) { - View v = mF1.onCreateView(name, context, attrs); - if (v != null) return v; - return mF2.onCreateView(name, context, attrs); - } - } - - /** - * Create a new LayoutInflater instance associated with a particular Context. - * Applications will almost always want to use - * {@link Context#getSystemService Context.getSystemService()} to retrieve - * the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}. - * - * @param context The Context in which this LayoutInflater will create its - * Views; most importantly, this supplies the theme from which the default - * values for their attributes are retrieved. - */ - protected LayoutInflater(Context context) { - mContext = context; - } - - /** - * Create a new LayoutInflater instance that is a copy of an existing - * LayoutInflater, optionally with its Context changed. For use in - * implementing {@link #cloneInContext}. - * - * @param original The original LayoutInflater to copy. - * @param newContext The new Context to use. - */ - protected LayoutInflater(LayoutInflater original, Context newContext) { - mContext = newContext; - mFactory = original.mFactory; - mFilter = original.mFilter; - } - - /** - * Obtains the LayoutInflater from the given context. - */ - public static LayoutInflater from(Context context) { - LayoutInflater LayoutInflater = - (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - if (LayoutInflater == null) { - throw new AssertionError("LayoutInflater not found."); - } - return LayoutInflater; - } - - /** - * Create a copy of the existing LayoutInflater object, with the copy - * pointing to a different Context than the original. This is used by - * {@link ContextThemeWrapper} to create a new LayoutInflater to go along - * with the new Context theme. - * - * @param newContext The new Context to associate with the new LayoutInflater. - * May be the same as the original Context if desired. - * - * @return Returns a brand spanking new LayoutInflater object associated with - * the given Context. - */ - public abstract LayoutInflater cloneInContext(Context newContext); - - /** - * Return the context we are running in, for access to resources, class - * loader, etc. - */ - public Context getContext() { - return mContext; - } - - /** - * Return the current factory (or null). This is called on each element - * name. If the factory returns a View, add that to the hierarchy. If it - * returns null, proceed to call onCreateView(name). - */ - public final Factory getFactory() { - return mFactory; - } - - /** - * Attach a custom Factory interface for creating views while using - * this LayoutInflater. This must not be null, and can only be set once; - * after setting, you can not change the factory. This is - * called on each element name as the xml is parsed. If the factory returns - * a View, that is added to the hierarchy. If it returns null, the next - * factory default {@link #onCreateView} method is called. - * - * <p>If you have an existing - * LayoutInflater and want to add your own factory to it, use - * {@link #cloneInContext} to clone the existing instance and then you - * can use this function (once) on the returned new instance. This will - * merge your own factory with whatever factory the original instance is - * using. - */ - public void setFactory(Factory factory) { - if (mFactorySet) { - throw new IllegalStateException("A factory has already been set on this LayoutInflater"); - } - if (factory == null) { - throw new NullPointerException("Given factory can not be null"); - } - mFactorySet = true; - if (mFactory == null) { - mFactory = factory; - } else { - mFactory = new FactoryMerger(factory, mFactory); - } - } - - /** - * @return The {@link Filter} currently used by this LayoutInflater to restrict the set of Views - * that are allowed to be inflated. - */ - public Filter getFilter() { - return mFilter; - } - - /** - * Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated - * which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will - * throw an {@link InflateException}. This filter will replace any previous filter set on this - * LayoutInflater. - * - * @param filter The Filter which restricts the set of Views that are allowed to be inflated. - * This filter will replace any previous filter set on this LayoutInflater. - */ - public void setFilter(Filter filter) { - mFilter = filter; - if (filter != null) { - mFilterMap = new HashMap<String, Boolean>(); - } - } - - /** - * Inflate a new view hierarchy from the specified xml resource. Throws - * {@link InflateException} if there is an error. - * - * @param resource ID for an XML layout resource to load (e.g., - * <code>R.layout.main_page</code>) - * @param root Optional view to be the parent of the generated hierarchy. - * @return The root View of the inflated hierarchy. If root was supplied, - * this is the root View; otherwise it is the root of the inflated - * XML file. - */ - public View inflate(int resource, ViewGroup root) { - return inflate(resource, root, root != null); - } - - /** - * Inflate a new view hierarchy from the specified xml node. Throws - * {@link InflateException} if there is an error. * - * <p> - * <em><strong>Important</strong></em> For performance - * reasons, view inflation relies heavily on pre-processing of XML files - * that is done at build time. Therefore, it is not currently possible to - * use LayoutInflater with an XmlPullParser over a plain XML file at runtime. - * - * @param parser XML dom node containing the description of the view - * hierarchy. - * @param root Optional view to be the parent of the generated hierarchy. - * @return The root View of the inflated hierarchy. If root was supplied, - * this is the root View; otherwise it is the root of the inflated - * XML file. - */ - public View inflate(XmlPullParser parser, ViewGroup root) { - return inflate(parser, root, root != null); - } - - /** - * Inflate a new view hierarchy from the specified xml resource. Throws - * {@link InflateException} if there is an error. - * - * @param resource ID for an XML layout resource to load (e.g., - * <code>R.layout.main_page</code>) - * @param root Optional view to be the parent of the generated hierarchy (if - * <em>attachToRoot</em> is true), or else simply an object that - * provides a set of LayoutParams values for root of the returned - * hierarchy (if <em>attachToRoot</em> is false.) - * @param attachToRoot Whether the inflated hierarchy should be attached to - * the root parameter? If false, root is only used to create the - * correct subclass of LayoutParams for the root view in the XML. - * @return The root View of the inflated hierarchy. If root was supplied and - * attachToRoot is true, this is root; otherwise it is the root of - * the inflated XML file. - */ - public View inflate(int resource, ViewGroup root, boolean attachToRoot) { - if (DEBUG) System.out.println("INFLATING from resource: " + resource); - XmlResourceParser parser = getContext().getResources().getLayout(resource); - try { - return inflate(parser, root, attachToRoot); - } finally { - parser.close(); - } - } - - /** - * Inflate a new view hierarchy from the specified XML node. Throws - * {@link InflateException} if there is an error. - * <p> - * <em><strong>Important</strong></em> For performance - * reasons, view inflation relies heavily on pre-processing of XML files - * that is done at build time. Therefore, it is not currently possible to - * use LayoutInflater with an XmlPullParser over a plain XML file at runtime. - * - * @param parser XML dom node containing the description of the view - * hierarchy. - * @param root Optional view to be the parent of the generated hierarchy (if - * <em>attachToRoot</em> is true), or else simply an object that - * provides a set of LayoutParams values for root of the returned - * hierarchy (if <em>attachToRoot</em> is false.) - * @param attachToRoot Whether the inflated hierarchy should be attached to - * the root parameter? If false, root is only used to create the - * correct subclass of LayoutParams for the root view in the XML. - * @return The root View of the inflated hierarchy. If root was supplied and - * attachToRoot is true, this is root; otherwise it is the root of - * the inflated XML file. - */ - public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) { - synchronized (mConstructorArgs) { - final AttributeSet attrs = Xml.asAttributeSet(parser); - mConstructorArgs[0] = mContext; - View result = root; - - try { - // Look for the root node. - int type; - while ((type = parser.next()) != XmlPullParser.START_TAG && - type != XmlPullParser.END_DOCUMENT) { - // Empty - } - - if (type != XmlPullParser.START_TAG) { - throw new InflateException(parser.getPositionDescription() - + ": No start tag found!"); - } - - final String name = parser.getName(); - - if (DEBUG) { - System.out.println("**************************"); - System.out.println("Creating root view: " - + name); - System.out.println("**************************"); - } - - if (TAG_MERGE.equals(name)) { - if (root == null || !attachToRoot) { - throw new InflateException("<merge /> can be used only with a valid " - + "ViewGroup root and attachToRoot=true"); - } - - rInflate(parser, root, attrs); - } else { - // Temp is the root view that was found in the xml - View temp = createViewFromTag(name, attrs); - - ViewGroup.LayoutParams params = null; - - if (root != null) { - if (DEBUG) { - System.out.println("Creating params from root: " + - root); - } - // Create layout params that match root, if supplied - params = root.generateLayoutParams(attrs); - if (!attachToRoot) { - // Set the layout params for temp if we are not - // attaching. (If we are, we use addView, below) - temp.setLayoutParams(params); - } - } - - if (DEBUG) { - System.out.println("-----> start inflating children"); - } - // Inflate all children under temp - rInflate(parser, temp, attrs); - if (DEBUG) { - System.out.println("-----> done inflating children"); - } - - // We are supposed to attach all the views we found (int temp) - // to root. Do that now. - if (root != null && attachToRoot) { - root.addView(temp, params); - } - - // Decide whether to return the root that was passed in or the - // top view found in xml. - if (root == null || !attachToRoot) { - result = temp; - } - } - - } catch (XmlPullParserException e) { - InflateException ex = new InflateException(e.getMessage()); - ex.initCause(e); - throw ex; - } catch (IOException e) { - InflateException ex = new InflateException( - parser.getPositionDescription() - + ": " + e.getMessage()); - ex.initCause(e); - throw ex; - } - - return result; - } - } - - /** - * Low-level function for instantiating a view by name. This attempts to - * instantiate a view class of the given <var>name</var> found in this - * LayoutInflater's ClassLoader. - * - * <p> - * There are two things that can happen in an error case: either the - * exception describing the error will be thrown, or a null will be - * returned. You must deal with both possibilities -- the former will happen - * the first time createView() is called for a class of a particular name, - * the latter every time there-after for that class name. - * - * @param name The full name of the class to be instantiated. - * @param attrs The XML attributes supplied for this instance. - * - * @return View The newly instantied view, or null. - */ - public final View createView(String name, String prefix, AttributeSet attrs) - throws ClassNotFoundException, InflateException { - Constructor constructor = sConstructorMap.get(name); - - try { - if (constructor == null) { - // Class not found in the cache, see if it's real, and try to add it - Class clazz = mContext.getClassLoader().loadClass( - prefix != null ? (prefix + name) : name); - - if (mFilter != null && clazz != null) { - boolean allowed = mFilter.onLoadClass(clazz); - if (!allowed) { - failNotAllowed(name, prefix, attrs); - } - } - constructor = clazz.getConstructor(mConstructorSignature); - sConstructorMap.put(name, constructor); - } else { - // If we have a filter, apply it to cached constructor - if (mFilter != null) { - // Have we seen this name before? - Boolean allowedState = mFilterMap.get(name); - if (allowedState == null) { - // New class -- remember whether it is allowed - Class clazz = mContext.getClassLoader().loadClass( - prefix != null ? (prefix + name) : name); - - boolean allowed = clazz != null && mFilter.onLoadClass(clazz); - mFilterMap.put(name, allowed); - if (!allowed) { - failNotAllowed(name, prefix, attrs); - } - } else if (allowedState.equals(Boolean.FALSE)) { - failNotAllowed(name, prefix, attrs); - } - } - } - - Object[] args = mConstructorArgs; - args[1] = attrs; - return (View) constructor.newInstance(args); - - } catch (NoSuchMethodException e) { - InflateException ie = new InflateException(attrs.getPositionDescription() - + ": Error inflating class " - + (prefix != null ? (prefix + name) : name)); - ie.initCause(e); - throw ie; - - } catch (ClassNotFoundException e) { - // If loadClass fails, we should propagate the exception. - throw e; - } catch (Exception e) { - InflateException ie = new InflateException(attrs.getPositionDescription() - + ": Error inflating class " - + (constructor == null ? "<unknown>" : constructor.getClass().getName())); - ie.initCause(e); - throw ie; - } - } - - /** - * Throw an excpetion because the specified class is not allowed to be inflated. - */ - private void failNotAllowed(String name, String prefix, AttributeSet attrs) { - InflateException ie = new InflateException(attrs.getPositionDescription() - + ": Class not allowed to be inflated " - + (prefix != null ? (prefix + name) : name)); - throw ie; - } - - /** - * This routine is responsible for creating the correct subclass of View - * given the xml element name. Override it to handle custom view objects. If - * you override this in your subclass be sure to call through to - * super.onCreateView(name) for names you do not recognize. - * - * @param name The fully qualified class name of the View to be create. - * @param attrs An AttributeSet of attributes to apply to the View. - * - * @return View The View created. - */ - protected View onCreateView(String name, AttributeSet attrs) - throws ClassNotFoundException { - return createView(name, "android.view.", attrs); - } - - /* - * default visibility so the BridgeInflater can override it. - */ - View createViewFromTag(String name, AttributeSet attrs) { - if (name.equals("view")) { - name = attrs.getAttributeValue(null, "class"); - } - - if (DEBUG) System.out.println("******** Creating view: " + name); - - try { - View view = (mFactory == null) ? null : mFactory.onCreateView(name, - mContext, attrs); - - if (view == null) { - if (-1 == name.indexOf('.')) { - view = onCreateView(name, attrs); - } else { - view = createView(name, null, attrs); - } - } - - if (DEBUG) System.out.println("Created view is: " + view); - return view; - - } catch (InflateException e) { - throw e; - - } catch (ClassNotFoundException e) { - InflateException ie = new InflateException(attrs.getPositionDescription() - + ": Error inflating class " + name); - ie.initCause(e); - throw ie; - - } catch (Exception e) { - InflateException ie = new InflateException(attrs.getPositionDescription() - + ": Error inflating class " + name); - ie.initCause(e); - throw ie; - } - } - - /** - * Recursive method used to descend down the xml hierarchy and instantiate - * views, instantiate their children, and then call onFinishInflate(). - */ - private void rInflate(XmlPullParser parser, View parent, final AttributeSet attrs) - throws XmlPullParserException, IOException { - - final int depth = parser.getDepth(); - int type; - - while (((type = parser.next()) != XmlPullParser.END_TAG || - parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { - - if (type != XmlPullParser.START_TAG) { - continue; - } - - final String name = parser.getName(); - - if (TAG_REQUEST_FOCUS.equals(name)) { - parseRequestFocus(parser, parent); - } else if (TAG_INCLUDE.equals(name)) { - if (parser.getDepth() == 0) { - throw new InflateException("<include /> cannot be the root element"); - } - parseInclude(parser, parent, attrs); - } else if (TAG_MERGE.equals(name)) { - throw new InflateException("<merge /> must be the root element"); - } else { - final View view = createViewFromTag(name, attrs); - final ViewGroup viewGroup = (ViewGroup) parent; - final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs); - rInflate(parser, view, attrs); - viewGroup.addView(view, params); - } - } - - parent.onFinishInflate(); - } - - private void parseRequestFocus(XmlPullParser parser, View parent) - throws XmlPullParserException, IOException { - int type; - parent.requestFocus(); - final int currentDepth = parser.getDepth(); - while (((type = parser.next()) != XmlPullParser.END_TAG || - parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) { - // Empty - } - } - - private void parseInclude(XmlPullParser parser, View parent, AttributeSet attrs) - throws XmlPullParserException, IOException { - - int type; - - if (parent instanceof ViewGroup) { - final int layout = attrs.getAttributeResourceValue(null, "layout", 0); - if (layout == 0) { - final String value = attrs.getAttributeValue(null, "layout"); - if (value == null) { - throw new InflateException("You must specifiy a layout in the" - + " include tag: <include layout=\"@layout/layoutID\" />"); - } else { - throw new InflateException("You must specifiy a valid layout " - + "reference. The layout ID " + value + " is not valid."); - } - } else { - final XmlResourceParser childParser = - getContext().getResources().getLayout(layout); - - try { - final AttributeSet childAttrs = Xml.asAttributeSet(childParser); - - while ((type = childParser.next()) != XmlPullParser.START_TAG && - type != XmlPullParser.END_DOCUMENT) { - // Empty. - } - - if (type != XmlPullParser.START_TAG) { - throw new InflateException(childParser.getPositionDescription() + - ": No start tag found!"); - } - - final String childName = childParser.getName(); - - if (TAG_MERGE.equals(childName)) { - // Inflate all children. - rInflate(childParser, parent, childAttrs); - } else { - final View view = createViewFromTag(childName, childAttrs); - final ViewGroup group = (ViewGroup) parent; - - // We try to load the layout params set in the <include /> tag. If - // they don't exist, we will rely on the layout params set in the - // included XML file. - // During a layoutparams generation, a runtime exception is thrown - // if either layout_width or layout_height is missing. We catch - // this exception and set localParams accordingly: true means we - // successfully loaded layout params from the <include /> tag, - // false means we need to rely on the included layout params. - ViewGroup.LayoutParams params = null; - try { - params = group.generateLayoutParams(attrs); - } catch (RuntimeException e) { - params = group.generateLayoutParams(childAttrs); - } finally { - if (params != null) { - view.setLayoutParams(params); - } - } - - // Inflate all children. - rInflate(childParser, view, childAttrs); - - // Attempt to override the included layout's android:id with the - // one set on the <include /> tag itself. - TypedArray a = mContext.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.View, 0, 0); - int id = a.getResourceId(com.android.internal.R.styleable.View_id, View.NO_ID); - // While we're at it, let's try to override android:visibility. - int visibility = a.getInt(com.android.internal.R.styleable.View_visibility, -1); - a.recycle(); - - if (id != View.NO_ID) { - view.setId(id); - } - - switch (visibility) { - case 0: - view.setVisibility(View.VISIBLE); - break; - case 1: - view.setVisibility(View.INVISIBLE); - break; - case 2: - view.setVisibility(View.GONE); - break; - } - - group.addView(view); - } - } finally { - childParser.close(); - } - } - } else { - throw new InflateException("<include /> can only be used inside of a ViewGroup"); - } - - final int currentDepth = parser.getDepth(); - while (((type = parser.next()) != XmlPullParser.END_TAG || - parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) { - // Empty - } - } -} diff --git a/core/java/android/view/Menu.java b/core/java/android/view/Menu.java deleted file mode 100644 index 97825e6..0000000 --- a/core/java/android/view/Menu.java +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.app.Activity; -import android.content.ComponentName; -import android.content.Intent; - -/** - * Interface for managing the items in a menu. - * <p> - * By default, every Activity supports an options menu of actions or options. - * You can add items to this menu and handle clicks on your additions. The - * easiest way of adding menu items is inflating an XML file into the - * {@link Menu} via {@link MenuInflater}. The easiest way of attaching code to - * clicks is via {@link Activity#onOptionsItemSelected(MenuItem)} and - * {@link Activity#onContextItemSelected(MenuItem)}. - * <p> - * Different menu types support different features: - * <ol> - * <li><b>Context menus</b>: Do not support item shortcuts and item icons. - * <li><b>Options menus</b>: The <b>icon menus</b> do not support item check - * marks and only show the item's - * {@link MenuItem#setTitleCondensed(CharSequence) condensed title}. The - * <b>expanded menus</b> (only available if six or more menu items are visible, - * reached via the 'More' item in the icon menu) do not show item icons, and - * item check marks are discouraged. - * <li><b>Sub menus</b>: Do not support item icons, or nested sub menus. - * </ol> - */ -public interface Menu { - - /** - * This is the part of an order integer that the user can provide. - * @hide - */ - static final int USER_MASK = 0x0000ffff; - /** - * Bit shift of the user portion of the order integer. - * @hide - */ - static final int USER_SHIFT = 0; - - /** - * This is the part of an order integer that supplies the category of the - * item. - * @hide - */ - static final int CATEGORY_MASK = 0xffff0000; - /** - * Bit shift of the category portion of the order integer. - * @hide - */ - static final int CATEGORY_SHIFT = 16; - - /** - * Value to use for group and item identifier integers when you don't care - * about them. - */ - static final int NONE = 0; - - /** - * First value for group and item identifier integers. - */ - static final int FIRST = 1; - - // Implementation note: Keep these CATEGORY_* in sync with the category enum - // in attrs.xml - - /** - * Category code for the order integer for items/groups that are part of a - * container -- or/add this with your base value. - */ - static final int CATEGORY_CONTAINER = 0x00010000; - - /** - * Category code for the order integer for items/groups that are provided by - * the system -- or/add this with your base value. - */ - static final int CATEGORY_SYSTEM = 0x00020000; - - /** - * Category code for the order integer for items/groups that are - * user-supplied secondary (infrequently used) options -- or/add this with - * your base value. - */ - static final int CATEGORY_SECONDARY = 0x00030000; - - /** - * Category code for the order integer for items/groups that are - * alternative actions on the data that is currently displayed -- or/add - * this with your base value. - */ - static final int CATEGORY_ALTERNATIVE = 0x00040000; - - /** - * Flag for {@link #addIntentOptions}: if set, do not automatically remove - * any existing menu items in the same group. - */ - static final int FLAG_APPEND_TO_GROUP = 0x0001; - - /** - * Flag for {@link #performShortcut}: if set, do not close the menu after - * executing the shortcut. - */ - static final int FLAG_PERFORM_NO_CLOSE = 0x0001; - - /** - * Flag for {@link #performShortcut(int, KeyEvent, int)}: if set, always - * close the menu after executing the shortcut. Closing the menu also resets - * the prepared state. - */ - static final int FLAG_ALWAYS_PERFORM_CLOSE = 0x0002; - - /** - * Add a new item to the menu. This item displays the given title for its - * label. - * - * @param title The text to display for the item. - * @return The newly added menu item. - */ - public MenuItem add(CharSequence title); - - /** - * Add a new item to the menu. This item displays the given title for its - * label. - * - * @param titleRes Resource identifier of title string. - * @return The newly added menu item. - */ - public MenuItem add(int titleRes); - - /** - * Add a new item to the menu. This item displays the given title for its - * label. - * - * @param groupId The group identifier that this item should be part of. - * This can be used to define groups of items for batch state - * changes. Normally use {@link #NONE} if an item should not be in a - * group. - * @param itemId Unique item ID. Use {@link #NONE} if you do not need a - * unique ID. - * @param order The order for the item. Use {@link #NONE} if you do not care - * about the order. See {@link MenuItem#getOrder()}. - * @param title The text to display for the item. - * @return The newly added menu item. - */ - public MenuItem add(int groupId, int itemId, int order, CharSequence title); - - /** - * Variation on {@link #add(int, int, int, CharSequence)} that takes a - * string resource identifier instead of the string itself. - * - * @param groupId The group identifier that this item should be part of. - * This can also be used to define groups of items for batch state - * changes. Normally use {@link #NONE} if an item should not be in a - * group. - * @param itemId Unique item ID. Use {@link #NONE} if you do not need a - * unique ID. - * @param order The order for the item. Use {@link #NONE} if you do not care - * about the order. See {@link MenuItem#getOrder()}. - * @param titleRes Resource identifier of title string. - * @return The newly added menu item. - */ - public MenuItem add(int groupId, int itemId, int order, int titleRes); - - /** - * Add a new sub-menu to the menu. This item displays the given title for - * its label. To modify other attributes on the submenu's menu item, use - * {@link SubMenu#getItem()}. - * - * @param title The text to display for the item. - * @return The newly added sub-menu - */ - SubMenu addSubMenu(final CharSequence title); - - /** - * Add a new sub-menu to the menu. This item displays the given title for - * its label. To modify other attributes on the submenu's menu item, use - * {@link SubMenu#getItem()}. - * - * @param titleRes Resource identifier of title string. - * @return The newly added sub-menu - */ - SubMenu addSubMenu(final int titleRes); - - /** - * Add a new sub-menu to the menu. This item displays the given - * <var>title</var> for its label. To modify other attributes on the - * submenu's menu item, use {@link SubMenu#getItem()}. - *<p> - * Note that you can only have one level of sub-menus, i.e. you cannnot add - * a subMenu to a subMenu: An {@link UnsupportedOperationException} will be - * thrown if you try. - * - * @param groupId The group identifier that this item should be part of. - * This can also be used to define groups of items for batch state - * changes. Normally use {@link #NONE} if an item should not be in a - * group. - * @param itemId Unique item ID. Use {@link #NONE} if you do not need a - * unique ID. - * @param order The order for the item. Use {@link #NONE} if you do not care - * about the order. See {@link MenuItem#getOrder()}. - * @param title The text to display for the item. - * @return The newly added sub-menu - */ - SubMenu addSubMenu(final int groupId, final int itemId, int order, final CharSequence title); - - /** - * Variation on {@link #addSubMenu(int, int, int, CharSequence)} that takes - * a string resource identifier for the title instead of the string itself. - * - * @param groupId The group identifier that this item should be part of. - * This can also be used to define groups of items for batch state - * changes. Normally use {@link #NONE} if an item should not be in a group. - * @param itemId Unique item ID. Use {@link #NONE} if you do not need a unique ID. - * @param order The order for the item. Use {@link #NONE} if you do not care about the - * order. See {@link MenuItem#getOrder()}. - * @param titleRes Resource identifier of title string. - * @return The newly added sub-menu - */ - SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes); - - /** - * Add a group of menu items corresponding to actions that can be performed - * for a particular Intent. The Intent is most often configured with a null - * action, the data that the current activity is working with, and includes - * either the {@link Intent#CATEGORY_ALTERNATIVE} or - * {@link Intent#CATEGORY_SELECTED_ALTERNATIVE} to find activities that have - * said they would like to be included as optional action. You can, however, - * use any Intent you want. - * - * <p> - * See {@link android.content.pm.PackageManager#queryIntentActivityOptions} - * for more * details on the <var>caller</var>, <var>specifics</var>, and - * <var>intent</var> arguments. The list returned by that function is used - * to populate the resulting menu items. - * - * <p> - * All of the menu items of possible options for the intent will be added - * with the given group and id. You can use the group to control ordering of - * the items in relation to other items in the menu. Normally this function - * will automatically remove any existing items in the menu in the same - * group and place a divider above and below the added items; this behavior - * can be modified with the <var>flags</var> parameter. For each of the - * generated items {@link MenuItem#setIntent} is called to associate the - * appropriate Intent with the item; this means the activity will - * automatically be started for you without having to do anything else. - * - * @param groupId The group identifier that the items should be part of. - * This can also be used to define groups of items for batch state - * changes. Normally use {@link #NONE} if the items should not be in - * a group. - * @param itemId Unique item ID. Use {@link #NONE} if you do not need a - * unique ID. - * @param order The order for the items. Use {@link #NONE} if you do not - * care about the order. See {@link MenuItem#getOrder()}. - * @param caller The current activity component name as defined by - * queryIntentActivityOptions(). - * @param specifics Specific items to place first as defined by - * queryIntentActivityOptions(). - * @param intent Intent describing the kinds of items to populate in the - * list as defined by queryIntentActivityOptions(). - * @param flags Additional options controlling how the items are added. - * @param outSpecificItems Optional array in which to place the menu items - * that were generated for each of the <var>specifics</var> that were - * requested. Entries may be null if no activity was found for that - * specific action. - * @return The number of menu items that were added. - * - * @see #FLAG_APPEND_TO_GROUP - * @see MenuItem#setIntent - * @see android.content.pm.PackageManager#queryIntentActivityOptions - */ - public int addIntentOptions(int groupId, int itemId, int order, - ComponentName caller, Intent[] specifics, - Intent intent, int flags, MenuItem[] outSpecificItems); - - /** - * Remove the item with the given identifier. - * - * @param id The item to be removed. If there is no item with this - * identifier, nothing happens. - */ - public void removeItem(int id); - - /** - * Remove all items in the given group. - * - * @param groupId The group to be removed. If there are no items in this - * group, nothing happens. - */ - public void removeGroup(int groupId); - - /** - * Remove all existing items from the menu, leaving it empty as if it had - * just been created. - */ - public void clear(); - - /** - * Control whether a particular group of items can show a check mark. This - * is similar to calling {@link MenuItem#setCheckable} on all of the menu items - * with the given group identifier, but in addition you can control whether - * this group contains a mutually-exclusive set items. This should be called - * after the items of the group have been added to the menu. - * - * @param group The group of items to operate on. - * @param checkable Set to true to allow a check mark, false to - * disallow. The default is false. - * @param exclusive If set to true, only one item in this group can be - * checked at a time; checking an item will automatically - * uncheck all others in the group. If set to false, each - * item can be checked independently of the others. - * - * @see MenuItem#setCheckable - * @see MenuItem#setChecked - */ - public void setGroupCheckable(int group, boolean checkable, boolean exclusive); - - /** - * Show or hide all menu items that are in the given group. - * - * @param group The group of items to operate on. - * @param visible If true the items are visible, else they are hidden. - * - * @see MenuItem#setVisible - */ - public void setGroupVisible(int group, boolean visible); - - /** - * Enable or disable all menu items that are in the given group. - * - * @param group The group of items to operate on. - * @param enabled If true the items will be enabled, else they will be disabled. - * - * @see MenuItem#setEnabled - */ - public void setGroupEnabled(int group, boolean enabled); - - /** - * Return whether the menu currently has item items that are visible. - * - * @return True if there is one or more item visible, - * else false. - */ - public boolean hasVisibleItems(); - - /** - * Return the menu item with a particular identifier. - * - * @param id The identifier to find. - * - * @return The menu item object, or null if there is no item with - * this identifier. - */ - public MenuItem findItem(int id); - - /** - * Get the number of items in the menu. Note that this will change any - * times items are added or removed from the menu. - * - * @return The item count. - */ - public int size(); - - /** - * Gets the menu item at the given index. - * - * @param index The index of the menu item to return. - * @return The menu item. - * @exception IndexOutOfBoundsException - * when {@code index < 0 || >= size()} - */ - public MenuItem getItem(int index); - - /** - * Closes the menu, if open. - */ - public void close(); - - /** - * Execute the menu item action associated with the given shortcut - * character. - * - * @param keyCode The keycode of the shortcut key. - * @param event Key event message. - * @param flags Additional option flags or 0. - * - * @return If the given shortcut exists and is shown, returns - * true; else returns false. - * - * @see #FLAG_PERFORM_NO_CLOSE - */ - public boolean performShortcut(int keyCode, KeyEvent event, int flags); - - /** - * Is a keypress one of the defined shortcut keys for this window. - * @param keyCode the key code from {@link KeyEvent} to check. - * @param event the {@link KeyEvent} to use to help check. - */ - boolean isShortcutKey(int keyCode, KeyEvent event); - - /** - * Execute the menu item action associated with the given menu identifier. - * - * @param id Identifier associated with the menu item. - * @param flags Additional option flags or 0. - * - * @return If the given identifier exists and is shown, returns - * true; else returns false. - * - * @see #FLAG_PERFORM_NO_CLOSE - */ - public boolean performIdentifierAction(int id, int flags); - - - /** - * Control whether the menu should be running in qwerty mode (alphabetic - * shortcuts) or 12-key mode (numeric shortcuts). - * - * @param isQwerty If true the menu will use alphabetic shortcuts; else it - * will use numeric shortcuts. - */ - public void setQwertyMode(boolean isQwerty); -} - diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java deleted file mode 100644 index 46c805c..0000000 --- a/core/java/android/view/MenuInflater.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import com.android.internal.view.menu.MenuItemImpl; - -import java.io.IOException; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.app.Activity; -import android.content.Context; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.util.AttributeSet; -import android.util.Xml; - -/** - * This class is used to instantiate menu XML files into Menu objects. - * <p> - * For performance reasons, menu inflation relies heavily on pre-processing of - * XML files that is done at build time. Therefore, it is not currently possible - * to use MenuInflater with an XmlPullParser over a plain XML file at runtime; - * it only works with an XmlPullParser returned from a compiled resource (R. - * <em>something</em> file.) - */ -public class MenuInflater { - /** Menu tag name in XML. */ - private static final String XML_MENU = "menu"; - - /** Group tag name in XML. */ - private static final String XML_GROUP = "group"; - - /** Item tag name in XML. */ - private static final String XML_ITEM = "item"; - - private static final int NO_ID = 0; - - private Context mContext; - - /** - * Constructs a menu inflater. - * - * @see Activity#getMenuInflater() - */ - public MenuInflater(Context context) { - mContext = context; - } - - /** - * Inflate a menu hierarchy from the specified XML resource. Throws - * {@link InflateException} if there is an error. - * - * @param menuRes Resource ID for an XML layout resource to load (e.g., - * <code>R.menu.main_activity</code>) - * @param menu The Menu to inflate into. The items and submenus will be - * added to this Menu. - */ - public void inflate(int menuRes, Menu menu) { - XmlResourceParser parser = null; - try { - parser = mContext.getResources().getLayout(menuRes); - AttributeSet attrs = Xml.asAttributeSet(parser); - - parseMenu(parser, attrs, menu); - } catch (XmlPullParserException e) { - throw new InflateException("Error inflating menu XML", e); - } catch (IOException e) { - throw new InflateException("Error inflating menu XML", e); - } finally { - if (parser != null) parser.close(); - } - } - - /** - * Called internally to fill the given menu. If a sub menu is seen, it will - * call this recursively. - */ - private void parseMenu(XmlPullParser parser, AttributeSet attrs, Menu menu) - throws XmlPullParserException, IOException { - MenuState menuState = new MenuState(menu); - - int eventType = parser.getEventType(); - String tagName; - boolean lookingForEndOfUnknownTag = false; - String unknownTagName = null; - - // This loop will skip to the menu start tag - do { - if (eventType == XmlPullParser.START_TAG) { - tagName = parser.getName(); - if (tagName.equals(XML_MENU)) { - // Go to next tag - eventType = parser.next(); - break; - } - - throw new RuntimeException("Expecting menu, got " + tagName); - } - eventType = parser.next(); - } while (eventType != XmlPullParser.END_DOCUMENT); - - boolean reachedEndOfMenu = false; - while (!reachedEndOfMenu) { - switch (eventType) { - case XmlPullParser.START_TAG: - if (lookingForEndOfUnknownTag) { - break; - } - - tagName = parser.getName(); - if (tagName.equals(XML_GROUP)) { - menuState.readGroup(attrs); - } else if (tagName.equals(XML_ITEM)) { - menuState.readItem(attrs); - } else if (tagName.equals(XML_MENU)) { - // A menu start tag denotes a submenu for an item - SubMenu subMenu = menuState.addSubMenuItem(); - - // Parse the submenu into returned SubMenu - parseMenu(parser, attrs, subMenu); - } else { - lookingForEndOfUnknownTag = true; - unknownTagName = tagName; - } - break; - - case XmlPullParser.END_TAG: - tagName = parser.getName(); - if (lookingForEndOfUnknownTag && tagName.equals(unknownTagName)) { - lookingForEndOfUnknownTag = false; - unknownTagName = null; - } else if (tagName.equals(XML_GROUP)) { - menuState.resetGroup(); - } else if (tagName.equals(XML_ITEM)) { - // Add the item if it hasn't been added (if the item was - // a submenu, it would have been added already) - if (!menuState.hasAddedItem()) { - menuState.addItem(); - } - } else if (tagName.equals(XML_MENU)) { - reachedEndOfMenu = true; - } - break; - - case XmlPullParser.END_DOCUMENT: - throw new RuntimeException("Unexpected end of document"); - } - - eventType = parser.next(); - } - } - - /** - * State for the current menu. - * <p> - * Groups can not be nested unless there is another menu (which will have - * its state class). - */ - private class MenuState { - private Menu menu; - - /* - * Group state is set on items as they are added, allowing an item to - * override its group state. (As opposed to set on items at the group end tag.) - */ - private int groupId; - private int groupCategory; - private int groupOrder; - private int groupCheckable; - private boolean groupVisible; - private boolean groupEnabled; - - private boolean itemAdded; - private int itemId; - private int itemCategoryOrder; - private String itemTitle; - private String itemTitleCondensed; - private int itemIconResId; - private char itemAlphabeticShortcut; - private char itemNumericShortcut; - /** - * Sync to attrs.xml enum: - * - 0: none - * - 1: all - * - 2: exclusive - */ - private int itemCheckable; - private boolean itemChecked; - private boolean itemVisible; - private boolean itemEnabled; - - private static final int defaultGroupId = NO_ID; - private static final int defaultItemId = NO_ID; - private static final int defaultItemCategory = 0; - private static final int defaultItemOrder = 0; - private static final int defaultItemCheckable = 0; - private static final boolean defaultItemChecked = false; - private static final boolean defaultItemVisible = true; - private static final boolean defaultItemEnabled = true; - - public MenuState(final Menu menu) { - this.menu = menu; - - resetGroup(); - } - - public void resetGroup() { - groupId = defaultGroupId; - groupCategory = defaultItemCategory; - groupOrder = defaultItemOrder; - groupCheckable = defaultItemCheckable; - groupVisible = defaultItemVisible; - groupEnabled = defaultItemEnabled; - } - - /** - * Called when the parser is pointing to a group tag. - */ - public void readGroup(AttributeSet attrs) { - TypedArray a = mContext.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.MenuGroup); - - groupId = a.getResourceId(com.android.internal.R.styleable.MenuGroup_id, defaultGroupId); - groupCategory = a.getInt(com.android.internal.R.styleable.MenuGroup_menuCategory, defaultItemCategory); - groupOrder = a.getInt(com.android.internal.R.styleable.MenuGroup_orderInCategory, defaultItemOrder); - groupCheckable = a.getInt(com.android.internal.R.styleable.MenuGroup_checkableBehavior, defaultItemCheckable); - groupVisible = a.getBoolean(com.android.internal.R.styleable.MenuGroup_visible, defaultItemVisible); - groupEnabled = a.getBoolean(com.android.internal.R.styleable.MenuGroup_enabled, defaultItemEnabled); - - a.recycle(); - } - - /** - * Called when the parser is pointing to an item tag. - */ - public void readItem(AttributeSet attrs) { - TypedArray a = mContext.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.MenuItem); - - // Inherit attributes from the group as default value - itemId = a.getResourceId(com.android.internal.R.styleable.MenuItem_id, defaultItemId); - final int category = a.getInt(com.android.internal.R.styleable.MenuItem_menuCategory, groupCategory); - final int order = a.getInt(com.android.internal.R.styleable.MenuItem_orderInCategory, groupOrder); - itemCategoryOrder = (category & Menu.CATEGORY_MASK) | (order & Menu.USER_MASK); - itemTitle = a.getString(com.android.internal.R.styleable.MenuItem_title); - itemTitleCondensed = a.getString(com.android.internal.R.styleable.MenuItem_titleCondensed); - itemIconResId = a.getResourceId(com.android.internal.R.styleable.MenuItem_icon, 0); - itemAlphabeticShortcut = - getShortcut(a.getString(com.android.internal.R.styleable.MenuItem_alphabeticShortcut)); - itemNumericShortcut = - getShortcut(a.getString(com.android.internal.R.styleable.MenuItem_numericShortcut)); - if (a.hasValue(com.android.internal.R.styleable.MenuItem_checkable)) { - // Item has attribute checkable, use it - itemCheckable = a.getBoolean(com.android.internal.R.styleable.MenuItem_checkable, false) ? 1 : 0; - } else { - // Item does not have attribute, use the group's (group can have one more state - // for checkable that represents the exclusive checkable) - itemCheckable = groupCheckable; - } - itemChecked = a.getBoolean(com.android.internal.R.styleable.MenuItem_checked, defaultItemChecked); - itemVisible = a.getBoolean(com.android.internal.R.styleable.MenuItem_visible, groupVisible); - itemEnabled = a.getBoolean(com.android.internal.R.styleable.MenuItem_enabled, groupEnabled); - - a.recycle(); - - itemAdded = false; - } - - private char getShortcut(String shortcutString) { - if (shortcutString == null) { - return 0; - } else { - return shortcutString.charAt(0); - } - } - - private void setItem(MenuItem item) { - item.setChecked(itemChecked) - .setVisible(itemVisible) - .setEnabled(itemEnabled) - .setCheckable(itemCheckable >= 1) - .setTitleCondensed(itemTitleCondensed) - .setIcon(itemIconResId) - .setAlphabeticShortcut(itemAlphabeticShortcut) - .setNumericShortcut(itemNumericShortcut); - - if (itemCheckable >= 2) { - ((MenuItemImpl) item).setExclusiveCheckable(true); - } - } - - public void addItem() { - itemAdded = true; - setItem(menu.add(groupId, itemId, itemCategoryOrder, itemTitle)); - } - - public SubMenu addSubMenuItem() { - itemAdded = true; - SubMenu subMenu = menu.addSubMenu(groupId, itemId, itemCategoryOrder, itemTitle); - setItem(subMenu.getItem()); - return subMenu; - } - - public boolean hasAddedItem() { - return itemAdded; - } - } - -} diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java deleted file mode 100644 index fcebec5..0000000 --- a/core/java/android/view/MenuItem.java +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (C) 2008 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.view; - -import android.app.Activity; -import android.content.Intent; -import android.graphics.drawable.Drawable; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.View.OnCreateContextMenuListener; - -/** - * Interface for direct access to a previously created menu item. - * <p> - * An Item is returned by calling one of the {@link android.view.Menu#add} - * methods. - * <p> - * For a feature set of specific menu types, see {@link Menu}. - */ -public interface MenuItem { - /** - * Interface definition for a callback to be invoked when a menu item is - * clicked. - * - * @see Activity#onContextItemSelected(MenuItem) - * @see Activity#onOptionsItemSelected(MenuItem) - */ - public interface OnMenuItemClickListener { - /** - * Called when a menu item has been invoked. This is the first code - * that is executed; if it returns true, no other callbacks will be - * executed. - * - * @param item The menu item that was invoked. - * - * @return Return true to consume this click and prevent others from - * executing. - */ - public boolean onMenuItemClick(MenuItem item); - } - - /** - * Return the identifier for this menu item. The identifier can not - * be changed after the menu is created. - * - * @return The menu item's identifier. - */ - public int getItemId(); - - /** - * Return the group identifier that this menu item is part of. The group - * identifier can not be changed after the menu is created. - * - * @return The menu item's group identifier. - */ - public int getGroupId(); - - /** - * Return the category and order within the category of this item. This - * item will be shown before all items (within its category) that have - * order greater than this value. - * <p> - * An order integer contains the item's category (the upper bits of the - * integer; set by or/add the category with the order within the - * category) and the ordering of the item within that category (the - * lower bits). Example categories are {@link Menu#CATEGORY_SYSTEM}, - * {@link Menu#CATEGORY_SECONDARY}, {@link Menu#CATEGORY_ALTERNATIVE}, - * {@link Menu#CATEGORY_CONTAINER}. See {@link Menu} for a full list. - * - * @return The order of this item. - */ - public int getOrder(); - - /** - * Change the title associated with this item. - * - * @param title The new text to be displayed. - * @return This Item so additional setters can be called. - */ - public MenuItem setTitle(CharSequence title); - - /** - * Change the title associated with this item. - * <p> - * Some menu types do not sufficient space to show the full title, and - * instead a condensed title is preferred. See {@link Menu} for more - * information. - * - * @param title The resource id of the new text to be displayed. - * @return This Item so additional setters can be called. - * @see #setTitleCondensed(CharSequence) - */ - - public MenuItem setTitle(int title); - - /** - * Retrieve the current title of the item. - * - * @return The title. - */ - public CharSequence getTitle(); - - /** - * Change the condensed title associated with this item. The condensed - * title is used in situations where the normal title may be too long to - * be displayed. - * - * @param title The new text to be displayed as the condensed title. - * @return This Item so additional setters can be called. - */ - public MenuItem setTitleCondensed(CharSequence title); - - /** - * Retrieve the current condensed title of the item. If a condensed - * title was never set, it will return the normal title. - * - * @return The condensed title, if it exists. - * Otherwise the normal title. - */ - public CharSequence getTitleCondensed(); - - /** - * Change the icon associated with this item. This icon will not always be - * shown, so the title should be sufficient in describing this item. See - * {@link Menu} for the menu types that support icons. - * - * @param icon The new icon (as a Drawable) to be displayed. - * @return This Item so additional setters can be called. - */ - public MenuItem setIcon(Drawable icon); - - /** - * Change the icon associated with this item. This icon will not always be - * shown, so the title should be sufficient in describing this item. See - * {@link Menu} for the menu types that support icons. - * <p> - * This method will set the resource ID of the icon which will be used to - * lazily get the Drawable when this item is being shown. - * - * @param iconRes The new icon (as a resource ID) to be displayed. - * @return This Item so additional setters can be called. - */ - public MenuItem setIcon(int iconRes); - - /** - * Returns the icon for this item as a Drawable (getting it from resources if it hasn't been - * loaded before). - * - * @return The icon as a Drawable. - */ - public Drawable getIcon(); - - /** - * Change the Intent associated with this item. By default there is no - * Intent associated with a menu item. If you set one, and nothing - * else handles the item, then the default behavior will be to call - * {@link android.content.Context#startActivity} with the given Intent. - * - * <p>Note that setIntent() can not be used with the versions of - * {@link Menu#add} that take a Runnable, because {@link Runnable#run} - * does not return a value so there is no way to tell if it handled the - * item. In this case it is assumed that the Runnable always handles - * the item, and the intent will never be started. - * - * @see #getIntent - * @param intent The Intent to associated with the item. This Intent - * object is <em>not</em> copied, so be careful not to - * modify it later. - * @return This Item so additional setters can be called. - */ - public MenuItem setIntent(Intent intent); - - /** - * Return the Intent associated with this item. This returns a - * reference to the Intent which you can change as desired to modify - * what the Item is holding. - * - * @see #setIntent - * @return Returns the last value supplied to {@link #setIntent}, or - * null. - */ - public Intent getIntent(); - - /** - * Change both the numeric and alphabetic shortcut associated with this - * item. Note that the shortcut will be triggered when the key that - * generates the given character is pressed alone or along with with the alt - * key. Also note that case is not significant and that alphabetic shortcut - * characters will be displayed in lower case. - * <p> - * See {@link Menu} for the menu types that support shortcuts. - * - * @param numericChar The numeric shortcut key. This is the shortcut when - * using a numeric (e.g., 12-key) keyboard. - * @param alphaChar The alphabetic shortcut key. This is the shortcut when - * using a keyboard with alphabetic keys. - * @return This Item so additional setters can be called. - */ - public MenuItem setShortcut(char numericChar, char alphaChar); - - /** - * Change the numeric shortcut associated with this item. - * <p> - * See {@link Menu} for the menu types that support shortcuts. - * - * @param numericChar The numeric shortcut key. This is the shortcut when - * using a 12-key (numeric) keyboard. - * @return This Item so additional setters can be called. - */ - public MenuItem setNumericShortcut(char numericChar); - - /** - * Return the char for this menu item's numeric (12-key) shortcut. - * - * @return Numeric character to use as a shortcut. - */ - public char getNumericShortcut(); - - /** - * Change the alphabetic shortcut associated with this item. The shortcut - * will be triggered when the key that generates the given character is - * pressed alone or along with with the alt key. Case is not significant and - * shortcut characters will be displayed in lower case. Note that menu items - * with the characters '\b' or '\n' as shortcuts will get triggered by the - * Delete key or Carriage Return key, respectively. - * <p> - * See {@link Menu} for the menu types that support shortcuts. - * - * @param alphaChar The alphabetic shortcut key. This is the shortcut when - * using a keyboard with alphabetic keys. - * @return This Item so additional setters can be called. - */ - public MenuItem setAlphabeticShortcut(char alphaChar); - - /** - * Return the char for this menu item's alphabetic shortcut. - * - * @return Alphabetic character to use as a shortcut. - */ - public char getAlphabeticShortcut(); - - /** - * Control whether this item can display a check mark. Setting this does - * not actually display a check mark (see {@link #setChecked} for that); - * rather, it ensures there is room in the item in which to display a - * check mark. - * <p> - * See {@link Menu} for the menu types that support check marks. - * - * @param checkable Set to true to allow a check mark, false to - * disallow. The default is false. - * @see #setChecked - * @see #isCheckable - * @see Menu#setGroupCheckable - * @return This Item so additional setters can be called. - */ - public MenuItem setCheckable(boolean checkable); - - /** - * Return whether the item can currently display a check mark. - * - * @return If a check mark can be displayed, returns true. - * - * @see #setCheckable - */ - public boolean isCheckable(); - - /** - * Control whether this item is shown with a check mark. Note that you - * must first have enabled checking with {@link #setCheckable} or else - * the check mark will not appear. If this item is a member of a group that contains - * mutually-exclusive items (set via {@link Menu#setGroupCheckable(int, boolean, boolean)}, - * the other items in the group will be unchecked. - * <p> - * See {@link Menu} for the menu types that support check marks. - * - * @see #setCheckable - * @see #isChecked - * @see Menu#setGroupCheckable - * @param checked Set to true to display a check mark, false to hide - * it. The default value is false. - * @return This Item so additional setters can be called. - */ - public MenuItem setChecked(boolean checked); - - /** - * Return whether the item is currently displaying a check mark. - * - * @return If a check mark is displayed, returns true. - * - * @see #setChecked - */ - public boolean isChecked(); - - /** - * Sets the visibility of the menu item. Even if a menu item is not visible, - * it may still be invoked via its shortcut (to completely disable an item, - * set it to invisible and {@link #setEnabled(boolean) disabled}). - * - * @param visible If true then the item will be visible; if false it is - * hidden. - * @return This Item so additional setters can be called. - */ - public MenuItem setVisible(boolean visible); - - /** - * Return the visibility of the menu item. - * - * @return If true the item is visible; else it is hidden. - */ - public boolean isVisible(); - - /** - * Sets whether the menu item is enabled. Disabling a menu item will not - * allow it to be invoked via its shortcut. The menu item will still be - * visible. - * - * @param enabled If true then the item will be invokable; if false it is - * won't be invokable. - * @return This Item so additional setters can be called. - */ - public MenuItem setEnabled(boolean enabled); - - /** - * Return the enabled state of the menu item. - * - * @return If true the item is enabled and hence invokable; else it is not. - */ - public boolean isEnabled(); - - /** - * Check whether this item has an associated sub-menu. I.e. it is a - * sub-menu of another menu. - * - * @return If true this item has a menu; else it is a - * normal item. - */ - public boolean hasSubMenu(); - - /** - * Get the sub-menu to be invoked when this item is selected, if it has - * one. See {@link #hasSubMenu()}. - * - * @return The associated menu if there is one, else null - */ - public SubMenu getSubMenu(); - - /** - * Set a custom listener for invocation of this menu item. In most - * situations, it is more efficient and easier to use - * {@link Activity#onOptionsItemSelected(MenuItem)} or - * {@link Activity#onContextItemSelected(MenuItem)}. - * - * @param menuItemClickListener The object to receive invokations. - * @return This Item so additional setters can be called. - * @see Activity#onOptionsItemSelected(MenuItem) - * @see Activity#onContextItemSelected(MenuItem) - */ - public MenuItem setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener menuItemClickListener); - - /** - * Gets the extra information linked to this menu item. This extra - * information is set by the View that added this menu item to the - * menu. - * - * @see OnCreateContextMenuListener - * @return The extra information linked to the View that added this - * menu item to the menu. This can be null. - */ - public ContextMenuInfo getMenuInfo(); -}
\ No newline at end of file diff --git a/core/java/android/view/MotionEvent.aidl b/core/java/android/view/MotionEvent.aidl deleted file mode 100644 index 3c89988..0000000 --- a/core/java/android/view/MotionEvent.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android.view.KeyEvent.aidl -** -** Copyright 2007, 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.view; - -parcelable MotionEvent; diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java deleted file mode 100644 index 882a079..0000000 --- a/core/java/android/view/MotionEvent.java +++ /dev/null @@ -1,685 +0,0 @@ -/* - * Copyright (C) 2007 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.view; - -import android.os.Parcel; -import android.os.Parcelable; -import android.os.SystemClock; -import android.util.Config; - -/** - * Object used to report movement (mouse, pen, finger, trackball) events. This - * class may hold either absolute or relative movements, depending on what - * it is being used for. - */ -public final class MotionEvent implements Parcelable { - /** - * Constant for {@link #getAction}: A pressed gesture has started, the - * motion contains the initial starting location. - */ - public static final int ACTION_DOWN = 0; - /** - * Constant for {@link #getAction}: A pressed gesture has finished, the - * motion contains the final release location as well as any intermediate - * points since the last down or move event. - */ - public static final int ACTION_UP = 1; - /** - * Constant for {@link #getAction}: A change has happened during a - * press gesture (between {@link #ACTION_DOWN} and {@link #ACTION_UP}). - * The motion contains the most recent point, as well as any intermediate - * points since the last down or move event. - */ - public static final int ACTION_MOVE = 2; - /** - * Constant for {@link #getAction}: The current gesture has been aborted. - * You will not receive any more points in it. You should treat this as - * an up event, but not perform any action that you normally would. - */ - public static final int ACTION_CANCEL = 3; - /** - * Constant for {@link #getAction}: A movement has happened outside of the - * normal bounds of the UI element. This does not provide a full gesture, - * but only the initial location of the movement/touch. - */ - public static final int ACTION_OUTSIDE = 4; - - private static final boolean TRACK_RECYCLED_LOCATION = false; - - /** - * Flag indicating the motion event intersected the top edge of the screen. - */ - public static final int EDGE_TOP = 0x00000001; - - /** - * Flag indicating the motion event intersected the bottom edge of the screen. - */ - public static final int EDGE_BOTTOM = 0x00000002; - - /** - * Flag indicating the motion event intersected the left edge of the screen. - */ - public static final int EDGE_LEFT = 0x00000004; - - /** - * Flag indicating the motion event intersected the right edge of the screen. - */ - public static final int EDGE_RIGHT = 0x00000008; - - static private final int MAX_RECYCLED = 10; - static private Object gRecyclerLock = new Object(); - static private int gRecyclerUsed = 0; - static private MotionEvent gRecyclerTop = null; - - private long mDownTime; - private long mEventTime; - private int mAction; - private float mX; - private float mY; - private float mRawX; - private float mRawY; - private float mPressure; - private float mSize; - private int mMetaState; - private int mNumHistory; - private float[] mHistory; - private long[] mHistoryTimes; - private float mXPrecision; - private float mYPrecision; - private int mDeviceId; - private int mEdgeFlags; - - private MotionEvent mNext; - private RuntimeException mRecycledLocation; - private boolean mRecycled; - - private MotionEvent() { - } - - static private MotionEvent obtain() { - synchronized (gRecyclerLock) { - if (gRecyclerTop == null) { - return new MotionEvent(); - } - MotionEvent ev = gRecyclerTop; - gRecyclerTop = ev.mNext; - gRecyclerUsed--; - ev.mRecycledLocation = null; - ev.mRecycled = false; - return ev; - } - } - - /** - * Create a new MotionEvent, filling in all of the basic values that - * define the motion. - * - * @param downTime The time (in ms) when the user originally pressed down to start - * a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}. - * @param eventTime The the time (in ms) when this specific event was generated. This - * must be obtained from {@link SystemClock#uptimeMillis()}. - * @param action The kind of action being performed -- one of either - * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or - * {@link #ACTION_CANCEL}. - * @param x The X coordinate of this event. - * @param y The Y coordinate of this event. - * @param pressure The current pressure of this event. The pressure generally - * ranges from 0 (no pressure at all) to 1 (normal pressure), however - * values higher than 1 may be generated depending on the calibration of - * the input device. - * @param size A scaled value of the approximate size of the area being pressed when - * touched with the finger. The actual value in pixels corresponding to the finger - * touch is normalized with a device specific range of values - * and scaled to a value between 0 and 1. - * @param metaState The state of any meta / modifier keys that were in effect when - * the event was generated. - * @param xPrecision The precision of the X coordinate being reported. - * @param yPrecision The precision of the Y coordinate being reported. - * @param deviceId The id for the device that this event came from. An id of - * zero indicates that the event didn't come from a physical device; other - * numbers are arbitrary and you shouldn't depend on the values. - * @param edgeFlags A bitfield indicating which edges, if any, where touched by this - * MotionEvent. - */ - static public MotionEvent obtain(long downTime, long eventTime, int action, - float x, float y, float pressure, float size, int metaState, - float xPrecision, float yPrecision, int deviceId, int edgeFlags) { - MotionEvent ev = obtain(); - ev.mDeviceId = deviceId; - ev.mEdgeFlags = edgeFlags; - ev.mDownTime = downTime; - ev.mEventTime = eventTime; - ev.mAction = action; - ev.mX = ev.mRawX = x; - ev.mY = ev.mRawY = y; - ev.mPressure = pressure; - ev.mSize = size; - ev.mMetaState = metaState; - ev.mXPrecision = xPrecision; - ev.mYPrecision = yPrecision; - - return ev; - } - - /** - * Create a new MotionEvent, filling in a subset of the basic motion - * values. Those not specified here are: device id (always 0), pressure - * and size (always 1), x and y precision (always 1), and edgeFlags (always 0). - * - * @param downTime The time (in ms) when the user originally pressed down to start - * a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}. - * @param eventTime The the time (in ms) when this specific event was generated. This - * must be obtained from {@link SystemClock#uptimeMillis()}. - * @param action The kind of action being performed -- one of either - * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or - * {@link #ACTION_CANCEL}. - * @param x The X coordinate of this event. - * @param y The Y coordinate of this event. - * @param metaState The state of any meta / modifier keys that were in effect when - * the event was generated. - */ - static public MotionEvent obtain(long downTime, long eventTime, int action, - float x, float y, int metaState) { - MotionEvent ev = obtain(); - ev.mDeviceId = 0; - ev.mEdgeFlags = 0; - ev.mDownTime = downTime; - ev.mEventTime = eventTime; - ev.mAction = action; - ev.mX = ev.mRawX = x; - ev.mY = ev.mRawY = y; - ev.mPressure = 1.0f; - ev.mSize = 1.0f; - ev.mMetaState = metaState; - ev.mXPrecision = 1.0f; - ev.mYPrecision = 1.0f; - - return ev; - } - - /** - * Create a new MotionEvent, copying from an existing one. - */ - static public MotionEvent obtain(MotionEvent o) { - MotionEvent ev = obtain(); - ev.mDeviceId = o.mDeviceId; - ev.mEdgeFlags = o.mEdgeFlags; - ev.mDownTime = o.mDownTime; - ev.mEventTime = o.mEventTime; - ev.mAction = o.mAction; - ev.mX = o.mX; - ev.mRawX = o.mRawX; - ev.mY = o.mY; - ev.mRawY = o.mRawY; - ev.mPressure = o.mPressure; - ev.mSize = o.mSize; - ev.mMetaState = o.mMetaState; - ev.mXPrecision = o.mXPrecision; - ev.mYPrecision = o.mYPrecision; - final int N = o.mNumHistory; - ev.mNumHistory = N; - if (N > 0) { - // could be more efficient about this... - ev.mHistory = (float[])o.mHistory.clone(); - ev.mHistoryTimes = (long[])o.mHistoryTimes.clone(); - } - return ev; - } - - /** - * Recycle the MotionEvent, to be re-used by a later caller. After calling - * this function you must not ever touch the event again. - */ - public void recycle() { - // Ensure recycle is only called once! - if (TRACK_RECYCLED_LOCATION) { - if (mRecycledLocation != null) { - throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation); - } - mRecycledLocation = new RuntimeException("Last recycled here"); - } else if (mRecycled) { - throw new RuntimeException(toString() + " recycled twice!"); - } - - //Log.w("MotionEvent", "Recycling event " + this, mRecycledLocation); - synchronized (gRecyclerLock) { - if (gRecyclerUsed < MAX_RECYCLED) { - gRecyclerUsed++; - mNumHistory = 0; - mNext = gRecyclerTop; - gRecyclerTop = this; - } - } - } - - /** - * Return the kind of action being performed -- one of either - * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or - * {@link #ACTION_CANCEL}. - */ - public final int getAction() { - return mAction; - } - - /** - * Returns the time (in ms) when the user originally pressed down to start - * a stream of position events. - */ - public final long getDownTime() { - return mDownTime; - } - - /** - * Returns the time (in ms) when this specific event was generated. - */ - public final long getEventTime() { - return mEventTime; - } - - /** - * Returns the X coordinate of this event. Whole numbers are pixels; the - * value may have a fraction for input devices that are sub-pixel precise. - */ - public final float getX() { - return mX; - } - - /** - * Returns the Y coordinate of this event. Whole numbers are pixels; the - * value may have a fraction for input devices that are sub-pixel precise. - */ - public final float getY() { - return mY; - } - - /** - * Returns the current pressure of this event. The pressure generally - * ranges from 0 (no pressure at all) to 1 (normal pressure), however - * values higher than 1 may be generated depending on the calibration of - * the input device. - */ - public final float getPressure() { - return mPressure; - } - - /** - * Returns a scaled value of the approximate size, of the area being pressed when - * touched with the finger. The actual value in pixels corresponding to the finger - * touch is normalized with the device specific range of values - * and scaled to a value between 0 and 1. The value of size can be used to - * determine fat touch events. - */ - public final float getSize() { - return mSize; - } - - /** - * Returns the state of any meta / modifier keys that were in effect when - * the event was generated. This is the same values as those - * returned by {@link KeyEvent#getMetaState() KeyEvent.getMetaState}. - * - * @return an integer in which each bit set to 1 represents a pressed - * meta key - * - * @see KeyEvent#getMetaState() - */ - public final int getMetaState() { - return mMetaState; - } - - /** - * Returns the original raw X coordinate of this event. For touch - * events on the screen, this is the original location of the event - * on the screen, before it had been adjusted for the containing window - * and views. - */ - public final float getRawX() { - return mRawX; - } - - /** - * Returns the original raw Y coordinate of this event. For touch - * events on the screen, this is the original location of the event - * on the screen, before it had been adjusted for the containing window - * and views. - */ - public final float getRawY() { - return mRawY; - } - - /** - * Return the precision of the X coordinates being reported. You can - * multiple this number with {@link #getX} to find the actual hardware - * value of the X coordinate. - * @return Returns the precision of X coordinates being reported. - */ - public final float getXPrecision() { - return mXPrecision; - } - - /** - * Return the precision of the Y coordinates being reported. You can - * multiple this number with {@link #getY} to find the actual hardware - * value of the Y coordinate. - * @return Returns the precision of Y coordinates being reported. - */ - public final float getYPrecision() { - return mYPrecision; - } - - /** - * Returns the number of historical points in this event. These are - * movements that have occurred between this event and the previous event. - * This only applies to ACTION_MOVE events -- all other actions will have - * a size of 0. - * - * @return Returns the number of historical points in the event. - */ - public final int getHistorySize() { - return mNumHistory; - } - - /** - * Returns the time that a historical movement occurred between this event - * and the previous event. Only applies to ACTION_MOVE events. - * - * @param pos Which historical value to return; must be less than - * {@link #getHistorySize} - * - * @see #getHistorySize - * @see #getEventTime - */ - public final long getHistoricalEventTime(int pos) { - return mHistoryTimes[pos]; - } - - /** - * Returns a historical X coordinate that occurred between this event - * and the previous event. Only applies to ACTION_MOVE events. - * - * @param pos Which historical value to return; must be less than - * {@link #getHistorySize} - * - * @see #getHistorySize - * @see #getX - */ - public final float getHistoricalX(int pos) { - return mHistory[pos*4]; - } - - /** - * Returns a historical Y coordinate that occurred between this event - * and the previous event. Only applies to ACTION_MOVE events. - * - * @param pos Which historical value to return; must be less than - * {@link #getHistorySize} - * - * @see #getHistorySize - * @see #getY - */ - public final float getHistoricalY(int pos) { - return mHistory[pos*4 + 1]; - } - - /** - * Returns a historical pressure coordinate that occurred between this event - * and the previous event. Only applies to ACTION_MOVE events. - * - * @param pos Which historical value to return; must be less than - * {@link #getHistorySize} - * - * @see #getHistorySize - * @see #getPressure - */ - public final float getHistoricalPressure(int pos) { - return mHistory[pos*4 + 2]; - } - - /** - * Returns a historical size coordinate that occurred between this event - * and the previous event. Only applies to ACTION_MOVE events. - * - * @param pos Which historical value to return; must be less than - * {@link #getHistorySize} - * - * @see #getHistorySize - * @see #getSize - */ - public final float getHistoricalSize(int pos) { - return mHistory[pos*4 + 3]; - } - - /** - * Return the id for the device that this event came from. An id of - * zero indicates that the event didn't come from a physical device; other - * numbers are arbitrary and you shouldn't depend on the values. - */ - public final int getDeviceId() { - return mDeviceId; - } - - /** - * Returns a bitfield indicating which edges, if any, where touched by this - * MotionEvent. For touch events, clients can use this to determine if the - * user's finger was touching the edge of the display. - * - * @see #EDGE_LEFT - * @see #EDGE_TOP - * @see #EDGE_RIGHT - * @see #EDGE_BOTTOM - */ - public final int getEdgeFlags() { - return mEdgeFlags; - } - - - /** - * Sets the bitfield indicating which edges, if any, where touched by this - * MotionEvent. - * - * @see #getEdgeFlags() - */ - public final void setEdgeFlags(int flags) { - mEdgeFlags = flags; - } - - /** - * Sets this event's action. - */ - public final void setAction(int action) { - mAction = action; - } - - /** - * Adjust this event's location. - * @param deltaX Amount to add to the current X coordinate of the event. - * @param deltaY Amount to add to the current Y coordinate of the event. - */ - public final void offsetLocation(float deltaX, float deltaY) { - mX += deltaX; - mY += deltaY; - final int N = mNumHistory*4; - if (N <= 0) { - return; - } - final float[] pos = mHistory; - for (int i=0; i<N; i+=4) { - pos[i] += deltaX; - pos[i+1] += deltaY; - } - } - - /** - * Set this event's location. Applies {@link #offsetLocation} with a - * delta from the current location to the given new location. - * - * @param x New absolute X location. - * @param y New absolute Y location. - */ - public final void setLocation(float x, float y) { - float deltaX = x-mX; - float deltaY = y-mY; - if (deltaX != 0 || deltaY != 0) { - offsetLocation(deltaX, deltaY); - } - } - - /** - * Add a new movement to the batch of movements in this event. The event's - * current location, position and size is updated to the new values. In - * the future, the current values in the event will be added to a list of - * historic values. - * - * @param x The new X position. - * @param y The new Y position. - * @param pressure The new pressure. - * @param size The new size. - */ - public final void addBatch(long eventTime, float x, float y, - float pressure, float size, int metaState) { - float[] history = mHistory; - long[] historyTimes = mHistoryTimes; - int N; - int avail; - if (history == null) { - mHistory = history = new float[8*4]; - mHistoryTimes = historyTimes = new long[8]; - mNumHistory = N = 0; - avail = 8; - } else { - N = mNumHistory; - avail = history.length/4; - if (N == avail) { - avail += 8; - float[] newHistory = new float[avail*4]; - System.arraycopy(history, 0, newHistory, 0, N*4); - mHistory = history = newHistory; - long[] newHistoryTimes = new long[avail]; - System.arraycopy(historyTimes, 0, newHistoryTimes, 0, N); - mHistoryTimes = historyTimes = newHistoryTimes; - } - } - - historyTimes[N] = mEventTime; - - final int pos = N*4; - history[pos] = mX; - history[pos+1] = mY; - history[pos+2] = mPressure; - history[pos+3] = mSize; - mNumHistory = N+1; - - mEventTime = eventTime; - mX = mRawX = x; - mY = mRawY = y; - mPressure = pressure; - mSize = size; - mMetaState |= metaState; - } - - @Override - public String toString() { - return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this)) - + " action=" + mAction + " x=" + mX - + " y=" + mY + " pressure=" + mPressure + " size=" + mSize + "}"; - } - - public static final Parcelable.Creator<MotionEvent> CREATOR - = new Parcelable.Creator<MotionEvent>() { - public MotionEvent createFromParcel(Parcel in) { - MotionEvent ev = obtain(); - ev.readFromParcel(in); - return ev; - } - - public MotionEvent[] newArray(int size) { - return new MotionEvent[size]; - } - }; - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel out, int flags) { - out.writeLong(mDownTime); - out.writeLong(mEventTime); - out.writeInt(mAction); - out.writeFloat(mX); - out.writeFloat(mY); - out.writeFloat(mPressure); - out.writeFloat(mSize); - out.writeInt(mMetaState); - out.writeFloat(mRawX); - out.writeFloat(mRawY); - final int N = mNumHistory; - out.writeInt(N); - if (N > 0) { - final int N4 = N*4; - int i; - float[] history = mHistory; - for (i=0; i<N4; i++) { - out.writeFloat(history[i]); - } - long[] times = mHistoryTimes; - for (i=0; i<N; i++) { - out.writeLong(times[i]); - } - } - out.writeFloat(mXPrecision); - out.writeFloat(mYPrecision); - out.writeInt(mDeviceId); - out.writeInt(mEdgeFlags); - } - - private void readFromParcel(Parcel in) { - mDownTime = in.readLong(); - mEventTime = in.readLong(); - mAction = in.readInt(); - mX = in.readFloat(); - mY = in.readFloat(); - mPressure = in.readFloat(); - mSize = in.readFloat(); - mMetaState = in.readInt(); - mRawX = in.readFloat(); - mRawY = in.readFloat(); - final int N = in.readInt(); - if ((mNumHistory=N) > 0) { - final int N4 = N*4; - float[] history = mHistory; - if (history == null || history.length < N4) { - mHistory = history = new float[N4 + (4*4)]; - } - for (int i=0; i<N4; i++) { - history[i] = in.readFloat(); - } - long[] times = mHistoryTimes; - if (times == null || times.length < N) { - mHistoryTimes = times = new long[N + 4]; - } - for (int i=0; i<N; i++) { - times[i] = in.readLong(); - } - } - mXPrecision = in.readFloat(); - mYPrecision = in.readFloat(); - mDeviceId = in.readInt(); - mEdgeFlags = in.readInt(); - } - -} - diff --git a/core/java/android/view/OrientationEventListener.java b/core/java/android/view/OrientationEventListener.java deleted file mode 100755 index 391ba1e..0000000 --- a/core/java/android/view/OrientationEventListener.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2008 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.view; - -import android.content.Context; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; -import android.util.Config; -import android.util.Log; - -/** - * Helper class for receiving notifications from the SensorManager when - * the orientation of the device has changed. - */ -public abstract class OrientationEventListener { - private static final String TAG = "OrientationEventListener"; - private static final boolean DEBUG = false; - private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; - private int mOrientation = ORIENTATION_UNKNOWN; - private SensorManager mSensorManager; - private boolean mEnabled = false; - private int mRate; - private Sensor mSensor; - private SensorEventListener mSensorEventListener; - private OrientationListener mOldListener; - - /** - * Returned from onOrientationChanged when the device orientation cannot be determined - * (typically when the device is in a close to flat position). - * - * @see #onOrientationChanged - */ - public static final int ORIENTATION_UNKNOWN = -1; - - /** - * Creates a new OrientationEventListener. - * - * @param context for the OrientationEventListener. - */ - public OrientationEventListener(Context context) { - this(context, SensorManager.SENSOR_DELAY_NORMAL); - } - - /** - * Creates a new OrientationEventListener. - * - * @param context for the OrientationEventListener. - * @param rate at which sensor events are processed (see also - * {@link android.hardware.SensorManager SensorManager}). Use the default - * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL - * SENSOR_DELAY_NORMAL} for simple screen orientation change detection. - */ - public OrientationEventListener(Context context, int rate) { - mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); - mRate = rate; - mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - if (mSensor != null) { - // Create listener only if sensors do exist - mSensorEventListener = new SensorEventListenerImpl(); - } - } - - void registerListener(OrientationListener lis) { - mOldListener = lis; - } - - /** - * Enables the OrientationEventListener so it will monitor the sensor and call - * {@link #onOrientationChanged} when the device orientation changes. - */ - public void enable() { - if (mSensor == null) { - Log.w(TAG, "Cannot detect sensors. Not enabled"); - return; - } - if (mEnabled == false) { - if (localLOGV) Log.d(TAG, "OrientationEventListener enabled"); - mSensorManager.registerListener(mSensorEventListener, mSensor, mRate); - mEnabled = true; - } - } - - /** - * Disables the OrientationEventListener. - */ - public void disable() { - if (mSensor == null) { - Log.w(TAG, "Cannot detect sensors. Invalid disable"); - return; - } - if (mEnabled == true) { - if (localLOGV) Log.d(TAG, "OrientationEventListener disabled"); - mSensorManager.unregisterListener(mSensorEventListener); - mEnabled = false; - } - } - - class SensorEventListenerImpl implements SensorEventListener { - private static final int _DATA_X = 0; - private static final int _DATA_Y = 1; - private static final int _DATA_Z = 2; - - public void onSensorChanged(SensorEvent event) { - float[] values = event.values; - int orientation = ORIENTATION_UNKNOWN; - float X = -values[_DATA_X]; - float Y = -values[_DATA_Y]; - float Z = -values[_DATA_Z]; - float magnitude = X*X + Y*Y; - // Don't trust the angle if the magnitude is small compared to the y value - if (magnitude * 4 >= Z*Z) { - float OneEightyOverPi = 57.29577957855f; - float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi; - orientation = 90 - (int)Math.round(angle); - // normalize to 0 - 359 range - while (orientation >= 360) { - orientation -= 360; - } - while (orientation < 0) { - orientation += 360; - } - } - if (mOldListener != null) { - mOldListener.onSensorChanged(Sensor.TYPE_ACCELEROMETER, event.values); - } - if (orientation != mOrientation) { - mOrientation = orientation; - onOrientationChanged(orientation); - } - } - - public void onAccuracyChanged(Sensor sensor, int accuracy) { - - } - } - - /* - * Returns true if sensor is enabled and false otherwise - */ - public boolean canDetectOrientation() { - return mSensor != null; - } - - /** - * Called when the orientation of the device has changed. - * orientation parameter is in degrees, ranging from 0 to 359. - * orientation is 0 degrees when the device is oriented in its natural position, - * 90 degrees when its left side is at the top, 180 degrees when it is upside down, - * and 270 degrees when its right side is to the top. - * {@link #ORIENTATION_UNKNOWN} is returned when the device is close to flat - * and the orientation cannot be determined. - * - * @param orientation The new orientation of the device. - * - * @see #ORIENTATION_UNKNOWN - */ - abstract public void onOrientationChanged(int orientation); -} diff --git a/core/java/android/view/OrientationListener.java b/core/java/android/view/OrientationListener.java deleted file mode 100644 index ce8074e..0000000 --- a/core/java/android/view/OrientationListener.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2008 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.view; - -import android.content.Context; -import android.hardware.SensorListener; - -/** - * Helper class for receiving notifications from the SensorManager when - * the orientation of the device has changed. - * @deprecated use {@link android.view.OrientationEventListener} instead. - * This class internally uses the OrientationEventListener. - */ -@Deprecated -public abstract class OrientationListener implements SensorListener { - private OrientationEventListener mOrientationEventLis; - - /** - * Returned from onOrientationChanged when the device orientation cannot be determined - * (typically when the device is in a close to flat position). - * - * @see #onOrientationChanged - */ - public static final int ORIENTATION_UNKNOWN = OrientationEventListener.ORIENTATION_UNKNOWN; - - /** - * Creates a new OrientationListener. - * - * @param context for the OrientationListener. - */ - public OrientationListener(Context context) { - mOrientationEventLis = new OrientationEventListenerInternal(context); - } - - /** - * Creates a new OrientationListener. - * - * @param context for the OrientationListener. - * @param rate at which sensor events are processed (see also - * {@link android.hardware.SensorManager SensorManager}). Use the default - * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL - * SENSOR_DELAY_NORMAL} for simple screen orientation change detection. - */ - public OrientationListener(Context context, int rate) { - mOrientationEventLis = new OrientationEventListenerInternal(context, rate); - } - - class OrientationEventListenerInternal extends OrientationEventListener { - OrientationEventListenerInternal(Context context) { - super(context); - } - - OrientationEventListenerInternal(Context context, int rate) { - super(context, rate); - // register so that onSensorChanged gets invoked - registerListener(OrientationListener.this); - } - - public void onOrientationChanged(int orientation) { - OrientationListener.this.onOrientationChanged(orientation); - } - } - - /** - * Enables the OrientationListener so it will monitor the sensor and call - * {@link #onOrientationChanged} when the device orientation changes. - */ - public void enable() { - mOrientationEventLis.enable(); - } - - /** - * Disables the OrientationListener. - */ - public void disable() { - mOrientationEventLis.disable(); - } - - public void onAccuracyChanged(int sensor, int accuracy) { - } - - public void onSensorChanged(int sensor, float[] values) { - // just ignore the call here onOrientationChanged is invoked anyway - } - - - /** - * Look at {@link android.view.OrientationEventListener#onOrientationChanged} - * for method description and usage - * @param orientation The new orientation of the device. - * - * @see #ORIENTATION_UNKNOWN - */ - abstract public void onOrientationChanged(int orientation); - -} diff --git a/core/java/android/view/RawInputEvent.java b/core/java/android/view/RawInputEvent.java deleted file mode 100644 index 30da83e..0000000 --- a/core/java/android/view/RawInputEvent.java +++ /dev/null @@ -1,170 +0,0 @@ -/** - * - */ -package android.view; - -/** - * @hide - * This really belongs in services.jar; WindowManagerPolicy should go there too. - */ -public class RawInputEvent { - // Event class as defined by EventHub. - public static final int CLASS_KEYBOARD = 0x00000001; - public static final int CLASS_ALPHAKEY = 0x00000002; - public static final int CLASS_TOUCHSCREEN = 0x00000004; - public static final int CLASS_TRACKBALL = 0x00000008; - - // More special classes for QueuedEvent below. - public static final int CLASS_CONFIGURATION_CHANGED = 0x10000000; - - // Event types. - - public static final int EV_SYN = 0x00; - public static final int EV_KEY = 0x01; - public static final int EV_REL = 0x02; - public static final int EV_ABS = 0x03; - public static final int EV_MSC = 0x04; - public static final int EV_SW = 0x05; - public static final int EV_LED = 0x11; - public static final int EV_SND = 0x12; - public static final int EV_REP = 0x14; - public static final int EV_FF = 0x15; - public static final int EV_PWR = 0x16; - public static final int EV_FF_STATUS = 0x17; - - // Platform-specific event types. - - public static final int EV_DEVICE_ADDED = 0x10000000; - public static final int EV_DEVICE_REMOVED = 0x20000000; - - // Special key (EV_KEY) scan codes for pointer buttons. - - public static final int BTN_FIRST = 0x100; - - public static final int BTN_MISC = 0x100; - public static final int BTN_0 = 0x100; - public static final int BTN_1 = 0x101; - public static final int BTN_2 = 0x102; - public static final int BTN_3 = 0x103; - public static final int BTN_4 = 0x104; - public static final int BTN_5 = 0x105; - public static final int BTN_6 = 0x106; - public static final int BTN_7 = 0x107; - public static final int BTN_8 = 0x108; - public static final int BTN_9 = 0x109; - - public static final int BTN_MOUSE = 0x110; - public static final int BTN_LEFT = 0x110; - public static final int BTN_RIGHT = 0x111; - public static final int BTN_MIDDLE = 0x112; - public static final int BTN_SIDE = 0x113; - public static final int BTN_EXTRA = 0x114; - public static final int BTN_FORWARD = 0x115; - public static final int BTN_BACK = 0x116; - public static final int BTN_TASK = 0x117; - - public static final int BTN_JOYSTICK = 0x120; - public static final int BTN_TRIGGER = 0x120; - public static final int BTN_THUMB = 0x121; - public static final int BTN_THUMB2 = 0x122; - public static final int BTN_TOP = 0x123; - public static final int BTN_TOP2 = 0x124; - public static final int BTN_PINKIE = 0x125; - public static final int BTN_BASE = 0x126; - public static final int BTN_BASE2 = 0x127; - public static final int BTN_BASE3 = 0x128; - public static final int BTN_BASE4 = 0x129; - public static final int BTN_BASE5 = 0x12a; - public static final int BTN_BASE6 = 0x12b; - public static final int BTN_DEAD = 0x12f; - - public static final int BTN_GAMEPAD = 0x130; - public static final int BTN_A = 0x130; - public static final int BTN_B = 0x131; - public static final int BTN_C = 0x132; - public static final int BTN_X = 0x133; - public static final int BTN_Y = 0x134; - public static final int BTN_Z = 0x135; - public static final int BTN_TL = 0x136; - public static final int BTN_TR = 0x137; - public static final int BTN_TL2 = 0x138; - public static final int BTN_TR2 = 0x139; - public static final int BTN_SELECT = 0x13a; - public static final int BTN_START = 0x13b; - public static final int BTN_MODE = 0x13c; - public static final int BTN_THUMBL = 0x13d; - public static final int BTN_THUMBR = 0x13e; - - public static final int BTN_DIGI = 0x140; - public static final int BTN_TOOL_PEN = 0x140; - public static final int BTN_TOOL_RUBBER = 0x141; - public static final int BTN_TOOL_BRUSH = 0x142; - public static final int BTN_TOOL_PENCIL = 0x143; - public static final int BTN_TOOL_AIRBRUSH = 0x144; - public static final int BTN_TOOL_FINGER = 0x145; - public static final int BTN_TOOL_MOUSE = 0x146; - public static final int BTN_TOOL_LENS = 0x147; - public static final int BTN_TOUCH = 0x14a; - public static final int BTN_STYLUS = 0x14b; - public static final int BTN_STYLUS2 = 0x14c; - public static final int BTN_TOOL_DOUBLETAP = 0x14d; - public static final int BTN_TOOL_TRIPLETAP = 0x14e; - - public static final int BTN_WHEEL = 0x150; - public static final int BTN_GEAR_DOWN = 0x150; - public static final int BTN_GEAR_UP = 0x151; - - public static final int BTN_LAST = 0x15f; - - // Relative axes (EV_REL) scan codes. - - public static final int REL_X = 0x00; - public static final int REL_Y = 0x01; - public static final int REL_Z = 0x02; - public static final int REL_RX = 0x03; - public static final int REL_RY = 0x04; - public static final int REL_RZ = 0x05; - public static final int REL_HWHEEL = 0x06; - public static final int REL_DIAL = 0x07; - public static final int REL_WHEEL = 0x08; - public static final int REL_MISC = 0x09; - public static final int REL_MAX = 0x0f; - - // Absolute axes (EV_ABS) scan codes. - - public static final int ABS_X = 0x00; - public static final int ABS_Y = 0x01; - public static final int ABS_Z = 0x02; - public static final int ABS_RX = 0x03; - public static final int ABS_RY = 0x04; - public static final int ABS_RZ = 0x05; - public static final int ABS_THROTTLE = 0x06; - public static final int ABS_RUDDER = 0x07; - public static final int ABS_WHEEL = 0x08; - public static final int ABS_GAS = 0x09; - public static final int ABS_BRAKE = 0x0a; - public static final int ABS_HAT0X = 0x10; - public static final int ABS_HAT0Y = 0x11; - public static final int ABS_HAT1X = 0x12; - public static final int ABS_HAT1Y = 0x13; - public static final int ABS_HAT2X = 0x14; - public static final int ABS_HAT2Y = 0x15; - public static final int ABS_HAT3X = 0x16; - public static final int ABS_HAT3Y = 0x17; - public static final int ABS_PRESSURE = 0x18; - public static final int ABS_DISTANCE = 0x19; - public static final int ABS_TILT_X = 0x1a; - public static final int ABS_TILT_Y = 0x1b; - public static final int ABS_TOOL_WIDTH = 0x1c; - public static final int ABS_VOLUME = 0x20; - public static final int ABS_MISC = 0x28; - public static final int ABS_MAX = 0x3f; - - public int deviceId; - public int type; - public int scancode; - public int keycode; - public int flags; - public int value; - public long when; -} diff --git a/core/java/android/view/RemotableViewMethod.java b/core/java/android/view/RemotableViewMethod.java deleted file mode 100644 index 4318290..0000000 --- a/core/java/android/view/RemotableViewMethod.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2007 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.view; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @hide - * This annotation indicates that a method on a subclass of View - * is alllowed to be used with the {@link android.widget.RemoteViews} mechanism. - */ -@Target({ ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -public @interface RemotableViewMethod { -} - - - diff --git a/core/java/android/view/SoundEffectConstants.java b/core/java/android/view/SoundEffectConstants.java deleted file mode 100644 index 4a77af4..0000000 --- a/core/java/android/view/SoundEffectConstants.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2008 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.view; - -/** - * Constants to be used to play sound effects via {@link View#playSoundEffect(int)} - */ -public class SoundEffectConstants { - - private SoundEffectConstants() {} - - public static final int CLICK = 0; - - public static final int NAVIGATION_LEFT = 1; - public static final int NAVIGATION_UP = 2; - public static final int NAVIGATION_RIGHT = 3; - public static final int NAVIGATION_DOWN = 4; - - /** - * Get the sonification constant for the focus directions. - * @param direction One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, - * {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT}, {@link View#FOCUS_FORWARD} - * or {@link View#FOCUS_BACKWARD} - - * @return The appropriate sonification constant. - */ - public static int getContantForFocusDirection(int direction) { - switch (direction) { - case View.FOCUS_RIGHT: - return SoundEffectConstants.NAVIGATION_RIGHT; - case View.FOCUS_FORWARD: - case View.FOCUS_DOWN: - return SoundEffectConstants.NAVIGATION_DOWN; - case View.FOCUS_LEFT: - return SoundEffectConstants.NAVIGATION_LEFT; - case View.FOCUS_BACKWARD: - case View.FOCUS_UP: - return SoundEffectConstants.NAVIGATION_UP; - } - throw new IllegalArgumentException("direction must be one of " - + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, FOCUS_BACKWARD}."); - } -} diff --git a/core/java/android/view/SubMenu.java b/core/java/android/view/SubMenu.java deleted file mode 100644 index e981486..0000000 --- a/core/java/android/view/SubMenu.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2007 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.view; - -import android.graphics.drawable.Drawable; - -/** - * Subclass of {@link Menu} for sub menus. - * <p> - * Sub menus do not support item icons, or nested sub menus. - */ - -public interface SubMenu extends Menu { - /** - * Sets the submenu header's title to the title given in <var>titleRes</var> - * resource identifier. - * - * @param titleRes The string resource identifier used for the title. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setHeaderTitle(int titleRes); - - /** - * Sets the submenu header's title to the title given in <var>title</var>. - * - * @param title The character sequence used for the title. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setHeaderTitle(CharSequence title); - - /** - * Sets the submenu header's icon to the icon given in <var>iconRes</var> - * resource id. - * - * @param iconRes The resource identifier used for the icon. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setHeaderIcon(int iconRes); - - /** - * Sets the submenu header's icon to the icon given in <var>icon</var> - * {@link Drawable}. - * - * @param icon The {@link Drawable} used for the icon. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setHeaderIcon(Drawable icon); - - /** - * Sets the header of the submenu to the {@link View} given in - * <var>view</var>. This replaces the header title and icon (and those - * replace this). - * - * @param view The {@link View} used for the header. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setHeaderView(View view); - - /** - * Clears the header of the submenu. - */ - public void clearHeader(); - - /** - * Change the icon associated with this submenu's item in its parent menu. - * - * @see MenuItem#setIcon(int) - * @param iconRes The new icon (as a resource ID) to be displayed. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setIcon(int iconRes); - - /** - * Change the icon associated with this submenu's item in its parent menu. - * - * @see MenuItem#setIcon(Drawable) - * @param icon The new icon (as a Drawable) to be displayed. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setIcon(Drawable icon); - - /** - * Gets the {@link MenuItem} that represents this submenu in the parent - * menu. Use this for setting additional item attributes. - * - * @return The {@link MenuItem} that launches the submenu when invoked. - */ - public MenuItem getItem(); -} diff --git a/core/java/android/view/Surface.aidl b/core/java/android/view/Surface.aidl deleted file mode 100644 index 90bf37a..0000000 --- a/core/java/android/view/Surface.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/Surface.aidl -** -** Copyright 2007, 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.view; - -parcelable Surface; diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java deleted file mode 100644 index 54ccf33..0000000 --- a/core/java/android/view/Surface.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (C) 2007 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.view; - -import android.graphics.*; -import android.os.Parcelable; -import android.os.Parcel; -import android.util.Log; - -/** - * Handle on to a raw buffer that is being managed by the screen compositor. - */ -public class Surface implements Parcelable { - private static final String LOG_TAG = "Surface"; - - /* flags used in constructor (keep in sync with ISurfaceComposer.h) */ - - /** Surface is created hidden */ - public static final int HIDDEN = 0x00000004; - - /** The surface is to be used by hardware accelerators or DMA engines */ - public static final int HARDWARE = 0x00000010; - - /** Implies "HARDWARE", the surface is to be used by the GPU - * additionally the backbuffer is never preserved for these - * surfaces. */ - public static final int GPU = 0x00000028; - - /** The surface contains secure content, special measures will - * be taken to disallow the surface's content to be copied from - * another process. In particular, screenshots and VNC servers will - * be disabled, but other measures can take place, for instance the - * surface might not be hardware accelerated. */ - public static final int SECURE = 0x00000080; - - /** Creates a surface where color components are interpreted as - * "non pre-multiplied" by their alpha channel. Of course this flag is - * meaningless for surfaces without an alpha channel. By default - * surfaces are pre-multiplied, which means that each color component is - * already multiplied by its alpha value. In this case the blending - * equation used is: - * - * DEST = SRC + DEST * (1-SRC_ALPHA) - * - * By contrast, non pre-multiplied surfaces use the following equation: - * - * DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA) - * - * pre-multiplied surfaces must always be used if transparent pixels are - * composited on top of each-other into the surface. A pre-multiplied - * surface can never lower the value of the alpha component of a given - * pixel. - * - * In some rare situations, a non pre-multiplied surface is preferable. - * - */ - public static final int NON_PREMULTIPLIED = 0x00000100; - - /** - * Creates a surface without a rendering buffer. Instead, the content - * of the surface must be pushed by an external entity. This is type - * of surface can be used for efficient camera preview or movie - * play back. - */ - public static final int PUSH_BUFFERS = 0x00000200; - - /** Creates a normal surface. This is the default */ - public static final int FX_SURFACE_NORMAL = 0x00000000; - - /** Creates a Blur surface. Everything behind this surface is blurred - * by some amount. The quality and refresh speed of the blur effect - * is not settable or guaranteed. - * It is an error to lock a Blur surface, since it doesn't have - * a backing store. - */ - public static final int FX_SURFACE_BLUR = 0x00010000; - - /** Creates a Dim surface. Everything behind this surface is dimmed - * by the amount specified in setAlpha(). - * It is an error to lock a Dim surface, since it doesn't have - * a backing store. - */ - public static final int FX_SURFACE_DIM = 0x00020000; - - /** Mask used for FX values above */ - public static final int FX_SURFACE_MASK = 0x000F0000; - - /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */ - - /** Hide the surface. Equivalent to calling hide() */ - public static final int SURFACE_HIDDEN = 0x01; - - /** Freeze the surface. Equivalent to calling freeze() */ - public static final int SURACE_FROZEN = 0x02; - - /** Enable dithering when compositing this surface */ - public static final int SURFACE_DITHER = 0x04; - - public static final int SURFACE_BLUR_FREEZE= 0x10; - - /* orientations for setOrientation() */ - public static final int ROTATION_0 = 0; - public static final int ROTATION_90 = 1; - public static final int ROTATION_180 = 2; - public static final int ROTATION_270 = 3; - - @SuppressWarnings("unused") - private int mSurface; - @SuppressWarnings("unused") - private int mSaveCount; - @SuppressWarnings("unused") - private Canvas mCanvas; - - /** - * Exception thrown when a surface couldn't be created or resized - */ - public static class OutOfResourcesException extends Exception { - public OutOfResourcesException() { - } - public OutOfResourcesException(String name) { - super(name); - } - } - - /* - * We use a class initializer to allow the native code to cache some - * field offsets. - */ - native private static void nativeClassInit(); - static { nativeClassInit(); } - - - /** - * create a surface - * {@hide} - */ - public Surface(SurfaceSession s, - int pid, int display, int w, int h, int format, int flags) - throws OutOfResourcesException { - mCanvas = new Canvas(); - init(s,pid,display,w,h,format,flags); - } - - /** - * Create an empty surface, which will later be filled in by - * readFromParcel(). - * {@hide} - */ - public Surface() { - mCanvas = new Canvas(); - } - - /** - * Copy another surface to this one. This surface now holds a reference - * to the same data as the original surface, and is -not- the owner. - * {@hide} - */ - public native void copyFrom(Surface o); - - /** - * Does this object hold a valid surface? Returns true if it holds - * a physical surface, so lockCanvas() will succeed. Otherwise - * returns false. - */ - public native boolean isValid(); - - /** Call this free the surface up. {@hide} */ - public native void clear(); - - /** draw into a surface */ - public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException { - /* the dirty rectangle may be expanded to the surface's size, if - * for instance it has been resized or if the bits were lost, since - * the last call. - */ - return lockCanvasNative(dirty); - } - - private native Canvas lockCanvasNative(Rect dirty); - - /** unlock the surface and asks a page flip */ - public native void unlockCanvasAndPost(Canvas canvas); - - /** - * unlock the surface. the screen won't be updated until - * post() or postAll() is called - */ - public native void unlockCanvas(Canvas canvas); - - /** start/end a transaction {@hide} */ - public static native void openTransaction(); - /** {@hide} */ - public static native void closeTransaction(); - - /** - * Freezes the specified display, No updating of the screen will occur - * until unfreezeDisplay() is called. Everything else works as usual though, - * in particular transactions. - * @param display - * {@hide} - */ - public static native void freezeDisplay(int display); - - /** - * resume updating the specified display. - * @param display - * {@hide} - */ - public static native void unfreezeDisplay(int display); - - /** - * set the orientation of the given display. - * @param display - * @param orientation - */ - public static native void setOrientation(int display, int orientation); - - /** - * set surface parameters. - * needs to be inside open/closeTransaction block - */ - public native void setLayer(int zorder); - public native void setPosition(int x, int y); - public native void setSize(int w, int h); - - public native void hide(); - public native void show(); - public native void setTransparentRegionHint(Region region); - public native void setAlpha(float alpha); - public native void setMatrix(float dsdx, float dtdx, - float dsdy, float dtdy); - - public native void freeze(); - public native void unfreeze(); - - public native void setFreezeTint(int tint); - - public native void setFlags(int flags, int mask); - - @Override - public String toString() { - return "Surface(native-token=" + mSurface + ")"; - } - - private Surface(Parcel source) throws OutOfResourcesException { - init(source); - } - - public int describeContents() { - return 0; - } - - public native void readFromParcel(Parcel source); - public native void writeToParcel(Parcel dest, int flags); - - public static final Parcelable.Creator<Surface> CREATOR - = new Parcelable.Creator<Surface>() - { - public Surface createFromParcel(Parcel source) { - try { - return new Surface(source); - } catch (Exception e) { - Log.e(LOG_TAG, "Exception creating surface from parcel", e); - } - return null; - } - - public Surface[] newArray(int size) { - return new Surface[size]; - } - }; - - /* no user serviceable parts here ... */ - @Override - protected void finalize() throws Throwable { - clear(); - } - - private native void init(SurfaceSession s, - int pid, int display, int w, int h, int format, int flags) - throws OutOfResourcesException; - - private native void init(Parcel source); -} diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java deleted file mode 100644 index 3d0dda3..0000000 --- a/core/java/android/view/SurfaceHolder.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.graphics.Canvas; -import android.graphics.Rect; -import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_NORMAL; -import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_HARDWARE; -import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_GPU; -import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_PUSH_BUFFERS; - -/** - * Abstract interface to someone holding a display surface. Allows you to - * control the surface size and format, edit the pixels in the surface, and - * monitor changes to the surface. This interface is typically available - * through the {@link SurfaceView} class. - * - * <p>When using this interface from a thread different than the one running - * its {@link SurfaceView}, you will want to carefully read the - * {@link #lockCanvas} and {@link Callback#surfaceCreated Callback.surfaceCreated}. - */ -public interface SurfaceHolder { - /** - * Surface type. - * - * @see #SURFACE_TYPE_NORMAL - * @see #SURFACE_TYPE_HARDWARE - * @see #SURFACE_TYPE_GPU - * @see #SURFACE_TYPE_PUSH_BUFFERS - */ - - /** Surface type: creates a regular surface, usually in main, non - * contiguous, cached/buffered RAM. */ - public static final int SURFACE_TYPE_NORMAL = MEMORY_TYPE_NORMAL; - /** Surface type: creates a suited to be used with DMA engines and - * hardware accelerators. */ - public static final int SURFACE_TYPE_HARDWARE = MEMORY_TYPE_HARDWARE; - /** Surface type: creates a surface suited to be used with the GPU */ - public static final int SURFACE_TYPE_GPU = MEMORY_TYPE_GPU; - /** Surface type: creates a "push" surface, that is a surface that - * doesn't owns its buffers. With such a surface lockCanvas will fail. */ - public static final int SURFACE_TYPE_PUSH_BUFFERS = MEMORY_TYPE_PUSH_BUFFERS; - - /** - * Exception that is thrown from {@link #lockCanvas} when called on a Surface - * whose is SURFACE_TYPE_PUSH_BUFFERS. - */ - public static class BadSurfaceTypeException extends RuntimeException { - public BadSurfaceTypeException() { - } - - public BadSurfaceTypeException(String name) { - super(name); - } - } - - /** - * A client may implement this interface to receive information about - * changes to the surface. When used with a {@link SurfaceView}, the - * Surface being held is only available between calls to - * {@link #surfaceCreated(SurfaceHolder)} and - * {@link #surfaceDestroyed(SurfaceHolder). The Callback is set with - * {@link SurfaceHolder#addCallback SurfaceHolder.addCallback} method. - */ - public interface Callback { - /** - * This is called immediately after the surface is first created. - * Implementations of this should start up whatever rendering code - * they desire. Note that only one thread can ever draw into - * a {@link Surface}, so you should not draw into the Surface here - * if your normal rendering will be in another thread. - * - * @param holder The SurfaceHolder whose surface is being created. - */ - public void surfaceCreated(SurfaceHolder holder); - - /** - * This is called immediately after any structural changes (format or - * size) have been made to the surface. You should at this point update - * the imagery in the surface. This method is always called at least - * once, after {@link #surfaceCreated}. - * - * @param holder The SurfaceHolder whose surface has changed. - * @param format The new PixelFormat of the surface. - * @param width The new width of the surface. - * @param height The new height of the surface. - */ - public void surfaceChanged(SurfaceHolder holder, int format, int width, - int height); - - /** - * This is called immediately before a surface is being destroyed. After - * returning from this call, you should no longer try to access this - * surface. If you have a rendering thread that directly accesses - * the surface, you must ensure that thread is no longer touching the - * Surface before returning from this function. - * - * @param holder The SurfaceHolder whose surface is being destroyed. - */ - public void surfaceDestroyed(SurfaceHolder holder); - } - - /** - * Add a Callback interface for this holder. There can several Callback - * interfaces associated to a holder. - * - * @param callback The new Callback interface. - */ - public void addCallback(Callback callback); - - /** - * Removes a previously added Callback interface from this holder. - * - * @param callback The Callback interface to remove. - */ - public void removeCallback(Callback callback); - - /** - * Use this method to find out if the surface is in the process of being - * created from Callback methods. This is intended to be used with - * {@link Callback#surfaceChanged}. - * - * @return true if the surface is in the process of being created. - */ - public boolean isCreating(); - - /** - * Sets the surface's type. Surfaces intended to be used with OpenGL ES - * should be of SURFACE_TYPE_GPU, surfaces accessed by DMA engines and - * hardware accelerators should be of type SURFACE_TYPE_HARDWARE. - * Failing to set the surface's type appropriately could result in - * degraded performance or failure. - * - * @param type The surface's memory type. - */ - public void setType(int type); - - /** - * Make the surface a fixed size. It will never change from this size. - * When working with a {link SurfaceView}, this must be called from the - * same thread running the SurfaceView's window. - * - * @param width The surface's width. - * @param height The surface's height. - */ - public void setFixedSize(int width, int height); - - /** - * Allow the surface to resized based on layout of its container (this is - * the default). When this is enabled, you should monitor - * {@link Callback#surfaceChanged} for changes to the size of the surface. - * When working with a {link SurfaceView}, this must be called from the - * same thread running the SurfaceView's window. - */ - public void setSizeFromLayout(); - - /** - * Set the desired PixelFormat of the surface. The default is OPAQUE. - * When working with a {link SurfaceView}, this must be called from the - * same thread running the SurfaceView's window. - * - * @param format A constant from PixelFormat. - * - * @see android.graphics.PixelFormat - */ - public void setFormat(int format); - - /** - * Enable or disable option to keep the screen turned on while this - * surface is displayed. The default is false, allowing it to turn off. - * Enabling the option effectivelty. - * This is safe to call from any thread. - * - * @param screenOn Supply to true to force the screen to stay on, false - * to allow it to turn off. - */ - public void setKeepScreenOn(boolean screenOn); - - /** - * Start editing the pixels in the surface. The returned Canvas can be used - * to draw into the surface's bitmap. A null is returned if the surface has - * not been created or otherwise can not be edited. You will usually need - * to implement {@link Callback#surfaceCreated Callback.surfaceCreated} - * to find out when the Surface is available for use. - * - * <p>The content of the Surface is never preserved between unlockCanvas() and - * lockCanvas(), for this reason, every pixel within the Surface area - * must be written. The only exception to this rule is when a dirty - * rectangle is specified, in which case, non dirty pixels will be - * preserved. - * - * <p>If you call this repeatedly when the Surface is not ready (before - * {@link Callback#surfaceCreated Callback.surfaceCreated} or after - * {@link Callback#surfaceDestroyed Callback.surfaceDestroyed}), your calls - * will be throttled to a slow rate in order to avoid consuming CPU. - * - * <p>If null is not returned, this function internally holds a lock until - * the corresponding {@link #unlockCanvasAndPost} call, preventing - * {@link SurfaceView} from creating, destroying, or modifying the surface - * while it is being drawn. This can be more convenience than accessing - * the Surface directly, as you do not need to do special synchronization - * with a drawing thread in {@link Callback#surfaceDestroyed - * Callback.surfaceDestroyed}. - * - * @return Canvas Use to draw into the surface. - */ - public Canvas lockCanvas(); - - - /** - * Just like {@link #lockCanvas()} but allows to specify a dirty rectangle. - * Every - * pixel within that rectangle must be written; however pixels outside - * the dirty rectangle will be preserved by the next call to lockCanvas(). - * - * @see android.view.SurfaceHolder#lockCanvas - * - * @param dirty Area of the Surface that will be modified. - * @return Canvas Use to draw into the surface. - */ - public Canvas lockCanvas(Rect dirty); - - /** - * Finish editing pixels in the surface. After this call, the surface's - * current pixels will be shown on the screen, but its content is lost, - * in particular there is no guarantee that the content of the Surface - * will remain unchanged when lockCanvas() is called again. - * - * @see #lockCanvas() - * - * @param canvas The Canvas previously returned by lockCanvas(). - */ - public void unlockCanvasAndPost(Canvas canvas); - - /** - * Retrieve the current size of the surface. Note: do not modify the - * returned Rect. This is only safe to call from the thread of - * {@link SurfaceView}'s window, or while inside of - * {@link #lockCanvas()}. - * - * @return Rect The surface's dimensions. The left and top are always 0. - */ - public Rect getSurfaceFrame(); - - /** - * Direct access to the surface object. The Surface may not always be - * available -- for example when using a {@link SurfaceView} the holder's - * Surface is not created until the view has been attached to the window - * manager and performed a layout in order to determine the dimensions - * and screen position of the Surface. You will thus usually need - * to implement {@link Callback#surfaceCreated Callback.surfaceCreated} - * to find out when the Surface is available for use. - * - * <p>Note that if you directly access the Surface from another thread, - * it is critical that you correctly implement - * {@link Callback#surfaceCreated Callback.surfaceCreated} and - * {@link Callback#surfaceDestroyed Callback.surfaceDestroyed} to ensure - * that thread only accesses the Surface while it is valid, and that the - * Surface does not get destroyed while the thread is using it. - * - * <p>This method is intended to be used by frameworks which often need - * direct access to the Surface object (usually to pass it to native code). - * When designing APIs always use SurfaceHolder to pass surfaces around - * as opposed to the Surface object itself. A rule of thumb is that - * application code should never have to call this method. - * - * @return Surface The surface. - */ - public Surface getSurface(); -} diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java deleted file mode 100644 index 2a04675..0000000 --- a/core/java/android/view/SurfaceSession.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - - -/** - * An instance of this class represents a connection to the surface - * flinger, in which you can create one or more Surface instances that will - * be composited to the screen. - * {@hide} - */ -public class SurfaceSession { - /** Create a new connection with the surface flinger. */ - public SurfaceSession() { - init(); - } - - /** Forcibly detach native resources associated with this object. - * Unlike destroy(), after this call any surfaces that were created - * from the session will no longer work. The session itself is destroyed. - */ - public native void kill(); - - /* no user serviceable parts here ... */ - @Override - protected void finalize() throws Throwable { - destroy(); - } - - private native void init(); - private native void destroy(); - - private int mClient; -} - diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java deleted file mode 100644 index e928998..0000000 --- a/core/java/android/view/SurfaceView.java +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.PixelFormat; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.graphics.Region; -import android.os.Handler; -import android.os.Message; -import android.os.RemoteException; -import android.os.SystemClock; -import android.os.ParcelFileDescriptor; -import android.util.AttributeSet; -import android.util.Config; -import android.util.Log; -import java.util.ArrayList; - -import java.util.concurrent.locks.ReentrantLock; -import java.lang.ref.WeakReference; - -/** - * Provides a dedicated drawing surface embedded inside of a view hierarchy. - * You can control the format of this surface and, if you like, its size; the - * SurfaceView takes care of placing the surface at the correct location on the - * screen - * - * <p>The surface is Z ordered so that it is behind the window holding its - * SurfaceView; the SurfaceView punches a hole in its window to allow its - * surface to be displayed. The view hierarchy will take care of correctly - * compositing with the Surface any siblings of the SurfaceView that would - * normally appear on top of it. This can be used to place overlays such as - * buttons on top of the Surface, though note however that it can have an - * impact on performance since a full alpha-blended composite will be performed - * each time the Surface changes. - * - * <p>Access to the underlying surface is provided via the SurfaceHolder interface, - * which can be retrieved by calling {@link #getHolder}. - * - * <p>The Surface will be created for you while the SurfaceView's window is - * visible; you should implement {@link SurfaceHolder.Callback#surfaceCreated} - * and {@link SurfaceHolder.Callback#surfaceDestroyed} to discover when the - * Surface is created and destroyed as the window is shown and hidden. - * - * <p>One of the purposes of this class is to provide a surface in which a - * secondary thread can render in to the screen. If you are going to use it - * this way, you need to be aware of some threading semantics: - * - * <ul> - * <li> All SurfaceView and - * {@link SurfaceHolder.Callback SurfaceHolder.Callback} methods will be called - * from the thread running the SurfaceView's window (typically the main thread - * of the application). They thus need to correctly synchronize with any - * state that is also touched by the drawing thread. - * <li> You must ensure that the drawing thread only touches the underlying - * Surface while it is valid -- between - * {@link SurfaceHolder.Callback#surfaceCreated SurfaceHolder.Callback.surfaceCreated()} - * and - * {@link SurfaceHolder.Callback#surfaceDestroyed SurfaceHolder.Callback.surfaceDestroyed()}. - * </ul> - */ -public class SurfaceView extends View { - static private final String TAG = "SurfaceView"; - static private final boolean DEBUG = false; - static private final boolean localLOGV = DEBUG ? true : Config.LOGV; - - final ArrayList<SurfaceHolder.Callback> mCallbacks - = new ArrayList<SurfaceHolder.Callback>(); - - final int[] mLocation = new int[2]; - - final ReentrantLock mSurfaceLock = new ReentrantLock(); - final Surface mSurface = new Surface(); - boolean mDrawingStopped = true; - - final WindowManager.LayoutParams mLayout - = new WindowManager.LayoutParams(); - IWindowSession mSession; - MyWindow mWindow; - final Rect mVisibleInsets = new Rect(); - final Rect mWinFrame = new Rect(); - final Rect mContentInsets = new Rect(); - - static final int KEEP_SCREEN_ON_MSG = 1; - static final int GET_NEW_SURFACE_MSG = 2; - - boolean mIsCreating = false; - - final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case KEEP_SCREEN_ON_MSG: { - setKeepScreenOn(msg.arg1 != 0); - } break; - case GET_NEW_SURFACE_MSG: { - handleGetNewSurface(); - } break; - } - } - }; - - boolean mRequestedVisible = false; - int mRequestedWidth = -1; - int mRequestedHeight = -1; - int mRequestedFormat = PixelFormat.OPAQUE; - int mRequestedType = -1; - - boolean mHaveFrame = false; - boolean mDestroyReportNeeded = false; - boolean mNewSurfaceNeeded = false; - long mLastLockTime = 0; - - boolean mVisible = false; - int mLeft = -1; - int mTop = -1; - int mWidth = -1; - int mHeight = -1; - int mFormat = -1; - int mType = -1; - final Rect mSurfaceFrame = new Rect(); - - public SurfaceView(Context context) { - super(context); - setWillNotDraw(true); - } - - public SurfaceView(Context context, AttributeSet attrs) { - super(context, attrs); - setWillNotDraw(true); - } - - public SurfaceView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - setWillNotDraw(true); - } - - /** - * Return the SurfaceHolder providing access and control over this - * SurfaceView's underlying surface. - * - * @return SurfaceHolder The holder of the surface. - */ - public SurfaceHolder getHolder() { - return mSurfaceHolder; - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - mParent.requestTransparentRegion(this); - mSession = getWindowSession(); - mLayout.token = getWindowToken(); - mLayout.setTitle("SurfaceView"); - } - - @Override - protected void onWindowVisibilityChanged(int visibility) { - super.onWindowVisibilityChanged(visibility); - mRequestedVisible = visibility == VISIBLE; - updateWindow(false); - } - - @Override - protected void onDetachedFromWindow() { - mRequestedVisible = false; - updateWindow(false); - mHaveFrame = false; - if (mWindow != null) { - try { - mSession.remove(mWindow); - } catch (RemoteException ex) { - } - mWindow = null; - } - mSession = null; - mLayout.token = null; - - super.onDetachedFromWindow(); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int width = getDefaultSize(mRequestedWidth, widthMeasureSpec); - int height = getDefaultSize(mRequestedHeight, heightMeasureSpec); - setMeasuredDimension(width, height); - } - - @Override - protected void onScrollChanged(int l, int t, int oldl, int oldt) { - super.onScrollChanged(l, t, oldl, oldt); - updateWindow(false); - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - updateWindow(false); - } - - @Override - public boolean gatherTransparentRegion(Region region) { - boolean opaque = true; - if ((mPrivateFlags & SKIP_DRAW) == 0) { - // this view draws, remove it from the transparent region - opaque = super.gatherTransparentRegion(region); - } else if (region != null) { - int w = getWidth(); - int h = getHeight(); - if (w>0 && h>0) { - getLocationInWindow(mLocation); - // otherwise, punch a hole in the whole hierarchy - int l = mLocation[0]; - int t = mLocation[1]; - region.op(l, t, l+w, t+h, Region.Op.UNION); - } - } - if (PixelFormat.formatHasAlpha(mRequestedFormat)) { - opaque = false; - } - return opaque; - } - - @Override - public void draw(Canvas canvas) { - // draw() is not called when SKIP_DRAW is set - if ((mPrivateFlags & SKIP_DRAW) == 0) { - // punch a whole in the view-hierarchy below us - canvas.drawColor(0, PorterDuff.Mode.CLEAR); - } - super.draw(canvas); - } - - @Override - protected void dispatchDraw(Canvas canvas) { - // if SKIP_DRAW is cleared, draw() has already punched a hole - if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { - // punch a whole in the view-hierarchy below us - canvas.drawColor(0, PorterDuff.Mode.CLEAR); - } - // reposition ourselves where the surface is - mHaveFrame = true; - updateWindow(false); - super.dispatchDraw(canvas); - } - - private void updateWindow(boolean force) { - if (!mHaveFrame) { - return; - } - - int myWidth = mRequestedWidth; - if (myWidth <= 0) myWidth = getWidth(); - int myHeight = mRequestedHeight; - if (myHeight <= 0) myHeight = getHeight(); - - getLocationInWindow(mLocation); - final boolean creating = mWindow == null; - final boolean formatChanged = mFormat != mRequestedFormat; - final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight; - final boolean visibleChanged = mVisible != mRequestedVisible - || mNewSurfaceNeeded; - final boolean typeChanged = mType != mRequestedType; - if (force || creating || formatChanged || sizeChanged || visibleChanged - || typeChanged || mLeft != mLocation[0] || mTop != mLocation[1]) { - - if (localLOGV) Log.i(TAG, "Changes: creating=" + creating - + " format=" + formatChanged + " size=" + sizeChanged - + " visible=" + visibleChanged - + " left=" + (mLeft != mLocation[0]) - + " top=" + (mTop != mLocation[1])); - - try { - final boolean visible = mVisible = mRequestedVisible; - mLeft = mLocation[0]; - mTop = mLocation[1]; - mWidth = myWidth; - mHeight = myHeight; - mFormat = mRequestedFormat; - mType = mRequestedType; - - mLayout.x = mLeft; - mLayout.y = mTop; - mLayout.width = getWidth(); - mLayout.height = getHeight(); - mLayout.format = mRequestedFormat; - mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS - | WindowManager.LayoutParams.FLAG_SCALED - | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE - ; - - mLayout.memoryType = mRequestedType; - - if (mWindow == null) { - mWindow = new MyWindow(this); - mLayout.type = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; - mLayout.gravity = Gravity.LEFT|Gravity.TOP; - mSession.add(mWindow, mLayout, - mVisible ? VISIBLE : GONE, mContentInsets); - } - - if (visibleChanged && (!visible || mNewSurfaceNeeded)) { - reportSurfaceDestroyed(); - } - - mNewSurfaceNeeded = false; - - mSurfaceLock.lock(); - mDrawingStopped = !visible; - final int relayoutResult = mSession.relayout( - mWindow, mLayout, mWidth, mHeight, - visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets, - mVisibleInsets, mSurface); - if (localLOGV) Log.i(TAG, "New surface: " + mSurface - + ", vis=" + visible + ", frame=" + mWinFrame); - mSurfaceFrame.left = 0; - mSurfaceFrame.top = 0; - mSurfaceFrame.right = mWinFrame.width(); - mSurfaceFrame.bottom = mWinFrame.height(); - mSurfaceLock.unlock(); - - try { - if (visible) { - mDestroyReportNeeded = true; - - SurfaceHolder.Callback callbacks[]; - synchronized (mCallbacks) { - callbacks = new SurfaceHolder.Callback[mCallbacks.size()]; - mCallbacks.toArray(callbacks); - } - - if (visibleChanged) { - mIsCreating = true; - for (SurfaceHolder.Callback c : callbacks) { - c.surfaceCreated(mSurfaceHolder); - } - } - if (creating || formatChanged || sizeChanged - || visibleChanged) { - for (SurfaceHolder.Callback c : callbacks) { - c.surfaceChanged(mSurfaceHolder, mFormat, mWidth, mHeight); - } - } - } - } finally { - mIsCreating = false; - if (creating || (relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) { - mSession.finishDrawing(mWindow); - } - } - } catch (RemoteException ex) { - } - if (localLOGV) Log.v( - TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y + - " w=" + mLayout.width + " h=" + mLayout.height + - ", frame=" + mSurfaceFrame); - } - } - - private void reportSurfaceDestroyed() { - if (mDestroyReportNeeded) { - mDestroyReportNeeded = false; - SurfaceHolder.Callback callbacks[]; - synchronized (mCallbacks) { - callbacks = new SurfaceHolder.Callback[mCallbacks.size()]; - mCallbacks.toArray(callbacks); - } - for (SurfaceHolder.Callback c : callbacks) { - c.surfaceDestroyed(mSurfaceHolder); - } - } - super.onDetachedFromWindow(); - } - - void handleGetNewSurface() { - mNewSurfaceNeeded = true; - updateWindow(false); - } - - private static class MyWindow extends IWindow.Stub { - private WeakReference<SurfaceView> mSurfaceView; - - public MyWindow(SurfaceView surfaceView) { - mSurfaceView = new WeakReference<SurfaceView>(surfaceView); - } - - public void resized(int w, int h, Rect coveredInsets, - Rect visibleInsets, boolean reportDraw) { - SurfaceView surfaceView = mSurfaceView.get(); - if (surfaceView != null) { - if (localLOGV) Log.v( - "SurfaceView", surfaceView + " got resized: w=" + - w + " h=" + h + ", cur w=" + mCurWidth + " h=" + mCurHeight); - synchronized (this) { - if (mCurWidth != w || mCurHeight != h) { - mCurWidth = w; - mCurHeight = h; - } - if (reportDraw) { - try { - surfaceView.mSession.finishDrawing(surfaceView.mWindow); - } catch (RemoteException e) { - } - } - } - } - } - - public void dispatchKey(KeyEvent event) { - SurfaceView surfaceView = mSurfaceView.get(); - if (surfaceView != null) { - //Log.w("SurfaceView", "Unexpected key event in surface: " + event); - if (surfaceView.mSession != null && surfaceView.mSurface != null) { - try { - surfaceView.mSession.finishKey(surfaceView.mWindow); - } catch (RemoteException ex) { - } - } - } - } - - public void dispatchPointer(MotionEvent event, long eventTime) { - Log.w("SurfaceView", "Unexpected pointer event in surface: " + event); - //if (mSession != null && mSurface != null) { - // try { - // //mSession.finishKey(mWindow); - // } catch (RemoteException ex) { - // } - //} - } - - public void dispatchTrackball(MotionEvent event, long eventTime) { - Log.w("SurfaceView", "Unexpected trackball event in surface: " + event); - //if (mSession != null && mSurface != null) { - // try { - // //mSession.finishKey(mWindow); - // } catch (RemoteException ex) { - // } - //} - } - - public void dispatchAppVisibility(boolean visible) { - // The point of SurfaceView is to let the app control the surface. - } - - public void dispatchGetNewSurface() { - SurfaceView surfaceView = mSurfaceView.get(); - if (surfaceView != null) { - Message msg = surfaceView.mHandler.obtainMessage(GET_NEW_SURFACE_MSG); - surfaceView.mHandler.sendMessage(msg); - } - } - - public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) { - Log.w("SurfaceView", "Unexpected focus in surface: focus=" + hasFocus + ", touchEnabled=" + touchEnabled); - } - - public void executeCommand(String command, String parameters, ParcelFileDescriptor out) { - } - - int mCurWidth = -1; - int mCurHeight = -1; - } - - private SurfaceHolder mSurfaceHolder = new SurfaceHolder() { - - private static final String LOG_TAG = "SurfaceHolder"; - - public boolean isCreating() { - return mIsCreating; - } - - public void addCallback(Callback callback) { - synchronized (mCallbacks) { - // This is a linear search, but in practice we'll - // have only a couple callbacks, so it doesn't matter. - if (mCallbacks.contains(callback) == false) { - mCallbacks.add(callback); - } - } - } - - public void removeCallback(Callback callback) { - synchronized (mCallbacks) { - mCallbacks.remove(callback); - } - } - - public void setFixedSize(int width, int height) { - if (mRequestedWidth != width || mRequestedHeight != height) { - mRequestedWidth = width; - mRequestedHeight = height; - requestLayout(); - } - } - - public void setSizeFromLayout() { - if (mRequestedWidth != -1 || mRequestedHeight != -1) { - mRequestedWidth = mRequestedHeight = -1; - requestLayout(); - } - } - - public void setFormat(int format) { - mRequestedFormat = format; - if (mWindow != null) { - updateWindow(false); - } - } - - public void setType(int type) { - switch (type) { - case SURFACE_TYPE_NORMAL: - case SURFACE_TYPE_HARDWARE: - case SURFACE_TYPE_GPU: - case SURFACE_TYPE_PUSH_BUFFERS: - mRequestedType = type; - if (mWindow != null) { - updateWindow(false); - } - break; - } - } - - public void setKeepScreenOn(boolean screenOn) { - Message msg = mHandler.obtainMessage(KEEP_SCREEN_ON_MSG); - msg.arg1 = screenOn ? 1 : 0; - mHandler.sendMessage(msg); - } - - public Canvas lockCanvas() { - return internalLockCanvas(null); - } - - public Canvas lockCanvas(Rect dirty) { - return internalLockCanvas(dirty); - } - - private final Canvas internalLockCanvas(Rect dirty) { - if (mType == SURFACE_TYPE_PUSH_BUFFERS) { - throw new BadSurfaceTypeException( - "Surface type is SURFACE_TYPE_PUSH_BUFFERS"); - } - mSurfaceLock.lock(); - - if (localLOGV) Log.i(TAG, "Locking canvas... stopped=" - + mDrawingStopped + ", win=" + mWindow); - - Canvas c = null; - if (!mDrawingStopped && mWindow != null) { - Rect frame = dirty != null ? dirty : mSurfaceFrame; - try { - c = mSurface.lockCanvas(frame); - } catch (Exception e) { - Log.e(LOG_TAG, "Exception locking surface", e); - } - } - - if (localLOGV) Log.i(TAG, "Returned canvas: " + c); - if (c != null) { - mLastLockTime = SystemClock.uptimeMillis(); - return c; - } - - // If the Surface is not ready to be drawn, then return null, - // but throttle calls to this function so it isn't called more - // than every 100ms. - long now = SystemClock.uptimeMillis(); - long nextTime = mLastLockTime + 100; - if (nextTime > now) { - try { - Thread.sleep(nextTime-now); - } catch (InterruptedException e) { - } - now = SystemClock.uptimeMillis(); - } - mLastLockTime = now; - mSurfaceLock.unlock(); - - return null; - } - - public void unlockCanvasAndPost(Canvas canvas) { - mSurface.unlockCanvasAndPost(canvas); - mSurfaceLock.unlock(); - } - - public Surface getSurface() { - return mSurface; - } - - public Rect getSurfaceFrame() { - return mSurfaceFrame; - } - }; -} - diff --git a/core/java/android/view/TouchDelegate.java b/core/java/android/view/TouchDelegate.java deleted file mode 100644 index 27b49db..0000000 --- a/core/java/android/view/TouchDelegate.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2008 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.view; - -import android.graphics.Rect; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; - -/** - * Helper class to handle situations where you want a view to have a larger touch area than its - * actual view bounds. The view whose touch area is changed is called the delegate view. This - * class should be used by an ancestor of the delegate. To use a TouchDelegate, first create an - * instance that specifies the bounds that should be mapped to the delegate and the delegate - * view itself. - * <p> - * The ancestor should then forward all of its touch events received in its - * {@link android.view.View#onTouchEvent(MotionEvent)} to {@link #onTouchEvent(MotionEvent)}. - * </p> - */ -public class TouchDelegate { - - /** - * View that should receive forwarded touch events - */ - private View mDelegateView; - - /** - * Bounds in local coordinates of the containing view that should be mapped to the delegate - * view. This rect is used for initial hit testing. - */ - private Rect mBounds; - - /** - * mBounds inflated to include some slop. This rect is to track whether the motion events - * should be considered to be be within the delegate view. - */ - private Rect mSlopBounds; - - /** - * True if the delegate had been targeted on a down event (intersected mBounds). - */ - private boolean mDelegateTargeted; - - /** - * The touchable region of the View extends above its actual extent. - */ - public static final int ABOVE = 1; - - /** - * The touchable region of the View extends below its actual extent. - */ - public static final int BELOW = 2; - - /** - * The touchable region of the View extends to the left of its - * actual extent. - */ - public static final int TO_LEFT = 4; - - /** - * The touchable region of the View extends to the right of its - * actual extent. - */ - public static final int TO_RIGHT = 8; - - private int mSlop; - - /** - * Constructor - * - * @param bounds Bounds in local coordinates of the containing view that should be mapped to - * the delegate view - * @param delegateView The view that should receive motion events - */ - public TouchDelegate(Rect bounds, View delegateView) { - mBounds = bounds; - - mSlop = ViewConfiguration.get(delegateView.getContext()).getScaledTouchSlop(); - mSlopBounds = new Rect(bounds); - mSlopBounds.inset(-mSlop, -mSlop); - mDelegateView = delegateView; - } - - /** - * Will forward touch events to the delegate view if the event is within the bounds - * specified in the constructor. - * - * @param event The touch event to forward - * @return True if the event was forwarded to the delegate, false otherwise. - */ - public boolean onTouchEvent(MotionEvent event) { - int x = (int)event.getX(); - int y = (int)event.getY(); - boolean sendToDelegate = false; - boolean hit = true; - boolean handled = false; - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - Rect bounds = mBounds; - - if (bounds.contains(x, y)) { - mDelegateTargeted = true; - sendToDelegate = true; - } - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_MOVE: - sendToDelegate = mDelegateTargeted; - if (sendToDelegate) { - Rect slopBounds = mSlopBounds; - if (!slopBounds.contains(x, y)) { - hit = false; - } - } - break; - case MotionEvent.ACTION_CANCEL: - sendToDelegate = mDelegateTargeted; - mDelegateTargeted = false; - break; - } - if (sendToDelegate) { - final View delegateView = mDelegateView; - - if (hit) { - // Offset event coordinates to be inside the target view - event.setLocation(delegateView.getWidth() / 2, delegateView.getHeight() / 2); - } else { - // Offset event coordinates to be outside the target view (in case it does - // something like tracking pressed state) - int slop = mSlop; - event.setLocation(-(slop * 2), -(slop * 2)); - } - handled = delegateView.dispatchTouchEvent(event); - } - return handled; - } -} diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java deleted file mode 100644 index c80167e..0000000 --- a/core/java/android/view/VelocityTracker.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.util.Config; -import android.util.Log; - -/** - * Helper for tracking the velocity of touch events, for implementing - * flinging and other such gestures. Use {@link #obtain} to retrieve a - * new instance of the class when you are going to begin tracking, put - * the motion events you receive into it with {@link #addMovement(MotionEvent)}, - * and when you want to determine the velocity call - * {@link #computeCurrentVelocity(int)} and then {@link #getXVelocity()} - * and {@link #getXVelocity()}. - */ -public final class VelocityTracker { - static final String TAG = "VelocityTracker"; - static final boolean DEBUG = false; - static final boolean localLOGV = DEBUG || Config.LOGV; - - static final int NUM_PAST = 10; - static final int LONGEST_PAST_TIME = 200; - - static final VelocityTracker[] mPool = new VelocityTracker[1]; - - final float mPastX[] = new float[NUM_PAST]; - final float mPastY[] = new float[NUM_PAST]; - final long mPastTime[] = new long[NUM_PAST]; - - float mYVelocity; - float mXVelocity; - - /** - * Retrieve a new VelocityTracker object to watch the velocity of a - * motion. Be sure to call {@link #recycle} when done. You should - * generally only maintain an active object while tracking a movement, - * so that the VelocityTracker can be re-used elsewhere. - * - * @return Returns a new VelocityTracker. - */ - static public VelocityTracker obtain() { - synchronized (mPool) { - VelocityTracker vt = mPool[0]; - if (vt != null) { - vt.clear(); - return vt; - } - return new VelocityTracker(); - } - } - - /** - * Return a VelocityTracker object back to be re-used by others. You must - * not touch the object after calling this function. - */ - public void recycle() { - synchronized (mPool) { - mPool[0] = this; - } - } - - private VelocityTracker() { - } - - /** - * Reset the velocity tracker back to its initial state. - */ - public void clear() { - mPastTime[0] = 0; - } - - /** - * Add a user's movement to the tracker. You should call this for the - * initial {@link MotionEvent#ACTION_DOWN}, the following - * {@link MotionEvent#ACTION_MOVE} events that you receive, and the - * final {@link MotionEvent#ACTION_UP}. You can, however, call this - * for whichever events you desire. - * - * @param ev The MotionEvent you received and would like to track. - */ - public void addMovement(MotionEvent ev) { - long time = ev.getEventTime(); - final int N = ev.getHistorySize(); - for (int i=0; i<N; i++) { - addPoint(ev.getHistoricalX(i), ev.getHistoricalY(i), - ev.getHistoricalEventTime(i)); - } - addPoint(ev.getX(), ev.getY(), time); - } - - private void addPoint(float x, float y, long time) { - int drop = -1; - int i; - if (localLOGV) Log.v(TAG, "Adding past y=" + y + " time=" + time); - final long[] pastTime = mPastTime; - for (i=0; i<NUM_PAST; i++) { - if (pastTime[i] == 0) { - break; - } else if (pastTime[i] < time-LONGEST_PAST_TIME) { - if (localLOGV) Log.v(TAG, "Dropping past too old at " - + i + " time=" + pastTime[i]); - drop = i; - } - } - if (localLOGV) Log.v(TAG, "Add index: " + i); - if (i == NUM_PAST && drop < 0) { - drop = 0; - } - if (drop == i) drop--; - final float[] pastX = mPastX; - final float[] pastY = mPastY; - if (drop >= 0) { - if (localLOGV) Log.v(TAG, "Dropping up to #" + drop); - final int start = drop+1; - final int count = NUM_PAST-drop-1; - System.arraycopy(pastX, start, pastX, 0, count); - System.arraycopy(pastY, start, pastY, 0, count); - System.arraycopy(pastTime, start, pastTime, 0, count); - i -= (drop+1); - } - pastX[i] = x; - pastY[i] = y; - pastTime[i] = time; - i++; - if (i < NUM_PAST) { - pastTime[i] = 0; - } - } - - /** - * Compute the current velocity based on the points that have been - * collected. Only call this when you actually want to retrieve velocity - * information, as it is relatively expensive. You can then retrieve - * the velocity with {@link #getXVelocity()} and - * {@link #getYVelocity()}. - * - * @param units The units you would like the velocity in. A value of 1 - * provides pixels per millisecond, 1000 provides pixels per second, etc. - */ - public void computeCurrentVelocity(int units) { - final float[] pastX = mPastX; - final float[] pastY = mPastY; - final long[] pastTime = mPastTime; - - // Kind-of stupid. - final float oldestX = pastX[0]; - final float oldestY = pastY[0]; - final long oldestTime = pastTime[0]; - float accumX = 0; - float accumY = 0; - int N=0; - while (N < NUM_PAST) { - if (pastTime[N] == 0) { - break; - } - N++; - } - // Skip the last received event, since it is probably pretty noisy. - if (N > 3) N--; - - for (int i=1; i < N; i++) { - final int dur = (int)(pastTime[i] - oldestTime); - if (dur == 0) continue; - float dist = pastX[i] - oldestX; - float vel = (dist/dur) * units; // pixels/frame. - if (accumX == 0) accumX = vel; - else accumX = (accumX + vel) * .5f; - - dist = pastY[i] - oldestY; - vel = (dist/dur) * units; // pixels/frame. - if (accumY == 0) accumY = vel; - else accumY = (accumY + vel) * .5f; - } - mXVelocity = accumX; - mYVelocity = accumY; - - if (localLOGV) Log.v(TAG, "Y velocity=" + mYVelocity +" X velocity=" - + mXVelocity + " N=" + N); - } - - /** - * Retrieve the last computed X velocity. You must first call - * {@link #computeCurrentVelocity(int)} before calling this function. - * - * @return The previously computed X velocity. - */ - public float getXVelocity() { - return mXVelocity; - } - - /** - * Retrieve the last computed Y velocity. You must first call - * {@link #computeCurrentVelocity(int)} before calling this function. - * - * @return The previously computed Y velocity. - */ - public float getYVelocity() { - return mYVelocity; - } -} diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java deleted file mode 100644 index 5ed3a7e..0000000 --- a/core/java/android/view/View.java +++ /dev/null @@ -1,8067 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.LinearGradient; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.Rect; -import android.graphics.Region; -import android.graphics.Shader; -import android.graphics.Point; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.RemoteException; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.util.AttributeSet; -import android.util.EventLog; -import android.util.Log; -import android.util.SparseArray; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.animation.Animation; -import android.view.inputmethod.InputConnection; -import android.view.inputmethod.InputMethodManager; -import android.view.inputmethod.EditorInfo; -import android.widget.ScrollBarDrawable; - -import com.android.internal.R; -import com.android.internal.view.menu.MenuBuilder; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * <p> - * This class represents the basic building block for user interface components. A View - * occupies a rectangular area on the screen and is responsible for drawing and - * event handling. View is the base class for <em>widgets</em>, which are - * used to create interactive UI components (buttons, text fields, etc.). The - * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which - * are invisible containers that hold other Views (or other ViewGroups) and define - * their layout properties. - * </p> - * - * <div class="special"> - * <p>For an introduction to using this class to develop your - * application's user interface, read the Developer Guide documentation on - * <strong><a href="{@docRoot}guide/topics/ui/index.html">User Interface</a></strong>. Special topics - * include: - * <br/><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a> - * <br/><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a> - * <br/><a href="{@docRoot}guide/topics/ui/layout-objects.html">Common Layout Objects</a> - * <br/><a href="{@docRoot}guide/topics/ui/binding.html">Binding to Data with AdapterView</a> - * <br/><a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a> - * <br/><a href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a> - * <br/><a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a> - * <br/><a href="{@docRoot}guide/topics/ui/how-android-draws.html">How Android Draws Views</a>. - * </p> - * </div> - * - * <a name="Using"></a> - * <h3>Using Views</h3> - * <p> - * All of the views in a window are arranged in a single tree. You can add views - * either from code or by specifying a tree of views in one or more XML layout - * files. There are many specialized subclasses of views that act as controls or - * are capable of displaying text, images, or other content. - * </p> - * <p> - * Once you have created a tree of views, there are typically a few types of - * common operations you may wish to perform: - * <ul> - * <li><strong>Set properties:</strong> for example setting the text of a - * {@link android.widget.TextView}. The available properties and the methods - * that set them will vary among the different subclasses of views. Note that - * properties that are known at build time can be set in the XML layout - * files.</li> - * <li><strong>Set focus:</strong> The framework will handled moving focus in - * response to user input. To force focus to a specific view, call - * {@link #requestFocus}.</li> - * <li><strong>Set up listeners:</strong> Views allow clients to set listeners - * that will be notified when something interesting happens to the view. For - * example, all views will let you set a listener to be notified when the view - * gains or loses focus. You can register such a listener using - * {@link #setOnFocusChangeListener}. Other view subclasses offer more - * specialized listeners. For example, a Button exposes a listener to notify - * clients when the button is clicked.</li> - * <li><strong>Set visibility:</strong> You can hide or show views using - * {@link #setVisibility}.</li> - * </ul> - * </p> - * <p><em> - * Note: The Android framework is responsible for measuring, laying out and - * drawing views. You should not call methods that perform these actions on - * views yourself unless you are actually implementing a - * {@link android.view.ViewGroup}. - * </em></p> - * - * <a name="Lifecycle"></a> - * <h3>Implementing a Custom View</h3> - * - * <p> - * To implement a custom view, you will usually begin by providing overrides for - * some of the standard methods that the framework calls on all views. You do - * not need to override all of these methods. In fact, you can start by just - * overriding {@link #onDraw(android.graphics.Canvas)}. - * <table border="2" width="85%" align="center" cellpadding="5"> - * <thead> - * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr> - * </thead> - * - * <tbody> - * <tr> - * <td rowspan="2">Creation</td> - * <td>Constructors</td> - * <td>There is a form of the constructor that are called when the view - * is created from code and a form that is called when the view is - * inflated from a layout file. The second form should parse and apply - * any attributes defined in the layout file. - * </td> - * </tr> - * <tr> - * <td><code>{@link #onFinishInflate()}</code></td> - * <td>Called after a view and all of its children has been inflated - * from XML.</td> - * </tr> - * - * <tr> - * <td rowspan="3">Layout</td> - * <td><code>{@link #onMeasure}</code></td> - * <td>Called to determine the size requirements for this view and all - * of its children. - * </td> - * </tr> - * <tr> - * <td><code>{@link #onLayout}</code></td> - * <td>Called when this view should assign a size and position to all - * of its children. - * </td> - * </tr> - * <tr> - * <td><code>{@link #onSizeChanged}</code></td> - * <td>Called when the size of this view has changed. - * </td> - * </tr> - * - * <tr> - * <td>Drawing</td> - * <td><code>{@link #onDraw}</code></td> - * <td>Called when the view should render its content. - * </td> - * </tr> - * - * <tr> - * <td rowspan="4">Event processing</td> - * <td><code>{@link #onKeyDown}</code></td> - * <td>Called when a new key event occurs. - * </td> - * </tr> - * <tr> - * <td><code>{@link #onKeyUp}</code></td> - * <td>Called when a key up event occurs. - * </td> - * </tr> - * <tr> - * <td><code>{@link #onTrackballEvent}</code></td> - * <td>Called when a trackball motion event occurs. - * </td> - * </tr> - * <tr> - * <td><code>{@link #onTouchEvent}</code></td> - * <td>Called when a touch screen motion event occurs. - * </td> - * </tr> - * - * <tr> - * <td rowspan="2">Focus</td> - * <td><code>{@link #onFocusChanged}</code></td> - * <td>Called when the view gains or loses focus. - * </td> - * </tr> - * - * <tr> - * <td><code>{@link #onWindowFocusChanged}</code></td> - * <td>Called when the window containing the view gains or loses focus. - * </td> - * </tr> - * - * <tr> - * <td rowspan="3">Attaching</td> - * <td><code>{@link #onAttachedToWindow()}</code></td> - * <td>Called when the view is attached to a window. - * </td> - * </tr> - * - * <tr> - * <td><code>{@link #onDetachedFromWindow}</code></td> - * <td>Called when the view is detached from its window. - * </td> - * </tr> - * - * <tr> - * <td><code>{@link #onWindowVisibilityChanged}</code></td> - * <td>Called when the visibility of the window containing the view - * has changed. - * </td> - * </tr> - * </tbody> - * - * </table> - * </p> - * - * <a name="IDs"></a> - * <h3>IDs</h3> - * Views may have an integer id associated with them. These ids are typically - * assigned in the layout XML files, and are used to find specific views within - * the view tree. A common pattern is to: - * <ul> - * <li>Define a Button in the layout file and assign it a unique ID. - * <pre> - * <Button id="@+id/my_button" - * android:layout_width="wrap_content" - * android:layout_height="wrap_content" - * android:text="@string/my_button_text"/> - * </pre></li> - * <li>From the onCreate method of an Activity, find the Button - * <pre class="prettyprint"> - * Button myButton = (Button) findViewById(R.id.my_button); - * </pre></li> - * </ul> - * <p> - * View IDs need not be unique throughout the tree, but it is good practice to - * ensure that they are at least unique within the part of the tree you are - * searching. - * </p> - * - * <a name="Position"></a> - * <h3>Position</h3> - * <p> - * The geometry of a view is that of a rectangle. A view has a location, - * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and - * two dimensions, expressed as a width and a height. The unit for location - * and dimensions is the pixel. - * </p> - * - * <p> - * It is possible to retrieve the location of a view by invoking the methods - * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X, - * coordinate of the rectangle representing the view. The latter returns the - * top, or Y, coordinate of the rectangle representing the view. These methods - * both return the location of the view relative to its parent. For instance, - * when getLeft() returns 20, that means the view is located 20 pixels to the - * right of the left edge of its direct parent. - * </p> - * - * <p> - * In addition, several convenience methods are offered to avoid unnecessary - * computations, namely {@link #getRight()} and {@link #getBottom()}. - * These methods return the coordinates of the right and bottom edges of the - * rectangle representing the view. For instance, calling {@link #getRight()} - * is similar to the following computation: <code>getLeft() + getWidth()</code> - * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.) - * </p> - * - * <a name="SizePaddingMargins"></a> - * <h3>Size, padding and margins</h3> - * <p> - * The size of a view is expressed with a width and a height. A view actually - * possess two pairs of width and height values. - * </p> - * - * <p> - * The first pair is known as <em>measured width</em> and - * <em>measured height</em>. These dimensions define how big a view wants to be - * within its parent (see <a href="#Layout">Layout</a> for more details.) The - * measured dimensions can be obtained by calling {@link #getMeasuredWidth()} - * and {@link #getMeasuredHeight()}. - * </p> - * - * <p> - * The second pair is simply known as <em>width</em> and <em>height</em>, or - * sometimes <em>drawing width</em> and <em>drawing height</em>. These - * dimensions define the actual size of the view on screen, at drawing time and - * after layout. These values may, but do not have to, be different from the - * measured width and height. The width and height can be obtained by calling - * {@link #getWidth()} and {@link #getHeight()}. - * </p> - * - * <p> - * To measure its dimensions, a view takes into account its padding. The padding - * is expressed in pixels for the left, top, right and bottom parts of the view. - * Padding can be used to offset the content of the view by a specific amount of - * pixels. For instance, a left padding of 2 will push the view's content by - * 2 pixels to the right of the left edge. Padding can be set using the - * {@link #setPadding(int, int, int, int)} method and queried by calling - * {@link #getPaddingLeft()}, {@link #getPaddingTop()}, - * {@link #getPaddingRight()} and {@link #getPaddingBottom()}. - * </p> - * - * <p> - * Even though a view can define a padding, it does not provide any support for - * margins. However, view groups provide such a support. Refer to - * {@link android.view.ViewGroup} and - * {@link android.view.ViewGroup.MarginLayoutParams} for further information. - * </p> - * - * <a name="Layout"></a> - * <h3>Layout</h3> - * <p> - * Layout is a two pass process: a measure pass and a layout pass. The measuring - * pass is implemented in {@link #measure(int, int)} and is a top-down traversal - * of the view tree. Each view pushes dimension specifications down the tree - * during the recursion. At the end of the measure pass, every view has stored - * its measurements. The second pass happens in - * {@link #layout(int,int,int,int)} and is also top-down. During - * this pass each parent is responsible for positioning all of its children - * using the sizes computed in the measure pass. - * </p> - * - * <p> - * When a view's measure() method returns, its {@link #getMeasuredWidth()} and - * {@link #getMeasuredHeight()} values must be set, along with those for all of - * that view's descendants. A view's measured width and measured height values - * must respect the constraints imposed by the view's parents. This guarantees - * that at the end of the measure pass, all parents accept all of their - * children's measurements. A parent view may call measure() more than once on - * its children. For example, the parent may measure each child once with - * unspecified dimensions to find out how big they want to be, then call - * measure() on them again with actual numbers if the sum of all the children's - * unconstrained sizes is too big or too small. - * </p> - * - * <p> - * The measure pass uses two classes to communicate dimensions. The - * {@link MeasureSpec} class is used by views to tell their parents how they - * want to be measured and positioned. The base LayoutParams class just - * describes how big the view wants to be for both width and height. For each - * dimension, it can specify one of: - * <ul> - * <li> an exact number - * <li>FILL_PARENT, which means the view wants to be as big as its parent - * (minus padding) - * <li> WRAP_CONTENT, which means that the view wants to be just big enough to - * enclose its content (plus padding). - * </ul> - * There are subclasses of LayoutParams for different subclasses of ViewGroup. - * For example, AbsoluteLayout has its own subclass of LayoutParams which adds - * an X and Y value. - * </p> - * - * <p> - * MeasureSpecs are used to push requirements down the tree from parent to - * child. A MeasureSpec can be in one of three modes: - * <ul> - * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension - * of a child view. For example, a LinearLayout may call measure() on its child - * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how - * tall the child view wants to be given a width of 240 pixels. - * <li>EXACTLY: This is used by the parent to impose an exact size on the - * child. The child must use this size, and guarantee that all of its - * descendants will fit within this size. - * <li>AT_MOST: This is used by the parent to impose a maximum size on the - * child. The child must gurantee that it and all of its descendants will fit - * within this size. - * </ul> - * </p> - * - * <p> - * To intiate a layout, call {@link #requestLayout}. This method is typically - * called by a view on itself when it believes that is can no longer fit within - * its current bounds. - * </p> - * - * <a name="Drawing"></a> - * <h3>Drawing</h3> - * <p> - * Drawing is handled by walking the tree and rendering each view that - * intersects the the invalid region. Because the tree is traversed in-order, - * this means that parents will draw before (i.e., behind) their children, with - * siblings drawn in the order they appear in the tree. - * If you set a background drawable for a View, then the View will draw it for you - * before calling back to its <code>onDraw()</code> method. - * </p> - * - * <p> - * Note that the framework will not draw views that are not in the invalid region. - * </p> - * - * <p> - * To force a view to draw, call {@link #invalidate()}. - * </p> - * - * <a name="EventHandlingThreading"></a> - * <h3>Event Handling and Threading</h3> - * <p> - * The basic cycle of a view is as follows: - * <ol> - * <li>An event comes in and is dispatched to the appropriate view. The view - * handles the event and notifies any listeners.</li> - * <li>If in the course of processing the event, the view's bounds may need - * to be changed, the view will call {@link #requestLayout()}.</li> - * <li>Similarly, if in the course of processing the event the view's appearance - * may need to be changed, the view will call {@link #invalidate()}.</li> - * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called, - * the framework will take care of measuring, laying out, and drawing the tree - * as appropriate.</li> - * </ol> - * </p> - * - * <p><em>Note: The entire view tree is single threaded. You must always be on - * the UI thread when calling any method on any view.</em> - * If you are doing work on other threads and want to update the state of a view - * from that thread, you should use a {@link Handler}. - * </p> - * - * <a name="FocusHandling"></a> - * <h3>Focus Handling</h3> - * <p> - * The framework will handle routine focus movement in response to user input. - * This includes changing the focus as views are removed or hidden, or as new - * views become available. Views indicate their willingness to take focus - * through the {@link #isFocusable} method. To change whether a view can take - * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below) - * views indicate whether they still would like focus via {@link #isFocusableInTouchMode} - * and can change this via {@link #setFocusableInTouchMode(boolean)}. - * </p> - * <p> - * Focus movement is based on an algorithm which finds the nearest neighbor in a - * given direction. In rare cases, the default algorithm may not match the - * intended behavior of the developer. In these situations, you can provide - * explicit overrides by using these XML attributes in the layout file: - * <pre> - * nextFocusDown - * nextFocusLeft - * nextFocusRight - * nextFocusUp - * </pre> - * </p> - * - * - * <p> - * To get a particular view to take focus, call {@link #requestFocus()}. - * </p> - * - * <a name="TouchMode"></a> - * <h3>Touch Mode</h3> - * <p> - * When a user is navigating a user interface via directional keys such as a D-pad, it is - * necessary to give focus to actionable items such as buttons so the user can see - * what will take input. If the device has touch capabilities, however, and the user - * begins interacting with the interface by touching it, it is no longer necessary to - * always highlight, or give focus to, a particular view. This motivates a mode - * for interaction named 'touch mode'. - * </p> - * <p> - * For a touch capable device, once the user touches the screen, the device - * will enter touch mode. From this point onward, only views for which - * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets. - * Other views that are touchable, like buttons, will not take focus when touched; they will - * only fire the on click listeners. - * </p> - * <p> - * Any time a user hits a directional key, such as a D-pad direction, the view device will - * exit touch mode, and find a view to take focus, so that the user may resume interacting - * with the user interface without touching the screen again. - * </p> - * <p> - * The touch mode state is maintained across {@link android.app.Activity}s. Call - * {@link #isInTouchMode} to see whether the device is currently in touch mode. - * </p> - * - * <a name="Scrolling"></a> - * <h3>Scrolling</h3> - * <p> - * The framework provides basic support for views that wish to internally - * scroll their content. This includes keeping track of the X and Y scroll - * offset as well as mechanisms for drawing scrollbars. See - * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)} for more details. - * </p> - * - * <a name="Tags"></a> - * <h3>Tags</h3> - * <p> - * Unlike IDs, tags are not used to identify views. Tags are essentially an - * extra piece of information that can be associated with a view. They are most - * often used as a convenience to store data related to views in the views - * themselves rather than by putting them in a separate structure. - * </p> - * - * <a name="Animation"></a> - * <h3>Animation</h3> - * <p> - * You can attach an {@link Animation} object to a view using - * {@link #setAnimation(Animation)} or - * {@link #startAnimation(Animation)}. The animation can alter the scale, - * rotation, translation and alpha of a view over time. If the animation is - * attached to a view that has children, the animation will affect the entire - * subtree rooted by that node. When an animation is started, the framework will - * take care of redrawing the appropriate views until the animation completes. - * </p> - * - * @attr ref android.R.styleable#View_fitsSystemWindows - * @attr ref android.R.styleable#View_nextFocusDown - * @attr ref android.R.styleable#View_nextFocusLeft - * @attr ref android.R.styleable#View_nextFocusRight - * @attr ref android.R.styleable#View_nextFocusUp - * @attr ref android.R.styleable#View_scrollX - * @attr ref android.R.styleable#View_scrollY - * @attr ref android.R.styleable#View_scrollbarTrackHorizontal - * @attr ref android.R.styleable#View_scrollbarThumbHorizontal - * @attr ref android.R.styleable#View_scrollbarSize - * @attr ref android.R.styleable#View_scrollbars - * @attr ref android.R.styleable#View_scrollbarThumbVertical - * @attr ref android.R.styleable#View_scrollbarTrackVertical - * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack - * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack - * - * @see android.view.ViewGroup - */ -public class View implements Drawable.Callback, KeyEvent.Callback { - private static final boolean DBG = false; - - /** - * The logging tag used by this class with android.util.Log. - */ - protected static final String VIEW_LOG_TAG = "View"; - - /** - * Used to mark a View that has no ID. - */ - public static final int NO_ID = -1; - - /** - * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when - * calling setFlags. - */ - private static final int NOT_FOCUSABLE = 0x00000000; - - /** - * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling - * setFlags. - */ - private static final int FOCUSABLE = 0x00000001; - - /** - * Mask for use with setFlags indicating bits used for focus. - */ - private static final int FOCUSABLE_MASK = 0x00000001; - - /** - * This view will adjust its padding to fit sytem windows (e.g. status bar) - */ - private static final int FITS_SYSTEM_WINDOWS = 0x00000002; - - /** - * This view is visible. Use with {@link #setVisibility}. - */ - public static final int VISIBLE = 0x00000000; - - /** - * This view is invisible, but it still takes up space for layout purposes. - * Use with {@link #setVisibility}. - */ - public static final int INVISIBLE = 0x00000004; - - /** - * This view is invisible, and it doesn't take any space for layout - * purposes. Use with {@link #setVisibility}. - */ - public static final int GONE = 0x00000008; - - /** - * Mask for use with setFlags indicating bits used for visibility. - * {@hide} - */ - static final int VISIBILITY_MASK = 0x0000000C; - - private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE}; - - /** - * This view is enabled. Intrepretation varies by subclass. - * Use with ENABLED_MASK when calling setFlags. - * {@hide} - */ - static final int ENABLED = 0x00000000; - - /** - * This view is disabled. Intrepretation varies by subclass. - * Use with ENABLED_MASK when calling setFlags. - * {@hide} - */ - static final int DISABLED = 0x00000020; - - /** - * Mask for use with setFlags indicating bits used for indicating whether - * this view is enabled - * {@hide} - */ - static final int ENABLED_MASK = 0x00000020; - - /** - * This view won't draw. {@link #onDraw} won't be called and further - * optimizations - * will be performed. It is okay to have this flag set and a background. - * Use with DRAW_MASK when calling setFlags. - * {@hide} - */ - static final int WILL_NOT_DRAW = 0x00000080; - - /** - * Mask for use with setFlags indicating bits used for indicating whether - * this view is will draw - * {@hide} - */ - static final int DRAW_MASK = 0x00000080; - - /** - * <p>This view doesn't show scrollbars.</p> - * {@hide} - */ - static final int SCROLLBARS_NONE = 0x00000000; - - /** - * <p>This view shows horizontal scrollbars.</p> - * {@hide} - */ - static final int SCROLLBARS_HORIZONTAL = 0x00000100; - - /** - * <p>This view shows vertical scrollbars.</p> - * {@hide} - */ - static final int SCROLLBARS_VERTICAL = 0x00000200; - - /** - * <p>Mask for use with setFlags indicating bits used for indicating which - * scrollbars are enabled.</p> - * {@hide} - */ - static final int SCROLLBARS_MASK = 0x00000300; - - // note 0x00000400 and 0x00000800 are now available for next flags... - - /** - * <p>This view doesn't show fading edges.</p> - * {@hide} - */ - static final int FADING_EDGE_NONE = 0x00000000; - - /** - * <p>This view shows horizontal fading edges.</p> - * {@hide} - */ - static final int FADING_EDGE_HORIZONTAL = 0x00001000; - - /** - * <p>This view shows vertical fading edges.</p> - * {@hide} - */ - static final int FADING_EDGE_VERTICAL = 0x00002000; - - /** - * <p>Mask for use with setFlags indicating bits used for indicating which - * fading edges are enabled.</p> - * {@hide} - */ - static final int FADING_EDGE_MASK = 0x00003000; - - /** - * <p>Indicates this view can be clicked. When clickable, a View reacts - * to clicks by notifying the OnClickListener.<p> - * {@hide} - */ - static final int CLICKABLE = 0x00004000; - - /** - * <p>Indicates this view is caching its drawing into a bitmap.</p> - * {@hide} - */ - static final int DRAWING_CACHE_ENABLED = 0x00008000; - - /** - * <p>Indicates that no icicle should be saved for this view.<p> - * {@hide} - */ - static final int SAVE_DISABLED = 0x000010000; - - /** - * <p>Mask for use with setFlags indicating bits used for the saveEnabled - * property.</p> - * {@hide} - */ - static final int SAVE_DISABLED_MASK = 0x000010000; - - /** - * <p>Indicates that no drawing cache should ever be created for this view.<p> - * {@hide} - */ - static final int WILL_NOT_CACHE_DRAWING = 0x000020000; - - /** - * <p>Indicates this view can take / keep focus when int touch mode.</p> - * {@hide} - */ - static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000; - - /** - * <p>Enables low quality mode for the drawing cache.</p> - */ - public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000; - - /** - * <p>Enables high quality mode for the drawing cache.</p> - */ - public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000; - - /** - * <p>Enables automatic quality mode for the drawing cache.</p> - */ - public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000; - - private static final int[] DRAWING_CACHE_QUALITY_FLAGS = { - DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH - }; - - /** - * <p>Mask for use with setFlags indicating bits used for the cache - * quality property.</p> - * {@hide} - */ - static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000; - - /** - * <p> - * Indicates this view can be long clicked. When long clickable, a View - * reacts to long clicks by notifying the OnLongClickListener or showing a - * context menu. - * </p> - * {@hide} - */ - static final int LONG_CLICKABLE = 0x00200000; - - /** - * <p>Indicates that this view gets its drawable states from its direct parent - * and ignores its original internal states.</p> - * - * @hide - */ - static final int DUPLICATE_PARENT_STATE = 0x00400000; - - /** - * The scrollbar style to display the scrollbars inside the content area, - * without increasing the padding. The scrollbars will be overlaid with - * translucency on the view's content. - */ - public static final int SCROLLBARS_INSIDE_OVERLAY = 0; - - /** - * The scrollbar style to display the scrollbars inside the padded area, - * increasing the padding of the view. The scrollbars will not overlap the - * content area of the view. - */ - public static final int SCROLLBARS_INSIDE_INSET = 0x01000000; - - /** - * The scrollbar style to display the scrollbars at the edge of the view, - * without increasing the padding. The scrollbars will be overlaid with - * translucency. - */ - public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000; - - /** - * The scrollbar style to display the scrollbars at the edge of the view, - * increasing the padding of the view. The scrollbars will only overlap the - * background, if any. - */ - public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000; - - /** - * Mask to check if the scrollbar style is overlay or inset. - * {@hide} - */ - static final int SCROLLBARS_INSET_MASK = 0x01000000; - - /** - * Mask to check if the scrollbar style is inside or outside. - * {@hide} - */ - static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000; - - /** - * Mask for scrollbar style. - * {@hide} - */ - static final int SCROLLBARS_STYLE_MASK = 0x03000000; - - /** - * View flag indicating that the screen should remain on while the - * window containing this view is visible to the user. This effectively - * takes care of automatically setting the WindowManager's - * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}. - */ - public static final int KEEP_SCREEN_ON = 0x04000000; - - /** - * View flag indicating whether this view should have sound effects enabled - * for events such as clicking and touching. - */ - public static final int SOUND_EFFECTS_ENABLED = 0x08000000; - - /** - * View flag indicating whether this view should have haptic feedback - * enabled for events such as long presses. - */ - public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000; - - /** - * Use with {@link #focusSearch}. Move focus to the previous selectable - * item. - */ - public static final int FOCUS_BACKWARD = 0x00000001; - - /** - * Use with {@link #focusSearch}. Move focus to the next selectable - * item. - */ - public static final int FOCUS_FORWARD = 0x00000002; - - /** - * Use with {@link #focusSearch}. Move focus to the left. - */ - public static final int FOCUS_LEFT = 0x00000011; - - /** - * Use with {@link #focusSearch}. Move focus up. - */ - public static final int FOCUS_UP = 0x00000021; - - /** - * Use with {@link #focusSearch}. Move focus to the right. - */ - public static final int FOCUS_RIGHT = 0x00000042; - - /** - * Use with {@link #focusSearch}. Move focus down. - */ - public static final int FOCUS_DOWN = 0x00000082; - - /** - * Base View state sets - */ - // Singles - /** - * Indicates the view has no states set. States are used with - * {@link android.graphics.drawable.Drawable} to change the drawing of the - * view depending on its state. - * - * @see android.graphics.drawable.Drawable - * @see #getDrawableState() - */ - protected static final int[] EMPTY_STATE_SET = {}; - /** - * Indicates the view is enabled. States are used with - * {@link android.graphics.drawable.Drawable} to change the drawing of the - * view depending on its state. - * - * @see android.graphics.drawable.Drawable - * @see #getDrawableState() - */ - protected static final int[] ENABLED_STATE_SET = {R.attr.state_enabled}; - /** - * Indicates the view is focused. States are used with - * {@link android.graphics.drawable.Drawable} to change the drawing of the - * view depending on its state. - * - * @see android.graphics.drawable.Drawable - * @see #getDrawableState() - */ - protected static final int[] FOCUSED_STATE_SET = {R.attr.state_focused}; - /** - * Indicates the view is selected. States are used with - * {@link android.graphics.drawable.Drawable} to change the drawing of the - * view depending on its state. - * - * @see android.graphics.drawable.Drawable - * @see #getDrawableState() - */ - protected static final int[] SELECTED_STATE_SET = {R.attr.state_selected}; - /** - * Indicates the view is pressed. States are used with - * {@link android.graphics.drawable.Drawable} to change the drawing of the - * view depending on its state. - * - * @see android.graphics.drawable.Drawable - * @see #getDrawableState() - * @hide - */ - protected static final int[] PRESSED_STATE_SET = {R.attr.state_pressed}; - /** - * Indicates the view's window has focus. States are used with - * {@link android.graphics.drawable.Drawable} to change the drawing of the - * view depending on its state. - * - * @see android.graphics.drawable.Drawable - * @see #getDrawableState() - */ - protected static final int[] WINDOW_FOCUSED_STATE_SET = - {R.attr.state_window_focused}; - // Doubles - /** - * Indicates the view is enabled and has the focus. - * - * @see #ENABLED_STATE_SET - * @see #FOCUSED_STATE_SET - */ - protected static final int[] ENABLED_FOCUSED_STATE_SET = - stateSetUnion(ENABLED_STATE_SET, FOCUSED_STATE_SET); - /** - * Indicates the view is enabled and selected. - * - * @see #ENABLED_STATE_SET - * @see #SELECTED_STATE_SET - */ - protected static final int[] ENABLED_SELECTED_STATE_SET = - stateSetUnion(ENABLED_STATE_SET, SELECTED_STATE_SET); - /** - * Indicates the view is enabled and that its window has focus. - * - * @see #ENABLED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - /** - * Indicates the view is focused and selected. - * - * @see #FOCUSED_STATE_SET - * @see #SELECTED_STATE_SET - */ - protected static final int[] FOCUSED_SELECTED_STATE_SET = - stateSetUnion(FOCUSED_STATE_SET, SELECTED_STATE_SET); - /** - * Indicates the view has the focus and that its window has the focus. - * - * @see #FOCUSED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - /** - * Indicates the view is selected and that its window has the focus. - * - * @see #SELECTED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - // Triples - /** - * Indicates the view is enabled, focused and selected. - * - * @see #ENABLED_STATE_SET - * @see #FOCUSED_STATE_SET - * @see #SELECTED_STATE_SET - */ - protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET = - stateSetUnion(ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET); - /** - * Indicates the view is enabled, focused and its window has the focus. - * - * @see #ENABLED_STATE_SET - * @see #FOCUSED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - /** - * Indicates the view is enabled, selected and its window has the focus. - * - * @see #ENABLED_STATE_SET - * @see #SELECTED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - /** - * Indicates the view is focused, selected and its window has the focus. - * - * @see #FOCUSED_STATE_SET - * @see #SELECTED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - /** - * Indicates the view is enabled, focused, selected and its window - * has the focus. - * - * @see #ENABLED_STATE_SET - * @see #FOCUSED_STATE_SET - * @see #SELECTED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(ENABLED_FOCUSED_SELECTED_STATE_SET, - WINDOW_FOCUSED_STATE_SET); - - /** - * Indicates the view is pressed and its window has the focus. - * - * @see #PRESSED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(PRESSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - - /** - * Indicates the view is pressed and selected. - * - * @see #PRESSED_STATE_SET - * @see #SELECTED_STATE_SET - */ - protected static final int[] PRESSED_SELECTED_STATE_SET = - stateSetUnion(PRESSED_STATE_SET, SELECTED_STATE_SET); - - /** - * Indicates the view is pressed, selected and its window has the focus. - * - * @see #PRESSED_STATE_SET - * @see #SELECTED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(PRESSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - - /** - * Indicates the view is pressed and focused. - * - * @see #PRESSED_STATE_SET - * @see #FOCUSED_STATE_SET - */ - protected static final int[] PRESSED_FOCUSED_STATE_SET = - stateSetUnion(PRESSED_STATE_SET, FOCUSED_STATE_SET); - - /** - * Indicates the view is pressed, focused and its window has the focus. - * - * @see #PRESSED_STATE_SET - * @see #FOCUSED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(PRESSED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - - /** - * Indicates the view is pressed, focused and selected. - * - * @see #PRESSED_STATE_SET - * @see #SELECTED_STATE_SET - * @see #FOCUSED_STATE_SET - */ - protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET = - stateSetUnion(PRESSED_FOCUSED_STATE_SET, SELECTED_STATE_SET); - - /** - * Indicates the view is pressed, focused, selected and its window has the focus. - * - * @see #PRESSED_STATE_SET - * @see #FOCUSED_STATE_SET - * @see #SELECTED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(PRESSED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - - /** - * Indicates the view is pressed and enabled. - * - * @see #PRESSED_STATE_SET - * @see #ENABLED_STATE_SET - */ - protected static final int[] PRESSED_ENABLED_STATE_SET = - stateSetUnion(PRESSED_STATE_SET, ENABLED_STATE_SET); - - /** - * Indicates the view is pressed, enabled and its window has the focus. - * - * @see #PRESSED_STATE_SET - * @see #ENABLED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(PRESSED_ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - - /** - * Indicates the view is pressed, enabled and selected. - * - * @see #PRESSED_STATE_SET - * @see #ENABLED_STATE_SET - * @see #SELECTED_STATE_SET - */ - protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET = - stateSetUnion(PRESSED_ENABLED_STATE_SET, SELECTED_STATE_SET); - - /** - * Indicates the view is pressed, enabled, selected and its window has the - * focus. - * - * @see #PRESSED_STATE_SET - * @see #ENABLED_STATE_SET - * @see #SELECTED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(PRESSED_ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - - /** - * Indicates the view is pressed, enabled and focused. - * - * @see #PRESSED_STATE_SET - * @see #ENABLED_STATE_SET - * @see #FOCUSED_STATE_SET - */ - protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET = - stateSetUnion(PRESSED_ENABLED_STATE_SET, FOCUSED_STATE_SET); - - /** - * Indicates the view is pressed, enabled, focused and its window has the - * focus. - * - * @see #PRESSED_STATE_SET - * @see #ENABLED_STATE_SET - * @see #FOCUSED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - - /** - * Indicates the view is pressed, enabled, focused and selected. - * - * @see #PRESSED_STATE_SET - * @see #ENABLED_STATE_SET - * @see #SELECTED_STATE_SET - * @see #FOCUSED_STATE_SET - */ - protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = - stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET); - - /** - * Indicates the view is pressed, enabled, focused, selected and its window - * has the focus. - * - * @see #PRESSED_STATE_SET - * @see #ENABLED_STATE_SET - * @see #SELECTED_STATE_SET - * @see #FOCUSED_STATE_SET - * @see #WINDOW_FOCUSED_STATE_SET - */ - protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = - stateSetUnion(PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); - - /** - * The order here is very important to {@link #getDrawableState()} - */ - private static final int[][] VIEW_STATE_SETS = { - EMPTY_STATE_SET, // 0 0 0 0 0 - WINDOW_FOCUSED_STATE_SET, // 0 0 0 0 1 - SELECTED_STATE_SET, // 0 0 0 1 0 - SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 0 0 1 1 - FOCUSED_STATE_SET, // 0 0 1 0 0 - FOCUSED_WINDOW_FOCUSED_STATE_SET, // 0 0 1 0 1 - FOCUSED_SELECTED_STATE_SET, // 0 0 1 1 0 - FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 0 1 1 1 - ENABLED_STATE_SET, // 0 1 0 0 0 - ENABLED_WINDOW_FOCUSED_STATE_SET, // 0 1 0 0 1 - ENABLED_SELECTED_STATE_SET, // 0 1 0 1 0 - ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 1 0 1 1 - ENABLED_FOCUSED_STATE_SET, // 0 1 1 0 0 - ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, // 0 1 1 0 1 - ENABLED_FOCUSED_SELECTED_STATE_SET, // 0 1 1 1 0 - ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 1 1 1 1 - PRESSED_STATE_SET, // 1 0 0 0 0 - PRESSED_WINDOW_FOCUSED_STATE_SET, // 1 0 0 0 1 - PRESSED_SELECTED_STATE_SET, // 1 0 0 1 0 - PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 0 0 1 1 - PRESSED_FOCUSED_STATE_SET, // 1 0 1 0 0 - PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET, // 1 0 1 0 1 - PRESSED_FOCUSED_SELECTED_STATE_SET, // 1 0 1 1 0 - PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 0 1 1 1 - PRESSED_ENABLED_STATE_SET, // 1 1 0 0 0 - PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET, // 1 1 0 0 1 - PRESSED_ENABLED_SELECTED_STATE_SET, // 1 1 0 1 0 - PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 1 0 1 1 - PRESSED_ENABLED_FOCUSED_STATE_SET, // 1 1 1 0 0 - PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, // 1 1 1 0 1 - PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, // 1 1 1 1 0 - PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 1 1 1 1 - }; - - /** - * Used by views that contain lists of items. This state indicates that - * the view is showing the last item. - * @hide - */ - protected static final int[] LAST_STATE_SET = {R.attr.state_last}; - /** - * Used by views that contain lists of items. This state indicates that - * the view is showing the first item. - * @hide - */ - protected static final int[] FIRST_STATE_SET = {R.attr.state_first}; - /** - * Used by views that contain lists of items. This state indicates that - * the view is showing the middle item. - * @hide - */ - protected static final int[] MIDDLE_STATE_SET = {R.attr.state_middle}; - /** - * Used by views that contain lists of items. This state indicates that - * the view is showing only one item. - * @hide - */ - protected static final int[] SINGLE_STATE_SET = {R.attr.state_single}; - /** - * Used by views that contain lists of items. This state indicates that - * the view is pressed and showing the last item. - * @hide - */ - protected static final int[] PRESSED_LAST_STATE_SET = {R.attr.state_last, R.attr.state_pressed}; - /** - * Used by views that contain lists of items. This state indicates that - * the view is pressed and showing the first item. - * @hide - */ - protected static final int[] PRESSED_FIRST_STATE_SET = {R.attr.state_first, R.attr.state_pressed}; - /** - * Used by views that contain lists of items. This state indicates that - * the view is pressed and showing the middle item. - * @hide - */ - protected static final int[] PRESSED_MIDDLE_STATE_SET = {R.attr.state_middle, R.attr.state_pressed}; - /** - * Used by views that contain lists of items. This state indicates that - * the view is pressed and showing only one item. - * @hide - */ - protected static final int[] PRESSED_SINGLE_STATE_SET = {R.attr.state_single, R.attr.state_pressed}; - - /** - * Temporary Rect currently for use in setBackground(). This will probably - * be extended in the future to hold our own class with more than just - * a Rect. :) - */ - static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>(); - - /** - * The animation currently associated with this view. - * @hide - */ - protected Animation mCurrentAnimation = null; - - /** - * Width as measured during measure pass. - * {@hide} - */ - @ViewDebug.ExportedProperty - protected int mMeasuredWidth; - - /** - * Height as measured during measure pass. - * {@hide} - */ - @ViewDebug.ExportedProperty - protected int mMeasuredHeight; - - /** - * The view's identifier. - * {@hide} - * - * @see #setId(int) - * @see #getId() - */ - @ViewDebug.ExportedProperty(resolveId = true) - int mID = NO_ID; - - /** - * The view's tag. - * {@hide} - * - * @see #setTag(Object) - * @see #getTag() - */ - protected Object mTag; - - // for mPrivateFlags: - /** {@hide} */ - static final int WANTS_FOCUS = 0x00000001; - /** {@hide} */ - static final int FOCUSED = 0x00000002; - /** {@hide} */ - static final int SELECTED = 0x00000004; - /** {@hide} */ - static final int IS_ROOT_NAMESPACE = 0x00000008; - /** {@hide} */ - static final int HAS_BOUNDS = 0x00000010; - /** {@hide} */ - static final int DRAWN = 0x00000020; - /** - * When this flag is set, this view is running an animation on behalf of its - * children and should therefore not cancel invalidate requests, even if they - * lie outside of this view's bounds. - * - * {@hide} - */ - static final int DRAW_ANIMATION = 0x00000040; - /** {@hide} */ - static final int SKIP_DRAW = 0x00000080; - /** {@hide} */ - static final int ONLY_DRAWS_BACKGROUND = 0x00000100; - /** {@hide} */ - static final int REQUEST_TRANSPARENT_REGIONS = 0x00000200; - /** {@hide} */ - static final int DRAWABLE_STATE_DIRTY = 0x00000400; - /** {@hide} */ - static final int MEASURED_DIMENSION_SET = 0x00000800; - /** {@hide} */ - static final int FORCE_LAYOUT = 0x00001000; - - private static final int LAYOUT_REQUIRED = 0x00002000; - - private static final int PRESSED = 0x00004000; - - /** {@hide} */ - static final int DRAWING_CACHE_VALID = 0x00008000; - /** - * Flag used to indicate that this view should be drawn once more (and only once - * more) after its animation has completed. - * {@hide} - */ - static final int ANIMATION_STARTED = 0x00010000; - - private static final int SAVE_STATE_CALLED = 0x00020000; - - /** - * Indicates that the View returned true when onSetAlpha() was called and that - * the alpha must be restored. - * {@hide} - */ - static final int ALPHA_SET = 0x00040000; - - /** - * Set by {@link #setScrollContainer(boolean)}. - */ - static final int SCROLL_CONTAINER = 0x00080000; - - /** - * Set by {@link #setScrollContainer(boolean)}. - */ - static final int SCROLL_CONTAINER_ADDED = 0x00100000; - - /** - * The parent this view is attached to. - * {@hide} - * - * @see #getParent() - */ - protected ViewParent mParent; - - /** - * {@hide} - */ - AttachInfo mAttachInfo; - - /** - * {@hide} - */ - @ViewDebug.ExportedProperty - int mPrivateFlags; - - /** - * Count of how many windows this view has been attached to. - */ - int mWindowAttachCount; - - /** - * The layout parameters associated with this view and used by the parent - * {@link android.view.ViewGroup} to determine how this view should be - * laid out. - * {@hide} - */ - protected ViewGroup.LayoutParams mLayoutParams; - - /** - * The view flags hold various views states. - * {@hide} - */ - @ViewDebug.ExportedProperty - int mViewFlags; - - /** - * The distance in pixels from the left edge of this view's parent - * to the left edge of this view. - * {@hide} - */ - @ViewDebug.ExportedProperty - protected int mLeft; - /** - * The distance in pixels from the left edge of this view's parent - * to the right edge of this view. - * {@hide} - */ - @ViewDebug.ExportedProperty - protected int mRight; - /** - * The distance in pixels from the top edge of this view's parent - * to the top edge of this view. - * {@hide} - */ - @ViewDebug.ExportedProperty - protected int mTop; - /** - * The distance in pixels from the top edge of this view's parent - * to the bottom edge of this view. - * {@hide} - */ - @ViewDebug.ExportedProperty - protected int mBottom; - - /** - * The offset, in pixels, by which the content of this view is scrolled - * horizontally. - * {@hide} - */ - @ViewDebug.ExportedProperty - protected int mScrollX; - /** - * The offset, in pixels, by which the content of this view is scrolled - * vertically. - * {@hide} - */ - @ViewDebug.ExportedProperty - protected int mScrollY; - - /** - * The left padding in pixels, that is the distance in pixels between the - * left edge of this view and the left edge of its content. - * {@hide} - */ - @ViewDebug.ExportedProperty - protected int mPaddingLeft; - /** - * The right padding in pixels, that is the distance in pixels between the - * right edge of this view and the right edge of its content. - * {@hide} - */ - @ViewDebug.ExportedProperty - protected int mPaddingRight; - /** - * The top padding in pixels, that is the distance in pixels between the - * top edge of this view and the top edge of its content. - * {@hide} - */ - @ViewDebug.ExportedProperty - protected int mPaddingTop; - /** - * The bottom padding in pixels, that is the distance in pixels between the - * bottom edge of this view and the bottom edge of its content. - * {@hide} - */ - @ViewDebug.ExportedProperty - protected int mPaddingBottom; - - /** - * Cache the paddingRight set by the user to append to the scrollbar's size. - */ - @ViewDebug.ExportedProperty - int mUserPaddingRight; - - /** - * Cache the paddingBottom set by the user to append to the scrollbar's size. - */ - @ViewDebug.ExportedProperty - int mUserPaddingBottom; - - private int mOldWidthMeasureSpec = Integer.MIN_VALUE; - private int mOldHeightMeasureSpec = Integer.MIN_VALUE; - - private Resources mResources = null; - - private Drawable mBGDrawable; - - private int mBackgroundResource; - private boolean mBackgroundSizeChanged; - - /** - * Listener used to dispatch focus change events. - * This field should be made private, so it is hidden from the SDK. - * {@hide} - */ - protected OnFocusChangeListener mOnFocusChangeListener; - - /** - * Listener used to dispatch click events. - * This field should be made private, so it is hidden from the SDK. - * {@hide} - */ - protected OnClickListener mOnClickListener; - - /** - * Listener used to dispatch long click events. - * This field should be made private, so it is hidden from the SDK. - * {@hide} - */ - protected OnLongClickListener mOnLongClickListener; - - /** - * Listener used to build the context menu. - * This field should be made private, so it is hidden from the SDK. - * {@hide} - */ - protected OnCreateContextMenuListener mOnCreateContextMenuListener; - - private OnKeyListener mOnKeyListener; - - private OnTouchListener mOnTouchListener; - - /** - * The application environment this view lives in. - * This field should be made private, so it is hidden from the SDK. - * {@hide} - */ - protected Context mContext; - - private ScrollabilityCache mScrollCache; - - private int[] mDrawableState = null; - - private Bitmap mDrawingCache; - - /** - * When this view has focus and the next focus is {@link #FOCUS_LEFT}, - * the user may specify which view to go to next. - */ - private int mNextFocusLeftId = View.NO_ID; - - /** - * When this view has focus and the next focus is {@link #FOCUS_RIGHT}, - * the user may specify which view to go to next. - */ - private int mNextFocusRightId = View.NO_ID; - - /** - * When this view has focus and the next focus is {@link #FOCUS_UP}, - * the user may specify which view to go to next. - */ - private int mNextFocusUpId = View.NO_ID; - - /** - * When this view has focus and the next focus is {@link #FOCUS_DOWN}, - * the user may specify which view to go to next. - */ - private int mNextFocusDownId = View.NO_ID; - - private CheckForLongPress mPendingCheckForLongPress; - private UnsetPressedState mUnsetPressedState; - - /** - * Whether the long press's action has been invoked. The tap's action is invoked on the - * up event while a long press is invoked as soon as the long press duration is reached, so - * a long press could be performed before the tap is checked, in which case the tap's action - * should not be invoked. - */ - private boolean mHasPerformedLongPress; - - /** - * The minimum height of the view. We'll try our best to have the height - * of this view to at least this amount. - */ - @ViewDebug.ExportedProperty - private int mMinHeight; - - /** - * The minimum width of the view. We'll try our best to have the width - * of this view to at least this amount. - */ - @ViewDebug.ExportedProperty - private int mMinWidth; - - /** - * The delegate to handle touch events that are physically in this view - * but should be handled by another view. - */ - private TouchDelegate mTouchDelegate = null; - - /** - * Solid color to use as a background when creating the drawing cache. Enables - * the cache to use 16 bit bitmaps instead of 32 bit. - */ - private int mDrawingCacheBackgroundColor = 0; - - /** - * Special tree observer used when mAttachInfo is null. - */ - private ViewTreeObserver mFloatingTreeObserver; - - // Used for debug only - static long sInstanceCount = 0; - - /** - * Simple constructor to use when creating a view from code. - * - * @param context The Context the view is running in, through which it can - * access the current theme, resources, etc. - */ - public View(Context context) { - mContext = context; - mResources = context != null ? context.getResources() : null; - mViewFlags = SOUND_EFFECTS_ENABLED|HAPTIC_FEEDBACK_ENABLED; - ++sInstanceCount; - } - - /** - * Constructor that is called when inflating a view from XML. This is called - * when a view is being constructed from an XML file, supplying attributes - * that were specified in the XML file. This version uses a default style of - * 0, so the only attribute values applied are those in the Context's Theme - * and the given AttributeSet. - * - * <p> - * The method onFinishInflate() will be called after all children have been - * added. - * - * @param context The Context the view is running in, through which it can - * access the current theme, resources, etc. - * @param attrs The attributes of the XML tag that is inflating the view. - * @see #View(Context, AttributeSet, int) - */ - public View(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - /** - * Perform inflation from XML and apply a class-specific base style. This - * constructor of View allows subclasses to use their own base style when - * they are inflating. For example, a Button class's constructor would call - * this version of the super class constructor and supply - * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows - * the theme's button style to modify all of the base view attributes (in - * particular its background) as well as the Button class's attributes. - * - * @param context The Context the view is running in, through which it can - * access the current theme, resources, etc. - * @param attrs The attributes of the XML tag that is inflating the view. - * @param defStyle The default style to apply to this view. If 0, no style - * will be applied (beyond what is included in the theme). This may - * either be an attribute resource, whose value will be retrieved - * from the current theme, or an explicit style resource. - * @see #View(Context, AttributeSet) - */ - public View(Context context, AttributeSet attrs, int defStyle) { - this(context); - - TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View, - defStyle, 0); - - Drawable background = null; - - int leftPadding = -1; - int topPadding = -1; - int rightPadding = -1; - int bottomPadding = -1; - - int padding = -1; - - int viewFlagValues = 0; - int viewFlagMasks = 0; - - boolean setScrollContainer = false; - - int x = 0; - int y = 0; - - int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; - - final int N = a.getIndexCount(); - for (int i = 0; i < N; i++) { - int attr = a.getIndex(i); - switch (attr) { - case com.android.internal.R.styleable.View_background: - background = a.getDrawable(attr); - break; - case com.android.internal.R.styleable.View_padding: - padding = a.getDimensionPixelSize(attr, -1); - break; - case com.android.internal.R.styleable.View_paddingLeft: - leftPadding = a.getDimensionPixelSize(attr, -1); - break; - case com.android.internal.R.styleable.View_paddingTop: - topPadding = a.getDimensionPixelSize(attr, -1); - break; - case com.android.internal.R.styleable.View_paddingRight: - rightPadding = a.getDimensionPixelSize(attr, -1); - break; - case com.android.internal.R.styleable.View_paddingBottom: - bottomPadding = a.getDimensionPixelSize(attr, -1); - break; - case com.android.internal.R.styleable.View_scrollX: - x = a.getDimensionPixelOffset(attr, 0); - break; - case com.android.internal.R.styleable.View_scrollY: - y = a.getDimensionPixelOffset(attr, 0); - break; - case com.android.internal.R.styleable.View_id: - mID = a.getResourceId(attr, NO_ID); - break; - case com.android.internal.R.styleable.View_tag: - mTag = a.getText(attr); - break; - case com.android.internal.R.styleable.View_fitsSystemWindows: - if (a.getBoolean(attr, false)) { - viewFlagValues |= FITS_SYSTEM_WINDOWS; - viewFlagMasks |= FITS_SYSTEM_WINDOWS; - } - break; - case com.android.internal.R.styleable.View_focusable: - if (a.getBoolean(attr, false)) { - viewFlagValues |= FOCUSABLE; - viewFlagMasks |= FOCUSABLE_MASK; - } - break; - case com.android.internal.R.styleable.View_focusableInTouchMode: - if (a.getBoolean(attr, false)) { - viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE; - viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK; - } - break; - case com.android.internal.R.styleable.View_clickable: - if (a.getBoolean(attr, false)) { - viewFlagValues |= CLICKABLE; - viewFlagMasks |= CLICKABLE; - } - break; - case com.android.internal.R.styleable.View_longClickable: - if (a.getBoolean(attr, false)) { - viewFlagValues |= LONG_CLICKABLE; - viewFlagMasks |= LONG_CLICKABLE; - } - break; - case com.android.internal.R.styleable.View_saveEnabled: - if (!a.getBoolean(attr, true)) { - viewFlagValues |= SAVE_DISABLED; - viewFlagMasks |= SAVE_DISABLED_MASK; - } - break; - case com.android.internal.R.styleable.View_duplicateParentState: - if (a.getBoolean(attr, false)) { - viewFlagValues |= DUPLICATE_PARENT_STATE; - viewFlagMasks |= DUPLICATE_PARENT_STATE; - } - break; - case com.android.internal.R.styleable.View_visibility: - final int visibility = a.getInt(attr, 0); - if (visibility != 0) { - viewFlagValues |= VISIBILITY_FLAGS[visibility]; - viewFlagMasks |= VISIBILITY_MASK; - } - break; - case com.android.internal.R.styleable.View_drawingCacheQuality: - final int cacheQuality = a.getInt(attr, 0); - if (cacheQuality != 0) { - viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality]; - viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK; - } - break; - case com.android.internal.R.styleable.View_soundEffectsEnabled: - if (!a.getBoolean(attr, true)) { - viewFlagValues &= ~SOUND_EFFECTS_ENABLED; - viewFlagMasks |= SOUND_EFFECTS_ENABLED; - } - case com.android.internal.R.styleable.View_hapticFeedbackEnabled: - if (!a.getBoolean(attr, true)) { - viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED; - viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED; - } - case R.styleable.View_scrollbars: - final int scrollbars = a.getInt(attr, SCROLLBARS_NONE); - if (scrollbars != SCROLLBARS_NONE) { - viewFlagValues |= scrollbars; - viewFlagMasks |= SCROLLBARS_MASK; - initializeScrollbars(a); - } - break; - case R.styleable.View_fadingEdge: - final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE); - if (fadingEdge != FADING_EDGE_NONE) { - viewFlagValues |= fadingEdge; - viewFlagMasks |= FADING_EDGE_MASK; - initializeFadingEdge(a); - } - break; - case R.styleable.View_scrollbarStyle: - scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY); - if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { - viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK; - viewFlagMasks |= SCROLLBARS_STYLE_MASK; - } - break; - case R.styleable.View_isScrollContainer: - setScrollContainer = true; - if (a.getBoolean(attr, false)) { - setScrollContainer(true); - } - break; - case com.android.internal.R.styleable.View_keepScreenOn: - if (a.getBoolean(attr, false)) { - viewFlagValues |= KEEP_SCREEN_ON; - viewFlagMasks |= KEEP_SCREEN_ON; - } - break; - case R.styleable.View_nextFocusLeft: - mNextFocusLeftId = a.getResourceId(attr, View.NO_ID); - break; - case R.styleable.View_nextFocusRight: - mNextFocusRightId = a.getResourceId(attr, View.NO_ID); - break; - case R.styleable.View_nextFocusUp: - mNextFocusUpId = a.getResourceId(attr, View.NO_ID); - break; - case R.styleable.View_nextFocusDown: - mNextFocusDownId = a.getResourceId(attr, View.NO_ID); - break; - case R.styleable.View_minWidth: - mMinWidth = a.getDimensionPixelSize(attr, 0); - break; - case R.styleable.View_minHeight: - mMinHeight = a.getDimensionPixelSize(attr, 0); - break; - } - } - - if (background != null) { - setBackgroundDrawable(background); - } - - if (padding >= 0) { - leftPadding = padding; - topPadding = padding; - rightPadding = padding; - bottomPadding = padding; - } - - // If the user specified the padding (either with android:padding or - // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise - // use the default padding or the padding from the background drawable - // (stored at this point in mPadding*) - setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft, - topPadding >= 0 ? topPadding : mPaddingTop, - rightPadding >= 0 ? rightPadding : mPaddingRight, - bottomPadding >= 0 ? bottomPadding : mPaddingBottom); - - if (viewFlagMasks != 0) { - setFlags(viewFlagValues, viewFlagMasks); - } - - // Needs to be called after mViewFlags is set - if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { - recomputePadding(); - } - - if (x != 0 || y != 0) { - scrollTo(x, y); - } - - if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) { - setScrollContainer(true); - } - - a.recycle(); - } - - /** - * Non-public constructor for use in testing - */ - View() { - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - --sInstanceCount; - } - - /** - * <p> - * Initializes the fading edges from a given set of styled attributes. This - * method should be called by subclasses that need fading edges and when an - * instance of these subclasses is created programmatically rather than - * being inflated from XML. This method is automatically called when the XML - * is inflated. - * </p> - * - * @param a the styled attributes set to initialize the fading edges from - */ - protected void initializeFadingEdge(TypedArray a) { - initScrollCache(); - - mScrollCache.fadingEdgeLength = a.getDimensionPixelSize( - R.styleable.View_fadingEdgeLength, - ViewConfiguration.get(mContext).getScaledFadingEdgeLength()); - } - - /** - * Returns the size of the vertical faded edges used to indicate that more - * content in this view is visible. - * - * @return The size in pixels of the vertical faded edge or 0 if vertical - * faded edges are not enabled for this view. - * @attr ref android.R.styleable#View_fadingEdgeLength - */ - public int getVerticalFadingEdgeLength() { - if (isVerticalFadingEdgeEnabled()) { - ScrollabilityCache cache = mScrollCache; - if (cache != null) { - return cache.fadingEdgeLength; - } - } - return 0; - } - - /** - * Set the size of the faded edge used to indicate that more content in this - * view is available. Will not change whether the fading edge is enabled; use - * {@link #setVerticalFadingEdgeEnabled} or {@link #setHorizontalFadingEdgeEnabled} - * to enable the fading edge for the vertical or horizontal fading edges. - * - * @param length The size in pixels of the faded edge used to indicate that more - * content in this view is visible. - */ - public void setFadingEdgeLength(int length) { - initScrollCache(); - mScrollCache.fadingEdgeLength = length; - } - - /** - * Returns the size of the horizontal faded edges used to indicate that more - * content in this view is visible. - * - * @return The size in pixels of the horizontal faded edge or 0 if horizontal - * faded edges are not enabled for this view. - * @attr ref android.R.styleable#View_fadingEdgeLength - */ - public int getHorizontalFadingEdgeLength() { - if (isHorizontalFadingEdgeEnabled()) { - ScrollabilityCache cache = mScrollCache; - if (cache != null) { - return cache.fadingEdgeLength; - } - } - return 0; - } - - /** - * Returns the width of the vertical scrollbar. - * - * @return The width in pixels of the vertical scrollbar or 0 if there - * is no vertical scrollbar. - */ - public int getVerticalScrollbarWidth() { - ScrollabilityCache cache = mScrollCache; - if (cache != null) { - ScrollBarDrawable scrollBar = cache.scrollBar; - if (scrollBar != null) { - int size = scrollBar.getSize(true); - if (size <= 0) { - size = cache.scrollBarSize; - } - return size; - } - return 0; - } - return 0; - } - - /** - * Returns the height of the horizontal scrollbar. - * - * @return The height in pixels of the horizontal scrollbar or 0 if - * there is no horizontal scrollbar. - */ - protected int getHorizontalScrollbarHeight() { - ScrollabilityCache cache = mScrollCache; - if (cache != null) { - ScrollBarDrawable scrollBar = cache.scrollBar; - if (scrollBar != null) { - int size = scrollBar.getSize(false); - if (size <= 0) { - size = cache.scrollBarSize; - } - return size; - } - return 0; - } - return 0; - } - - /** - * <p> - * Initializes the scrollbars from a given set of styled attributes. This - * method should be called by subclasses that need scrollbars and when an - * instance of these subclasses is created programmatically rather than - * being inflated from XML. This method is automatically called when the XML - * is inflated. - * </p> - * - * @param a the styled attributes set to initialize the scrollbars from - */ - protected void initializeScrollbars(TypedArray a) { - initScrollCache(); - - if (mScrollCache.scrollBar == null) { - mScrollCache.scrollBar = new ScrollBarDrawable(); - } - - final ScrollabilityCache scrollabilityCache = mScrollCache; - - scrollabilityCache.scrollBarSize = a.getDimensionPixelSize( - com.android.internal.R.styleable.View_scrollbarSize, - ViewConfiguration.get(mContext).getScaledScrollBarSize()); - - Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal); - scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track); - - Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal); - if (thumb != null) { - scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb); - } - - boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack, - false); - if (alwaysDraw) { - scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true); - } - - track = a.getDrawable(R.styleable.View_scrollbarTrackVertical); - scrollabilityCache.scrollBar.setVerticalTrackDrawable(track); - - thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical); - if (thumb != null) { - scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb); - } - - alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack, - false); - if (alwaysDraw) { - scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true); - } - - // Re-apply user/background padding so that scrollbar(s) get added - recomputePadding(); - } - - /** - * <p> - * Initalizes the scrollability cache if necessary. - * </p> - */ - private void initScrollCache() { - if (mScrollCache == null) { - mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext)); - } - } - - /** - * Register a callback to be invoked when focus of this view changed. - * - * @param l The callback that will run. - */ - public void setOnFocusChangeListener(OnFocusChangeListener l) { - mOnFocusChangeListener = l; - } - - /** - * Returns the focus-change callback registered for this view. - * - * @return The callback, or null if one is not registered. - */ - public OnFocusChangeListener getOnFocusChangeListener() { - return mOnFocusChangeListener; - } - - /** - * Register a callback to be invoked when this view is clicked. If this view is not - * clickable, it becomes clickable. - * - * @param l The callback that will run - * - * @see #setClickable(boolean) - */ - public void setOnClickListener(OnClickListener l) { - if (!isClickable()) { - setClickable(true); - } - mOnClickListener = l; - } - - /** - * Register a callback to be invoked when this view is clicked and held. If this view is not - * long clickable, it becomes long clickable. - * - * @param l The callback that will run - * - * @see #setLongClickable(boolean) - */ - public void setOnLongClickListener(OnLongClickListener l) { - if (!isLongClickable()) { - setLongClickable(true); - } - mOnLongClickListener = l; - } - - /** - * Register a callback to be invoked when the context menu for this view is - * being built. If this view is not long clickable, it becomes long clickable. - * - * @param l The callback that will run - * - */ - public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) { - if (!isLongClickable()) { - setLongClickable(true); - } - mOnCreateContextMenuListener = l; - } - - /** - * Call this view's OnClickListener, if it is defined. - * - * @return True there was an assigned OnClickListener that was called, false - * otherwise is returned. - */ - public boolean performClick() { - if (mOnClickListener != null) { - playSoundEffect(SoundEffectConstants.CLICK); - mOnClickListener.onClick(this); - return true; - } - - return false; - } - - /** - * Call this view's OnLongClickListener, if it is defined. Invokes the context menu - * if the OnLongClickListener did not consume the event. - * - * @return True there was an assigned OnLongClickListener that was called, false - * otherwise is returned. - */ - public boolean performLongClick() { - boolean handled = false; - if (mOnLongClickListener != null) { - handled = mOnLongClickListener.onLongClick(View.this); - } - if (!handled) { - handled = showContextMenu(); - } - if (handled) { - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - } - return handled; - } - - /** - * Bring up the context menu for this view. - * - * @return Whether a context menu was displayed. - */ - public boolean showContextMenu() { - return getParent().showContextMenuForChild(this); - } - - /** - * Register a callback to be invoked when a key is pressed in this view. - * @param l the key listener to attach to this view - */ - public void setOnKeyListener(OnKeyListener l) { - mOnKeyListener = l; - } - - /** - * Register a callback to be invoked when a touch event is sent to this view. - * @param l the touch listener to attach to this view - */ - public void setOnTouchListener(OnTouchListener l) { - mOnTouchListener = l; - } - - /** - * Give this view focus. This will cause {@link #onFocusChanged} to be called. - * - * Note: this does not check whether this {@link View} should get focus, it just - * gives it focus no matter what. It should only be called internally by framework - * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}. - * - * @param direction values are View.FOCUS_UP, View.FOCUS_DOWN, - * View.FOCUS_LEFT or View.FOCUS_RIGHT. This is the direction which - * focus moved when requestFocus() is called. It may not always - * apply, in which case use the default View.FOCUS_DOWN. - * @param previouslyFocusedRect The rectangle of the view that had focus - * prior in this View's coordinate system. - */ - void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) { - if (DBG) { - System.out.println(this + " requestFocus()"); - } - - if ((mPrivateFlags & FOCUSED) == 0) { - mPrivateFlags |= FOCUSED; - - if (mParent != null) { - mParent.requestChildFocus(this, this); - } - - onFocusChanged(true, direction, previouslyFocusedRect); - refreshDrawableState(); - } - } - - /** - * Request that a rectangle of this view be visible on the screen, - * scrolling if necessary just enough. - * - * <p>A View should call this if it maintains some notion of which part - * of its content is interesting. For example, a text editing view - * should call this when its cursor moves. - * - * @param rectangle The rectangle. - * @return Whether any parent scrolled. - */ - public boolean requestRectangleOnScreen(Rect rectangle) { - return requestRectangleOnScreen(rectangle, false); - } - - /** - * Request that a rectangle of this view be visible on the screen, - * scrolling if necessary just enough. - * - * <p>A View should call this if it maintains some notion of which part - * of its content is interesting. For example, a text editing view - * should call this when its cursor moves. - * - * <p>When <code>immediate</code> is set to true, scrolling will not be - * animated. - * - * @param rectangle The rectangle. - * @param immediate True to forbid animated scrolling, false otherwise - * @return Whether any parent scrolled. - */ - public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) { - View child = this; - ViewParent parent = mParent; - boolean scrolled = false; - while (parent != null) { - scrolled |= parent.requestChildRectangleOnScreen(child, - rectangle, immediate); - - // offset rect so next call has the rectangle in the - // coordinate system of its direct child. - rectangle.offset(child.getLeft(), child.getTop()); - rectangle.offset(-child.getScrollX(), -child.getScrollY()); - - if (!(parent instanceof View)) { - break; - } - - child = (View) parent; - parent = child.getParent(); - } - return scrolled; - } - - /** - * Called when this view wants to give up focus. This will cause - * {@link #onFocusChanged} to be called. - */ - public void clearFocus() { - if (DBG) { - System.out.println(this + " clearFocus()"); - } - - if ((mPrivateFlags & FOCUSED) != 0) { - mPrivateFlags &= ~FOCUSED; - - if (mParent != null) { - mParent.clearChildFocus(this); - } - - onFocusChanged(false, 0, null); - refreshDrawableState(); - } - } - - /** - * Called to clear the focus of a view that is about to be removed. - * Doesn't call clearChildFocus, which prevents this view from taking - * focus again before it has been removed from the parent - */ - void clearFocusForRemoval() { - if ((mPrivateFlags & FOCUSED) != 0) { - mPrivateFlags &= ~FOCUSED; - - onFocusChanged(false, 0, null); - refreshDrawableState(); - } - } - - /** - * Called internally by the view system when a new view is getting focus. - * This is what clears the old focus. - */ - void unFocus() { - if (DBG) { - System.out.println(this + " unFocus()"); - } - - if ((mPrivateFlags & FOCUSED) != 0) { - mPrivateFlags &= ~FOCUSED; - - onFocusChanged(false, 0, null); - refreshDrawableState(); - } - } - - /** - * Returns true if this view has focus iteself, or is the ancestor of the - * view that has focus. - * - * @return True if this view has or contains focus, false otherwise. - */ - @ViewDebug.ExportedProperty - public boolean hasFocus() { - return (mPrivateFlags & FOCUSED) != 0; - } - - /** - * Returns true if this view is focusable or if it contains a reachable View - * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()" - * is a View whose parents do not block descendants focus. - * - * Only {@link #VISIBLE} views are considered focusable. - * - * @return True if the view is focusable or if the view contains a focusable - * View, false otherwise. - * - * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS - */ - public boolean hasFocusable() { - return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable(); - } - - /** - * Called by the view system when the focus state of this view changes. - * When the focus change event is caused by directional navigation, direction - * and previouslyFocusedRect provide insight into where the focus is coming from. - * When overriding, be sure to call up through to the super class so that - * the standard focus handling will occur. - * - * @param gainFocus True if the View has focus; false otherwise. - * @param direction The direction focus has moved when requestFocus() - * is called to give this view focus. Values are - * View.FOCUS_UP, View.FOCUS_DOWN, View.FOCUS_LEFT or - * View.FOCUS_RIGHT. It may not always apply, in which - * case use the default. - * @param previouslyFocusedRect The rectangle, in this view's coordinate - * system, of the previously focused view. If applicable, this will be - * passed in as finer grained information about where the focus is coming - * from (in addition to direction). Will be <code>null</code> otherwise. - */ - protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { - InputMethodManager imm = InputMethodManager.peekInstance(); - if (!gainFocus) { - if (isPressed()) { - setPressed(false); - } - if (imm != null && mAttachInfo != null - && mAttachInfo.mHasWindowFocus) { - imm.focusOut(this); - } - } else if (imm != null && mAttachInfo != null - && mAttachInfo.mHasWindowFocus) { - imm.focusIn(this); - } - - invalidate(); - if (mOnFocusChangeListener != null) { - mOnFocusChangeListener.onFocusChange(this, gainFocus); - } - } - - /** - * Returns true if this view has focus - * - * @return True if this view has focus, false otherwise. - */ - @ViewDebug.ExportedProperty - public boolean isFocused() { - return (mPrivateFlags & FOCUSED) != 0; - } - - /** - * Find the view in the hierarchy rooted at this view that currently has - * focus. - * - * @return The view that currently has focus, or null if no focused view can - * be found. - */ - public View findFocus() { - return (mPrivateFlags & FOCUSED) != 0 ? this : null; - } - - /** - * Change whether this view is one of the set of scrollable containers in - * its window. This will be used to determine whether the window can - * resize or must pan when a soft input area is open -- scrollable - * containers allow the window to use resize mode since the container - * will appropriately shrink. - */ - public void setScrollContainer(boolean isScrollContainer) { - if (isScrollContainer) { - if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) { - mAttachInfo.mScrollContainers.add(this); - mPrivateFlags |= SCROLL_CONTAINER_ADDED; - } - mPrivateFlags |= SCROLL_CONTAINER; - } else { - if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) { - mAttachInfo.mScrollContainers.remove(this); - } - mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED); - } - } - - /** - * Returns the quality of the drawing cache. - * - * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO}, - * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} - * - * @see #setDrawingCacheQuality(int) - * @see #setDrawingCacheEnabled(boolean) - * @see #isDrawingCacheEnabled() - * - * @attr ref android.R.styleable#View_drawingCacheQuality - */ - public int getDrawingCacheQuality() { - return mViewFlags & DRAWING_CACHE_QUALITY_MASK; - } - - /** - * Set the drawing cache quality of this view. This value is used only when the - * drawing cache is enabled - * - * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO}, - * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} - * - * @see #getDrawingCacheQuality() - * @see #setDrawingCacheEnabled(boolean) - * @see #isDrawingCacheEnabled() - * - * @attr ref android.R.styleable#View_drawingCacheQuality - */ - public void setDrawingCacheQuality(int quality) { - setFlags(quality, DRAWING_CACHE_QUALITY_MASK); - } - - /** - * Returns whether the screen should remain on, corresponding to the current - * value of {@link #KEEP_SCREEN_ON}. - * - * @return Returns true if {@link #KEEP_SCREEN_ON} is set. - * - * @see #setKeepScreenOn(boolean) - * - * @attr ref android.R.styleable#View_keepScreenOn - */ - public boolean getKeepScreenOn() { - return (mViewFlags & KEEP_SCREEN_ON) != 0; - } - - /** - * Controls whether the screen should remain on, modifying the - * value of {@link #KEEP_SCREEN_ON}. - * - * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}. - * - * @see #getKeepScreenOn() - * - * @attr ref android.R.styleable#View_keepScreenOn - */ - public void setKeepScreenOn(boolean keepScreenOn) { - setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON); - } - - /** - * @return The user specified next focus ID. - * - * @attr ref android.R.styleable#View_nextFocusLeft - */ - public int getNextFocusLeftId() { - return mNextFocusLeftId; - } - - /** - * Set the id of the view to use for the next focus - * - * @param nextFocusLeftId - * - * @attr ref android.R.styleable#View_nextFocusLeft - */ - public void setNextFocusLeftId(int nextFocusLeftId) { - mNextFocusLeftId = nextFocusLeftId; - } - - /** - * @return The user specified next focus ID. - * - * @attr ref android.R.styleable#View_nextFocusRight - */ - public int getNextFocusRightId() { - return mNextFocusRightId; - } - - /** - * Set the id of the view to use for the next focus - * - * @param nextFocusRightId - * - * @attr ref android.R.styleable#View_nextFocusRight - */ - public void setNextFocusRightId(int nextFocusRightId) { - mNextFocusRightId = nextFocusRightId; - } - - /** - * @return The user specified next focus ID. - * - * @attr ref android.R.styleable#View_nextFocusUp - */ - public int getNextFocusUpId() { - return mNextFocusUpId; - } - - /** - * Set the id of the view to use for the next focus - * - * @param nextFocusUpId - * - * @attr ref android.R.styleable#View_nextFocusUp - */ - public void setNextFocusUpId(int nextFocusUpId) { - mNextFocusUpId = nextFocusUpId; - } - - /** - * @return The user specified next focus ID. - * - * @attr ref android.R.styleable#View_nextFocusDown - */ - public int getNextFocusDownId() { - return mNextFocusDownId; - } - - /** - * Set the id of the view to use for the next focus - * - * @param nextFocusDownId - * - * @attr ref android.R.styleable#View_nextFocusDown - */ - public void setNextFocusDownId(int nextFocusDownId) { - mNextFocusDownId = nextFocusDownId; - } - - /** - * Returns the visibility of this view and all of its ancestors - * - * @return True if this view and all of its ancestors are {@link #VISIBLE} - */ - public boolean isShown() { - View current = this; - //noinspection ConstantConditions - do { - if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { - return false; - } - ViewParent parent = current.mParent; - if (parent == null) { - return false; // We are not attached to the view root - } - if (!(parent instanceof View)) { - return true; - } - current = (View) parent; - } while (current != null); - - return false; - } - - /** - * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag - * is set - * - * @param insets Insets for system windows - * - * @return True if this view applied the insets, false otherwise - */ - protected boolean fitSystemWindows(Rect insets) { - if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) { - mPaddingLeft = insets.left; - mPaddingTop = insets.top; - mPaddingRight = insets.right; - mPaddingBottom = insets.bottom; - requestLayout(); - return true; - } - return false; - } - - /** - * Returns the visibility status for this view. - * - * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. - * @attr ref android.R.styleable#View_visibility - */ - @ViewDebug.ExportedProperty(mapping = { - @ViewDebug.IntToString(from = 0, to = "VISIBLE"), - @ViewDebug.IntToString(from = 4, to = "INVISIBLE"), - @ViewDebug.IntToString(from = 8, to = "GONE") - }) - public int getVisibility() { - return mViewFlags & VISIBILITY_MASK; - } - - /** - * Set the enabled state of this view. - * - * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. - * @attr ref android.R.styleable#View_visibility - */ - @RemotableViewMethod - public void setVisibility(int visibility) { - setFlags(visibility, VISIBILITY_MASK); - if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false); - } - - /** - * Returns the enabled status for this view. The interpretation of the - * enabled state varies by subclass. - * - * @return True if this view is enabled, false otherwise. - */ - @ViewDebug.ExportedProperty - public boolean isEnabled() { - return (mViewFlags & ENABLED_MASK) == ENABLED; - } - - /** - * Set the enabled state of this view. The interpretation of the enabled - * state varies by subclass. - * - * @param enabled True if this view is enabled, false otherwise. - */ - public void setEnabled(boolean enabled) { - setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK); - - /* - * The View most likely has to change its appearance, so refresh - * the drawable state. - */ - refreshDrawableState(); - - // Invalidate too, since the default behavior for views is to be - // be drawn at 50% alpha rather than to change the drawable. - invalidate(); - } - - /** - * Set whether this view can receive the focus. - * - * Setting this to false will also ensure that this view is not focusable - * in touch mode. - * - * @param focusable If true, this view can receive the focus. - * - * @see #setFocusableInTouchMode(boolean) - * @attr ref android.R.styleable#View_focusable - */ - public void setFocusable(boolean focusable) { - if (!focusable) { - setFlags(0, FOCUSABLE_IN_TOUCH_MODE); - } - setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK); - } - - /** - * Set whether this view can receive focus while in touch mode. - * - * Setting this to true will also ensure that this view is focusable. - * - * @param focusableInTouchMode If true, this view can receive the focus while - * in touch mode. - * - * @see #setFocusable(boolean) - * @attr ref android.R.styleable#View_focusableInTouchMode - */ - public void setFocusableInTouchMode(boolean focusableInTouchMode) { - // Focusable in touch mode should always be set before the focusable flag - // otherwise, setting the focusable flag will trigger a focusableViewAvailable() - // which, in touch mode, will not successfully request focus on this view - // because the focusable in touch mode flag is not set - setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE); - if (focusableInTouchMode) { - setFlags(FOCUSABLE, FOCUSABLE_MASK); - } - } - - /** - * Set whether this view should have sound effects enabled for events such as - * clicking and touching. - * - * <p>You may wish to disable sound effects for a view if you already play sounds, - * for instance, a dial key that plays dtmf tones. - * - * @param soundEffectsEnabled whether sound effects are enabled for this view. - * @see #isSoundEffectsEnabled() - * @see #playSoundEffect(int) - * @attr ref android.R.styleable#View_soundEffectsEnabled - */ - public void setSoundEffectsEnabled(boolean soundEffectsEnabled) { - setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED); - } - - /** - * @return whether this view should have sound effects enabled for events such as - * clicking and touching. - * - * @see #setSoundEffectsEnabled(boolean) - * @see #playSoundEffect(int) - * @attr ref android.R.styleable#View_soundEffectsEnabled - */ - @ViewDebug.ExportedProperty - public boolean isSoundEffectsEnabled() { - return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED); - } - - /** - * Set whether this view should have haptic feedback for events such as - * long presses. - * - * <p>You may wish to disable haptic feedback if your view already controls - * its own haptic feedback. - * - * @param hapticFeedbackEnabled whether haptic feedback enabled for this view. - * @see #isHapticFeedbackEnabled() - * @see #performHapticFeedback(int) - * @attr ref android.R.styleable#View_hapticFeedbackEnabled - */ - public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) { - setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED); - } - - /** - * @return whether this view should have haptic feedback enabled for events - * long presses. - * - * @see #setHapticFeedbackEnabled(boolean) - * @see #performHapticFeedback(int) - * @attr ref android.R.styleable#View_hapticFeedbackEnabled - */ - @ViewDebug.ExportedProperty - public boolean isHapticFeedbackEnabled() { - return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED); - } - - /** - * If this view doesn't do any drawing on its own, set this flag to - * allow further optimizations. By default, this flag is not set on - * View, but could be set on some View subclasses such as ViewGroup. - * - * Typically, if you override {@link #onDraw} you should clear this flag. - * - * @param willNotDraw whether or not this View draw on its own - */ - public void setWillNotDraw(boolean willNotDraw) { - setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK); - } - - /** - * Returns whether or not this View draws on its own. - * - * @return true if this view has nothing to draw, false otherwise - */ - @ViewDebug.ExportedProperty - public boolean willNotDraw() { - return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW; - } - - /** - * When a View's drawing cache is enabled, drawing is redirected to an - * offscreen bitmap. Some views, like an ImageView, must be able to - * bypass this mechanism if they already draw a single bitmap, to avoid - * unnecessary usage of the memory. - * - * @param willNotCacheDrawing true if this view does not cache its - * drawing, false otherwise - */ - public void setWillNotCacheDrawing(boolean willNotCacheDrawing) { - setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING); - } - - /** - * Returns whether or not this View can cache its drawing or not. - * - * @return true if this view does not cache its drawing, false otherwise - */ - @ViewDebug.ExportedProperty - public boolean willNotCacheDrawing() { - return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING; - } - - /** - * Indicates whether this view reacts to click events or not. - * - * @return true if the view is clickable, false otherwise - * - * @see #setClickable(boolean) - * @attr ref android.R.styleable#View_clickable - */ - @ViewDebug.ExportedProperty - public boolean isClickable() { - return (mViewFlags & CLICKABLE) == CLICKABLE; - } - - /** - * Enables or disables click events for this view. When a view - * is clickable it will change its state to "pressed" on every click. - * Subclasses should set the view clickable to visually react to - * user's clicks. - * - * @param clickable true to make the view clickable, false otherwise - * - * @see #isClickable() - * @attr ref android.R.styleable#View_clickable - */ - public void setClickable(boolean clickable) { - setFlags(clickable ? CLICKABLE : 0, CLICKABLE); - } - - /** - * Indicates whether this view reacts to long click events or not. - * - * @return true if the view is long clickable, false otherwise - * - * @see #setLongClickable(boolean) - * @attr ref android.R.styleable#View_longClickable - */ - public boolean isLongClickable() { - return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; - } - - /** - * Enables or disables long click events for this view. When a view is long - * clickable it reacts to the user holding down the button for a longer - * duration than a tap. This event can either launch the listener or a - * context menu. - * - * @param longClickable true to make the view long clickable, false otherwise - * @see #isLongClickable() - * @attr ref android.R.styleable#View_longClickable - */ - public void setLongClickable(boolean longClickable) { - setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE); - } - - /** - * Sets the pressed that for this view. - * - * @see #isClickable() - * @see #setClickable(boolean) - * - * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts - * the View's internal state from a previously set "pressed" state. - */ - public void setPressed(boolean pressed) { - if (pressed) { - mPrivateFlags |= PRESSED; - } else { - mPrivateFlags &= ~PRESSED; - } - refreshDrawableState(); - dispatchSetPressed(pressed); - } - - /** - * Dispatch setPressed to all of this View's children. - * - * @see #setPressed(boolean) - * - * @param pressed The new pressed state - */ - protected void dispatchSetPressed(boolean pressed) { - } - - /** - * Indicates whether the view is currently in pressed state. Unless - * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter - * the pressed state. - * - * @see #setPressed - * @see #isClickable() - * @see #setClickable(boolean) - * - * @return true if the view is currently pressed, false otherwise - */ - public boolean isPressed() { - return (mPrivateFlags & PRESSED) == PRESSED; - } - - /** - * Indicates whether this view will save its state (that is, - * whether its {@link #onSaveInstanceState} method will be called). - * - * @return Returns true if the view state saving is enabled, else false. - * - * @see #setSaveEnabled(boolean) - * @attr ref android.R.styleable#View_saveEnabled - */ - public boolean isSaveEnabled() { - return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED; - } - - /** - * Controls whether the saving of this view's state is - * enabled (that is, whether its {@link #onSaveInstanceState} method - * will be called). Note that even if freezing is enabled, the - * view still must have an id assigned to it (via {@link #setId setId()}) - * for its state to be saved. This flag can only disable the - * saving of this view; any child views may still have their state saved. - * - * @param enabled Set to false to <em>disable</em> state saving, or true - * (the default) to allow it. - * - * @see #isSaveEnabled() - * @see #setId(int) - * @see #onSaveInstanceState() - * @attr ref android.R.styleable#View_saveEnabled - */ - public void setSaveEnabled(boolean enabled) { - setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK); - } - - - /** - * Returns whether this View is able to take focus. - * - * @return True if this view can take focus, or false otherwise. - * @attr ref android.R.styleable#View_focusable - */ - @ViewDebug.ExportedProperty - public final boolean isFocusable() { - return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK); - } - - /** - * When a view is focusable, it may not want to take focus when in touch mode. - * For example, a button would like focus when the user is navigating via a D-pad - * so that the user can click on it, but once the user starts touching the screen, - * the button shouldn't take focus - * @return Whether the view is focusable in touch mode. - * @attr ref android.R.styleable#View_focusableInTouchMode - */ - @ViewDebug.ExportedProperty - public final boolean isFocusableInTouchMode() { - return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE); - } - - /** - * Find the nearest view in the specified direction that can take focus. - * This does not actually give focus to that view. - * - * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT - * - * @return The nearest focusable in the specified direction, or null if none - * can be found. - */ - public View focusSearch(int direction) { - if (mParent != null) { - return mParent.focusSearch(this, direction); - } else { - return null; - } - } - - /** - * This method is the last chance for the focused view and its ancestors to - * respond to an arrow key. This is called when the focused view did not - * consume the key internally, nor could the view system find a new view in - * the requested direction to give focus to. - * - * @param focused The currently focused view. - * @param direction The direction focus wants to move. One of FOCUS_UP, - * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT. - * @return True if the this view consumed this unhandled move. - */ - public boolean dispatchUnhandledMove(View focused, int direction) { - return false; - } - - /** - * If a user manually specified the next view id for a particular direction, - * use the root to look up the view. Once a view is found, it is cached - * for future lookups. - * @param root The root view of the hierarchy containing this view. - * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT - * @return The user specified next view, or null if there is none. - */ - View findUserSetNextFocus(View root, int direction) { - switch (direction) { - case FOCUS_LEFT: - if (mNextFocusLeftId == View.NO_ID) return null; - return findViewShouldExist(root, mNextFocusLeftId); - case FOCUS_RIGHT: - if (mNextFocusRightId == View.NO_ID) return null; - return findViewShouldExist(root, mNextFocusRightId); - case FOCUS_UP: - if (mNextFocusUpId == View.NO_ID) return null; - return findViewShouldExist(root, mNextFocusUpId); - case FOCUS_DOWN: - if (mNextFocusDownId == View.NO_ID) return null; - return findViewShouldExist(root, mNextFocusDownId); - } - return null; - } - - private static View findViewShouldExist(View root, int childViewId) { - View result = root.findViewById(childViewId); - if (result == null) { - Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified " - + "by user for id " + childViewId); - } - return result; - } - - /** - * Find and return all focusable views that are descendants of this view, - * possibly including this view if it is focusable itself. - * - * @param direction The direction of the focus - * @return A list of focusable views - */ - public ArrayList<View> getFocusables(int direction) { - ArrayList<View> result = new ArrayList<View>(24); - addFocusables(result, direction); - return result; - } - - /** - * Add any focusable views that are descendants of this view (possibly - * including this view if it is focusable itself) to views. If we are in touch mode, - * only add views that are also focusable in touch mode. - * - * @param views Focusable views found so far - * @param direction The direction of the focus - */ - public void addFocusables(ArrayList<View> views, int direction) { - if (!isFocusable()) return; - - if (isInTouchMode() && !isFocusableInTouchMode()) return; - - views.add(this); - } - - /** - * Find and return all touchable views that are descendants of this view, - * possibly including this view if it is touchable itself. - * - * @return A list of touchable views - */ - public ArrayList<View> getTouchables() { - ArrayList<View> result = new ArrayList<View>(); - addTouchables(result); - return result; - } - - /** - * Add any touchable views that are descendants of this view (possibly - * including this view if it is touchable itself) to views. - * - * @param views Touchable views found so far - */ - public void addTouchables(ArrayList<View> views) { - final int viewFlags = mViewFlags; - - if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) - && (viewFlags & ENABLED_MASK) == ENABLED) { - views.add(this); - } - } - - /** - * Call this to try to give focus to a specific view or to one of its - * descendants. - * - * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false), - * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode}) - * while the device is in touch mode. - * - * See also {@link #focusSearch}, which is what you call to say that you - * have focus, and you want your parent to look for the next one. - * - * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments - * {@link #FOCUS_DOWN} and <code>null</code>. - * - * @return Whether this view or one of its descendants actually took focus. - */ - public final boolean requestFocus() { - return requestFocus(View.FOCUS_DOWN); - } - - - /** - * Call this to try to give focus to a specific view or to one of its - * descendants and give it a hint about what direction focus is heading. - * - * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false), - * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode}) - * while the device is in touch mode. - * - * See also {@link #focusSearch}, which is what you call to say that you - * have focus, and you want your parent to look for the next one. - * - * This is equivalent to calling {@link #requestFocus(int, Rect)} with - * <code>null</code> set for the previously focused rectangle. - * - * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT - * @return Whether this view or one of its descendants actually took focus. - */ - public final boolean requestFocus(int direction) { - return requestFocus(direction, null); - } - - /** - * Call this to try to give focus to a specific view or to one of its descendants - * and give it hints about the direction and a specific rectangle that the focus - * is coming from. The rectangle can help give larger views a finer grained hint - * about where focus is coming from, and therefore, where to show selection, or - * forward focus change internally. - * - * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false), - * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode}) - * while the device is in touch mode. - * - * A View will not take focus if it is not visible. - * - * A View will not take focus if one of its parents has {@link android.view.ViewGroup#getDescendantFocusability()} - * equal to {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}. - * - * See also {@link #focusSearch}, which is what you call to say that you - * have focus, and you want your parent to look for the next one. - * - * You may wish to override this method if your custom {@link View} has an internal - * {@link View} that it wishes to forward the request to. - * - * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT - * @param previouslyFocusedRect The rectangle (in this View's coordinate system) - * to give a finer grained hint about where focus is coming from. May be null - * if there is no hint. - * @return Whether this view or one of its descendants actually took focus. - */ - public boolean requestFocus(int direction, Rect previouslyFocusedRect) { - // need to be focusable - if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE || - (mViewFlags & VISIBILITY_MASK) != VISIBLE) { - return false; - } - - // need to be focusable in touch mode if in touch mode - if (isInTouchMode() && - (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) { - return false; - } - - // need to not have any parents blocking us - if (hasAncestorThatBlocksDescendantFocus()) { - return false; - } - - handleFocusGainInternal(direction, previouslyFocusedRect); - return true; - } - - /** - * Call this to try to give focus to a specific view or to one of its descendants. This is a - * special variant of {@link #requestFocus() } that will allow views that are not focuable in - * touch mode to request focus when they are touched. - * - * @return Whether this view or one of its descendants actually took focus. - * - * @see #isInTouchMode() - * - */ - public final boolean requestFocusFromTouch() { - // Leave touch mode if we need to - if (isInTouchMode()) { - View root = getRootView(); - if (root != null) { - ViewRoot viewRoot = (ViewRoot)root.getParent(); - if (viewRoot != null) { - viewRoot.ensureTouchMode(false); - } - } - } - return requestFocus(View.FOCUS_DOWN); - } - - /** - * @return Whether any ancestor of this view blocks descendant focus. - */ - private boolean hasAncestorThatBlocksDescendantFocus() { - ViewParent ancestor = mParent; - while (ancestor instanceof ViewGroup) { - final ViewGroup vgAncestor = (ViewGroup) ancestor; - if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) { - return true; - } else { - ancestor = vgAncestor.getParent(); - } - } - return false; - } - - /** - * capture information of this view for later analysis: developement only - * check dynamic switch to make sure we only dump view - * when ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW) is set - */ - private static void captureViewInfo(String subTag, View v) { - if (v == null || - SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW, 0) == 0) { - return; - } - ViewDebug.dumpCapturedView(subTag, v); - } - - /** - * Dispatch a key event before it is processed by any input method - * associated with the view hierarchy. This can be used to intercept - * key events in special situations before the IME consumes them; a - * typical example would be handling the BACK key to update the application's - * UI instead of allowing the IME to see it and close itself. - * - * @param event The key event to be dispatched. - * @return True if the event was handled, false otherwise. - */ - public boolean dispatchKeyEventPreIme(KeyEvent event) { - return onKeyPreIme(event.getKeyCode(), event); - } - - /** - * Dispatch a key event to the next view on the focus path. This path runs - * from the top of the view tree down to the currently focused view. If this - * view has focus, it will dispatch to itself. Otherwise it will dispatch - * the next node down the focus path. This method also fires any key - * listeners. - * - * @param event The key event to be dispatched. - * @return True if the event was handled, false otherwise. - */ - public boolean dispatchKeyEvent(KeyEvent event) { - // If any attached key listener a first crack at the event. - //noinspection SimplifiableIfStatement - - if (android.util.Config.LOGV) { - captureViewInfo("captureViewKeyEvent", this); - } - - if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED - && mOnKeyListener.onKey(this, event.getKeyCode(), event)) { - return true; - } - - return event.dispatch(this); - } - - /** - * Dispatches a key shortcut event. - * - * @param event The key event to be dispatched. - * @return True if the event was handled by the view, false otherwise. - */ - public boolean dispatchKeyShortcutEvent(KeyEvent event) { - return onKeyShortcut(event.getKeyCode(), event); - } - - /** - * Pass the touch screen motion event down to the target view, or this - * view if it is the target. - * - * @param event The motion event to be dispatched. - * @return True if the event was handled by the view, false otherwise. - */ - public boolean dispatchTouchEvent(MotionEvent event) { - if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && - mOnTouchListener.onTouch(this, event)) { - return true; - } - return onTouchEvent(event); - } - - /** - * Pass a trackball motion event down to the focused view. - * - * @param event The motion event to be dispatched. - * @return True if the event was handled by the view, false otherwise. - */ - public boolean dispatchTrackballEvent(MotionEvent event) { - //Log.i("view", "view=" + this + ", " + event.toString()); - return onTrackballEvent(event); - } - - /** - * Called when the window containing this view gains or loses window focus. - * ViewGroups should override to route to their children. - * - * @param hasFocus True if the window containing this view now has focus, - * false otherwise. - */ - public void dispatchWindowFocusChanged(boolean hasFocus) { - onWindowFocusChanged(hasFocus); - } - - /** - * Called when the window containing this view gains or loses focus. Note - * that this is separate from view focus: to receive key events, both - * your view and its window must have focus. If a window is displayed - * on top of yours that takes input focus, then your own window will lose - * focus but the view focus will remain unchanged. - * - * @param hasWindowFocus True if the window containing this view now has - * focus, false otherwise. - */ - public void onWindowFocusChanged(boolean hasWindowFocus) { - InputMethodManager imm = InputMethodManager.peekInstance(); - if (!hasWindowFocus) { - if (isPressed()) { - setPressed(false); - } - if (imm != null && (mPrivateFlags & FOCUSED) != 0) { - imm.focusOut(this); - } - } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) { - imm.focusIn(this); - } - refreshDrawableState(); - } - - /** - * Returns true if this view is in a window that currently has window focus. - * Note that this is not the same as the view itself having focus. - * - * @return True if this view is in a window that currently has window focus. - */ - public boolean hasWindowFocus() { - return mAttachInfo != null && mAttachInfo.mHasWindowFocus; - } - - /** - * Dispatch a window visibility change down the view hierarchy. - * ViewGroups should override to route to their children. - * - * @param visibility The new visibility of the window. - * - * @see #onWindowVisibilityChanged - */ - public void dispatchWindowVisibilityChanged(int visibility) { - onWindowVisibilityChanged(visibility); - } - - /** - * Called when the window containing has change its visibility - * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note - * that this tells you whether or not your window is being made visible - * to the window manager; this does <em>not</em> tell you whether or not - * your window is obscured by other windows on the screen, even if it - * is itself visible. - * - * @param visibility The new visibility of the window. - */ - protected void onWindowVisibilityChanged(int visibility) { - } - - /** - * Returns the current visibility of the window this view is attached to - * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}). - * - * @return Returns the current visibility of the view's window. - */ - public int getWindowVisibility() { - return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE; - } - - /** - * Retrieve the overall visible display size in which the window this view is - * attached to has been positioned in. This takes into account screen - * decorations above the window, for both cases where the window itself - * is being position inside of them or the window is being placed under - * then and covered insets are used for the window to position its content - * inside. In effect, this tells you the available area where content can - * be placed and remain visible to users. - * - * <p>This function requires an IPC back to the window manager to retrieve - * the requested information, so should not be used in performance critical - * code like drawing. - * - * @param outRect Filled in with the visible display frame. If the view - * is not attached to a window, this is simply the raw display size. - */ - public void getWindowVisibleDisplayFrame(Rect outRect) { - if (mAttachInfo != null) { - try { - mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); - } catch (RemoteException e) { - return; - } - // XXX This is really broken, and probably all needs to be done - // in the window manager, and we need to know more about whether - // we want the area behind or in front of the IME. - final Rect insets = mAttachInfo.mVisibleInsets; - outRect.left += insets.left; - outRect.top += insets.top; - outRect.right -= insets.right; - outRect.bottom -= insets.bottom; - return; - } - Display d = WindowManagerImpl.getDefault().getDefaultDisplay(); - outRect.set(0, 0, d.getWidth(), d.getHeight()); - } - - /** - * Private function to aggregate all per-view attributes in to the view - * root. - */ - void dispatchCollectViewAttributes(int visibility) { - performCollectViewAttributes(visibility); - } - - void performCollectViewAttributes(int visibility) { - //noinspection PointlessBitwiseExpression - if (((visibility | mViewFlags) & (VISIBILITY_MASK | KEEP_SCREEN_ON)) - == (VISIBLE | KEEP_SCREEN_ON)) { - mAttachInfo.mKeepScreenOn = true; - } - } - - void needGlobalAttributesUpdate(boolean force) { - AttachInfo ai = mAttachInfo; - if (ai != null) { - if (ai.mKeepScreenOn || force) { - ai.mRecomputeGlobalAttributes = true; - } - } - } - - /** - * Returns whether the device is currently in touch mode. Touch mode is entered - * once the user begins interacting with the device by touch, and affects various - * things like whether focus is always visible to the user. - * - * @return Whether the device is in touch mode. - */ - @ViewDebug.ExportedProperty - public boolean isInTouchMode() { - if (mAttachInfo != null) { - return mAttachInfo.mInTouchMode; - } else { - return ViewRoot.isInTouchMode(); - } - } - - /** - * Returns the context the view is running in, through which it can - * access the current theme, resources, etc. - * - * @return The view's Context. - */ - @ViewDebug.CapturedViewProperty - public final Context getContext() { - return mContext; - } - - /** - * Handle a key event before it is processed by any input method - * associated with the view hierarchy. This can be used to intercept - * key events in special situations before the IME consumes them; a - * typical example would be handling the BACK key to update the application's - * UI instead of allowing the IME to see it and close itself. - * - * @param keyCode The value in event.getKeyCode(). - * @param event Description of the key event. - * @return If you handled the event, return true. If you want to allow the - * event to be handled by the next receiver, return false. - */ - public boolean onKeyPreIme(int keyCode, KeyEvent event) { - return false; - } - - /** - * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) - * KeyEvent.Callback.onKeyMultiple()}: perform press of the view - * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER} - * is released, if the view is enabled and clickable. - * - * @param keyCode A key code that represents the button pressed, from - * {@link android.view.KeyEvent}. - * @param event The KeyEvent object that defines the button action. - */ - public boolean onKeyDown(int keyCode, KeyEvent event) { - boolean result = false; - - switch (keyCode) { - case KeyEvent.KEYCODE_DPAD_CENTER: - case KeyEvent.KEYCODE_ENTER: { - if ((mViewFlags & ENABLED_MASK) == DISABLED) { - return true; - } - // Long clickable items don't necessarily have to be clickable - if (((mViewFlags & CLICKABLE) == CLICKABLE || - (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) && - (event.getRepeatCount() == 0)) { - setPressed(true); - if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { - postCheckForLongClick(); - } - return true; - } - break; - } - } - return result; - } - - /** - * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) - * KeyEvent.Callback.onKeyMultiple()}: perform clicking of the view - * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or - * {@link KeyEvent#KEYCODE_ENTER} is released. - * - * @param keyCode A key code that represents the button pressed, from - * {@link android.view.KeyEvent}. - * @param event The KeyEvent object that defines the button action. - */ - public boolean onKeyUp(int keyCode, KeyEvent event) { - boolean result = false; - - switch (keyCode) { - case KeyEvent.KEYCODE_DPAD_CENTER: - case KeyEvent.KEYCODE_ENTER: { - if ((mViewFlags & ENABLED_MASK) == DISABLED) { - return true; - } - if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) { - setPressed(false); - - if (!mHasPerformedLongPress) { - // This is a tap, so remove the longpress check - if (mPendingCheckForLongPress != null) { - removeCallbacks(mPendingCheckForLongPress); - } - - result = performClick(); - } - } - break; - } - } - return result; - } - - /** - * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) - * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle - * the event). - * - * @param keyCode A key code that represents the button pressed, from - * {@link android.view.KeyEvent}. - * @param repeatCount The number of times the action was made. - * @param event The KeyEvent object that defines the button action. - */ - public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { - return false; - } - - /** - * Called when an unhandled key shortcut event occurs. - * - * @param keyCode The value in event.getKeyCode(). - * @param event Description of the key event. - * @return If you handled the event, return true. If you want to allow the - * event to be handled by the next receiver, return false. - */ - public boolean onKeyShortcut(int keyCode, KeyEvent event) { - return false; - } - - /** - * Check whether the called view is a text editor, in which case it - * would make sense to automatically display a soft input window for - * it. Subclasses should override this if they implement - * {@link #onCreateInputConnection(EditorInfo)} to return true if - * a call on that method would return a non-null InputConnection. The - * default implementation always returns false. - * - * @return Returns true if this view is a text editor, else false. - */ - public boolean onCheckIsTextEditor() { - return false; - } - - /** - * Create a new InputConnection for an InputMethod to interact - * with the view. The default implementation returns null, since it doesn't - * support input methods. You can override this to implement such support. - * This is only needed for views that take focus and text input. - * - * <p>When implementing this, you probably also want to implement - * {@link #onCheckIsTextEditor()} to indicate you will return a - * non-null InputConnection. - * - * @param outAttrs Fill in with attribute information about the connection. - */ - public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - return null; - } - - /** - * Show the context menu for this view. It is not safe to hold on to the - * menu after returning from this method. - * - * @param menu The context menu to populate - */ - public void createContextMenu(ContextMenu menu) { - ContextMenuInfo menuInfo = getContextMenuInfo(); - - // Sets the current menu info so all items added to menu will have - // my extra info set. - ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo); - - onCreateContextMenu(menu); - if (mOnCreateContextMenuListener != null) { - mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo); - } - - // Clear the extra information so subsequent items that aren't mine don't - // have my extra info. - ((MenuBuilder)menu).setCurrentMenuInfo(null); - - if (mParent != null) { - mParent.createContextMenu(menu); - } - } - - /** - * Views should implement this if they have extra information to associate - * with the context menu. The return result is supplied as a parameter to - * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} - * callback. - * - * @return Extra information about the item for which the context menu - * should be shown. This information will vary across different - * subclasses of View. - */ - protected ContextMenuInfo getContextMenuInfo() { - return null; - } - - /** - * Views should implement this if the view itself is going to add items to - * the context menu. - * - * @param menu the context menu to populate - */ - protected void onCreateContextMenu(ContextMenu menu) { - } - - /** - * Implement this method to handle trackball motion events. The - * <em>relative</em> movement of the trackball since the last event - * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and - * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so - * that a movement of 1 corresponds to the user pressing one DPAD key (so - * they will often be fractional values, representing the more fine-grained - * movement information available from a trackball). - * - * @param event The motion event. - * @return True if the event was handled, false otherwise. - */ - public boolean onTrackballEvent(MotionEvent event) { - return false; - } - - /** - * Implement this method to handle touch screen motion events. - * - * @param event The motion event. - * @return True if the event was handled, false otherwise. - */ - public boolean onTouchEvent(MotionEvent event) { - final int viewFlags = mViewFlags; - - if ((viewFlags & ENABLED_MASK) == DISABLED) { - // A disabled view that is clickable still consumes the touch - // events, it just doesn't respond to them. - return (((viewFlags & CLICKABLE) == CLICKABLE || - (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)); - } - - if (mTouchDelegate != null) { - if (mTouchDelegate.onTouchEvent(event)) { - return true; - } - } - - if (((viewFlags & CLICKABLE) == CLICKABLE || - (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) { - switch (event.getAction()) { - case MotionEvent.ACTION_UP: - if ((mPrivateFlags & PRESSED) != 0) { - // take focus if we don't have it already and we should in - // touch mode. - boolean focusTaken = false; - if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { - focusTaken = requestFocus(); - } - - if (!mHasPerformedLongPress) { - // This is a tap, so remove the longpress check - if (mPendingCheckForLongPress != null) { - removeCallbacks(mPendingCheckForLongPress); - } - - // Only perform take click actions if we were in the pressed state - if (!focusTaken) { - performClick(); - } - } - - if (mUnsetPressedState == null) { - mUnsetPressedState = new UnsetPressedState(); - } - - if (!post(mUnsetPressedState)) { - // If the post failed, unpress right now - mUnsetPressedState.run(); - } - } - break; - - case MotionEvent.ACTION_DOWN: - mPrivateFlags |= PRESSED; - refreshDrawableState(); - if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { - postCheckForLongClick(); - } - break; - - case MotionEvent.ACTION_CANCEL: - mPrivateFlags &= ~PRESSED; - refreshDrawableState(); - break; - - case MotionEvent.ACTION_MOVE: - final int x = (int) event.getX(); - final int y = (int) event.getY(); - - // Be lenient about moving outside of buttons - int slop = ViewConfiguration.get(mContext).getScaledTouchSlop(); - if ((x < 0 - slop) || (x >= getWidth() + slop) || - (y < 0 - slop) || (y >= getHeight() + slop)) { - // Outside button - if ((mPrivateFlags & PRESSED) != 0) { - // Remove any future long press checks - if (mPendingCheckForLongPress != null) { - removeCallbacks(mPendingCheckForLongPress); - } - - // Need to switch from pressed to not pressed - mPrivateFlags &= ~PRESSED; - refreshDrawableState(); - } - } else { - // Inside button - if ((mPrivateFlags & PRESSED) == 0) { - // Need to switch from not pressed to pressed - mPrivateFlags |= PRESSED; - refreshDrawableState(); - } - } - break; - } - return true; - } - - return false; - } - - /** - * Cancels a pending long press. Your subclass can use this if you - * want the context menu to come up if the user presses and holds - * at the same place, but you don't want it to come up if they press - * and then move around enough to cause scrolling. - */ - public void cancelLongPress() { - if (mPendingCheckForLongPress != null) { - removeCallbacks(mPendingCheckForLongPress); - } - } - - /** - * Sets the TouchDelegate for this View. - */ - public void setTouchDelegate(TouchDelegate delegate) { - mTouchDelegate = delegate; - } - - /** - * Gets the TouchDelegate for this View. - */ - public TouchDelegate getTouchDelegate() { - return mTouchDelegate; - } - - /** - * Set flags controlling behavior of this view. - * - * @param flags Constant indicating the value which should be set - * @param mask Constant indicating the bit range that should be changed - */ - void setFlags(int flags, int mask) { - int old = mViewFlags; - mViewFlags = (mViewFlags & ~mask) | (flags & mask); - - int changed = mViewFlags ^ old; - if (changed == 0) { - return; - } - int privateFlags = mPrivateFlags; - - /* Check if the FOCUSABLE bit has changed */ - if (((changed & FOCUSABLE_MASK) != 0) && - ((privateFlags & HAS_BOUNDS) !=0)) { - if (((old & FOCUSABLE_MASK) == FOCUSABLE) - && ((privateFlags & FOCUSED) != 0)) { - /* Give up focus if we are no longer focusable */ - clearFocus(); - } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE) - && ((privateFlags & FOCUSED) == 0)) { - /* - * Tell the view system that we are now available to take focus - * if no one else already has it. - */ - if (mParent != null) mParent.focusableViewAvailable(this); - } - } - - if ((flags & VISIBILITY_MASK) == VISIBLE) { - if ((changed & VISIBILITY_MASK) != 0) { - /* - * If this view is becoming visible, set the DRAWN flag so that - * the next invalidate() will not be skipped. - */ - mPrivateFlags |= DRAWN; - - needGlobalAttributesUpdate(true); - - // a view becoming visible is worth notifying the parent - // about in case nothing has focus. even if this specific view - // isn't focusable, it may contain something that is, so let - // the root view try to give this focus if nothing else does. - if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) { - mParent.focusableViewAvailable(this); - } - } - } - - /* Check if the GONE bit has changed */ - if ((changed & GONE) != 0) { - needGlobalAttributesUpdate(false); - requestLayout(); - invalidate(); - - if (((mViewFlags & VISIBILITY_MASK) == GONE) && hasFocus()) { - clearFocus(); - } - if (mAttachInfo != null) { - mAttachInfo.mViewVisibilityChanged = true; - } - } - - /* Check if the VISIBLE bit has changed */ - if ((changed & INVISIBLE) != 0) { - needGlobalAttributesUpdate(false); - invalidate(); - - if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) { - // root view becoming invisible shouldn't clear focus - if (getRootView() != this) { - clearFocus(); - } - } - if (mAttachInfo != null) { - mAttachInfo.mViewVisibilityChanged = true; - } - } - - if ((changed & WILL_NOT_CACHE_DRAWING) != 0) { - if (mDrawingCache != null) { - mDrawingCache.recycle(); - } - mDrawingCache = null; - } - - if ((changed & DRAWING_CACHE_ENABLED) != 0) { - if (mDrawingCache != null) { - mDrawingCache.recycle(); - } - mDrawingCache = null; - mPrivateFlags &= ~DRAWING_CACHE_VALID; - } - - if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) { - if (mDrawingCache != null) { - mDrawingCache.recycle(); - } - mDrawingCache = null; - mPrivateFlags &= ~DRAWING_CACHE_VALID; - } - - if ((changed & DRAW_MASK) != 0) { - if ((mViewFlags & WILL_NOT_DRAW) != 0) { - if (mBGDrawable != null) { - mPrivateFlags &= ~SKIP_DRAW; - mPrivateFlags |= ONLY_DRAWS_BACKGROUND; - } else { - mPrivateFlags |= SKIP_DRAW; - } - } else { - mPrivateFlags &= ~SKIP_DRAW; - } - requestLayout(); - invalidate(); - } - - if ((changed & KEEP_SCREEN_ON) != 0) { - if (mParent != null) { - mParent.recomputeViewAttributes(this); - } - } - } - - /** - * Change the view's z order in the tree, so it's on top of other sibling - * views - */ - public void bringToFront() { - if (mParent != null) { - mParent.bringChildToFront(this); - } - } - - /** - * This is called in response to an internal scroll in this view (i.e., the - * view scrolled its own contents). This is typically as a result of - * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been - * called. - * - * @param l Current horizontal scroll origin. - * @param t Current vertical scroll origin. - * @param oldl Previous horizontal scroll origin. - * @param oldt Previous vertical scroll origin. - */ - protected void onScrollChanged(int l, int t, int oldl, int oldt) { - mBackgroundSizeChanged = true; - - final AttachInfo ai = mAttachInfo; - if (ai != null) { - ai.mViewScrollChanged = true; - } - } - - /** - * This is called during layout when the size of this view has changed. If - * you were just added to the view hierarchy, you're called with the old - * values of 0. - * - * @param w Current width of this view. - * @param h Current height of this view. - * @param oldw Old width of this view. - * @param oldh Old height of this view. - */ - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - } - - /** - * Called by draw to draw the child views. This may be overridden - * by derived classes to gain control just before its children are drawn - * (but after its own view has been drawn). - * @param canvas the canvas on which to draw the view - */ - protected void dispatchDraw(Canvas canvas) { - } - - /** - * Gets the parent of this view. Note that the parent is a - * ViewParent and not necessarily a View. - * - * @return Parent of this view. - */ - public final ViewParent getParent() { - return mParent; - } - - /** - * Return the scrolled left position of this view. This is the left edge of - * the displayed part of your view. You do not need to draw any pixels - * farther left, since those are outside of the frame of your view on - * screen. - * - * @return The left edge of the displayed part of your view, in pixels. - */ - public final int getScrollX() { - return mScrollX; - } - - /** - * Return the scrolled top position of this view. This is the top edge of - * the displayed part of your view. You do not need to draw any pixels above - * it, since those are outside of the frame of your view on screen. - * - * @return The top edge of the displayed part of your view, in pixels. - */ - public final int getScrollY() { - return mScrollY; - } - - /** - * Return the width of the your view. - * - * @return The width of your view, in pixels. - */ - @ViewDebug.ExportedProperty - public final int getWidth() { - return mRight - mLeft; - } - - /** - * Return the height of your view. - * - * @return The height of your view, in pixels. - */ - @ViewDebug.ExportedProperty - public final int getHeight() { - return mBottom - mTop; - } - - /** - * Return the visible drawing bounds of your view. Fills in the output - * rectangle with the values from getScrollX(), getScrollY(), - * getWidth(), and getHeight(). - * - * @param outRect The (scrolled) drawing bounds of the view. - */ - public void getDrawingRect(Rect outRect) { - outRect.left = mScrollX; - outRect.top = mScrollY; - outRect.right = mScrollX + (mRight - mLeft); - outRect.bottom = mScrollY + (mBottom - mTop); - } - - /** - * The width of this view as measured in the most recent call to measure(). - * This should be used during measurement and layout calculations only. Use - * {@link #getWidth()} to see how wide a view is after layout. - * - * @return The measured width of this view. - */ - public final int getMeasuredWidth() { - return mMeasuredWidth; - } - - /** - * The height of this view as measured in the most recent call to measure(). - * This should be used during measurement and layout calculations only. Use - * {@link #getHeight()} to see how tall a view is after layout. - * - * @return The measured height of this view. - */ - public final int getMeasuredHeight() { - return mMeasuredHeight; - } - - /** - * Top position of this view relative to its parent. - * - * @return The top of this view, in pixels. - */ - @ViewDebug.CapturedViewProperty - public final int getTop() { - return mTop; - } - - /** - * Bottom position of this view relative to its parent. - * - * @return The bottom of this view, in pixels. - */ - @ViewDebug.CapturedViewProperty - public final int getBottom() { - return mBottom; - } - - /** - * Left position of this view relative to its parent. - * - * @return The left edge of this view, in pixels. - */ - @ViewDebug.CapturedViewProperty - public final int getLeft() { - return mLeft; - } - - /** - * Right position of this view relative to its parent. - * - * @return The right edge of this view, in pixels. - */ - @ViewDebug.CapturedViewProperty - public final int getRight() { - return mRight; - } - - /** - * Hit rectangle in parent's coordinates - * - * @param outRect The hit rectangle of the view. - */ - public void getHitRect(Rect outRect) { - outRect.set(mLeft, mTop, mRight, mBottom); - } - - /** - * When a view has focus and the user navigates away from it, the next view is searched for - * starting from the rectangle filled in by this method. - * - * By default, the rectange is the {@link #getDrawingRect})of the view. However, if your - * view maintains some idea of internal selection, such as a cursor, or a selected row - * or column, you should override this method and fill in a more specific rectangle. - * - * @param r The rectangle to fill in, in this view's coordinates. - */ - public void getFocusedRect(Rect r) { - getDrawingRect(r); - } - - /** - * If some part of this view is not clipped by any of its parents, then - * return that area in r in global (root) coordinates. To convert r to local - * coordinates, offset it by -globalOffset (e.g. r.offset(-globalOffset.x, - * -globalOffset.y)) If the view is completely clipped or translated out, - * return false. - * - * @param r If true is returned, r holds the global coordinates of the - * visible portion of this view. - * @param globalOffset If true is returned, globalOffset holds the dx,dy - * between this view and its root. globalOffet may be null. - * @return true if r is non-empty (i.e. part of the view is visible at the - * root level. - */ - public boolean getGlobalVisibleRect(Rect r, Point globalOffset) { - int width = mRight - mLeft; - int height = mBottom - mTop; - if (width > 0 && height > 0) { - r.set(0, 0, width, height); - if (globalOffset != null) { - globalOffset.set(-mScrollX, -mScrollY); - } - return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset); - } - return false; - } - - public final boolean getGlobalVisibleRect(Rect r) { - return getGlobalVisibleRect(r, null); - } - - public final boolean getLocalVisibleRect(Rect r) { - Point offset = new Point(); - if (getGlobalVisibleRect(r, offset)) { - r.offset(-offset.x, -offset.y); // make r local - return true; - } - return false; - } - - /** - * Offset this view's vertical location by the specified number of pixels. - * - * @param offset the number of pixels to offset the view by - */ - public void offsetTopAndBottom(int offset) { - mTop += offset; - mBottom += offset; - } - - /** - * Offset this view's horizontal location by the specified amount of pixels. - * - * @param offset the numer of pixels to offset the view by - */ - public void offsetLeftAndRight(int offset) { - mLeft += offset; - mRight += offset; - } - - /** - * Get the LayoutParams associated with this view. All views should have - * layout parameters. These supply parameters to the <i>parent</i> of this - * view specifying how it should be arranged. There are many subclasses of - * ViewGroup.LayoutParams, and these correspond to the different subclasses - * of ViewGroup that are responsible for arranging their children. - * @return The LayoutParams associated with this view - */ - @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_") - public ViewGroup.LayoutParams getLayoutParams() { - return mLayoutParams; - } - - /** - * Set the layout parameters associated with this view. These supply - * parameters to the <i>parent</i> of this view specifying how it should be - * arranged. There are many subclasses of ViewGroup.LayoutParams, and these - * correspond to the different subclasses of ViewGroup that are responsible - * for arranging their children. - * - * @param params the layout parameters for this view - */ - public void setLayoutParams(ViewGroup.LayoutParams params) { - if (params == null) { - throw new NullPointerException("params == null"); - } - mLayoutParams = params; - requestLayout(); - } - - /** - * Set the scrolled position of your view. This will cause a call to - * {@link #onScrollChanged(int, int, int, int)} and the view will be - * invalidated. - * @param x the x position to scroll to - * @param y the y position to scroll to - */ - public void scrollTo(int x, int y) { - if (mScrollX != x || mScrollY != y) { - int oldX = mScrollX; - int oldY = mScrollY; - mScrollX = x; - mScrollY = y; - onScrollChanged(mScrollX, mScrollY, oldX, oldY); - invalidate(); - } - } - - /** - * Move the scrolled position of your view. This will cause a call to - * {@link #onScrollChanged(int, int, int, int)} and the view will be - * invalidated. - * @param x the amount of pixels to scroll by horizontally - * @param y the amount of pixels to scroll by vertically - */ - public void scrollBy(int x, int y) { - scrollTo(mScrollX + x, mScrollY + y); - } - - /** - * Mark the the area defined by dirty as needing to be drawn. If the view is - * visible, {@link #onDraw} will be called at some point in the future. - * This must be called from a UI thread. To call from a non-UI thread, call - * {@link #postInvalidate()}. - * - * WARNING: This method is destructive to dirty. - * @param dirty the rectangle representing the bounds of the dirty region - */ - public void invalidate(Rect dirty) { - if (ViewDebug.TRACE_HIERARCHY) { - ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); - } - - if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) { - mPrivateFlags &= ~DRAWING_CACHE_VALID; - final ViewParent p = mParent; - final AttachInfo ai = mAttachInfo; - if (p != null && ai != null) { - final int scrollX = mScrollX; - final int scrollY = mScrollY; - final Rect r = ai.mTmpInvalRect; - r.set(dirty.left - scrollX, dirty.top - scrollY, - dirty.right - scrollX, dirty.bottom - scrollY); - mParent.invalidateChild(this, r); - } - } - } - - /** - * Mark the the area defined by the rect (l,t,r,b) as needing to be drawn. - * The coordinates of the dirty rect are relative to the view. - * If the view is visible, {@link #onDraw} will be called at some point - * in the future. This must be called from a UI thread. To call - * from a non-UI thread, call {@link #postInvalidate()}. - * @param l the left position of the dirty region - * @param t the top position of the dirty region - * @param r the right position of the dirty region - * @param b the bottom position of the dirty region - */ - public void invalidate(int l, int t, int r, int b) { - if (ViewDebug.TRACE_HIERARCHY) { - ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); - } - - if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) { - mPrivateFlags &= ~DRAWING_CACHE_VALID; - final ViewParent p = mParent; - final AttachInfo ai = mAttachInfo; - if (p != null && ai != null && l < r && t < b) { - final int scrollX = mScrollX; - final int scrollY = mScrollY; - final Rect tmpr = ai.mTmpInvalRect; - tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY); - p.invalidateChild(this, tmpr); - } - } - } - - /** - * Invalidate the whole view. If the view is visible, {@link #onDraw} will - * be called at some point in the future. This must be called from a - * UI thread. To call from a non-UI thread, call {@link #postInvalidate()}. - */ - public void invalidate() { - if (ViewDebug.TRACE_HIERARCHY) { - ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); - } - - if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) { - mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID; - final ViewParent p = mParent; - final AttachInfo ai = mAttachInfo; - if (p != null && ai != null) { - final Rect r = ai.mTmpInvalRect; - r.set(0, 0, mRight - mLeft, mBottom - mTop); - // Don't call invalidate -- we don't want to internally scroll - // our own bounds - p.invalidateChild(this, r); - } - } - } - - /** - * @return A handler associated with the thread running the View. This - * handler can be used to pump events in the UI events queue. - */ - public Handler getHandler() { - if (mAttachInfo != null) { - return mAttachInfo.mHandler; - } - return null; - } - - /** - * Causes the Runnable to be added to the message queue. - * The runnable will be run on the user interface thread. - * - * @param action The Runnable that will be executed. - * - * @return Returns true if the Runnable was successfully placed in to the - * message queue. Returns false on failure, usually because the - * looper processing the message queue is exiting. - */ - public boolean post(Runnable action) { - Handler handler; - if (mAttachInfo != null) { - handler = mAttachInfo.mHandler; - } else { - // Assume that post will succeed later - ViewRoot.getRunQueue().post(action); - return true; - } - - return handler.post(action); - } - - /** - * Causes the Runnable to be added to the message queue, to be run - * after the specified amount of time elapses. - * The runnable will be run on the user interface thread. - * - * @param action The Runnable that will be executed. - * @param delayMillis The delay (in milliseconds) until the Runnable - * will be executed. - * - * @return true if the Runnable was successfully placed in to the - * message queue. Returns false on failure, usually because the - * looper processing the message queue is exiting. Note that a - * result of true does not mean the Runnable will be processed -- - * if the looper is quit before the delivery time of the message - * occurs then the message will be dropped. - */ - public boolean postDelayed(Runnable action, long delayMillis) { - Handler handler; - if (mAttachInfo != null) { - handler = mAttachInfo.mHandler; - } else { - // Assume that post will succeed later - ViewRoot.getRunQueue().postDelayed(action, delayMillis); - return true; - } - - return handler.postDelayed(action, delayMillis); - } - - /** - * Removes the specified Runnable from the message queue. - * - * @param action The Runnable to remove from the message handling queue - * - * @return true if this view could ask the Handler to remove the Runnable, - * false otherwise. When the returned value is true, the Runnable - * may or may not have been actually removed from the message queue - * (for instance, if the Runnable was not in the queue already.) - */ - public boolean removeCallbacks(Runnable action) { - Handler handler; - if (mAttachInfo != null) { - handler = mAttachInfo.mHandler; - } else { - // Assume that post will succeed later - ViewRoot.getRunQueue().removeCallbacks(action); - return true; - } - - handler.removeCallbacks(action); - return true; - } - - /** - * Cause an invalidate to happen on a subsequent cycle through the event loop. - * Use this to invalidate the View from a non-UI thread. - * - * @see #invalidate() - */ - public void postInvalidate() { - postInvalidateDelayed(0); - } - - /** - * Cause an invalidate of the specified area to happen on a subsequent cycle - * through the event loop. Use this to invalidate the View from a non-UI thread. - * - * @param left The left coordinate of the rectangle to invalidate. - * @param top The top coordinate of the rectangle to invalidate. - * @param right The right coordinate of the rectangle to invalidate. - * @param bottom The bottom coordinate of the rectangle to invalidate. - * - * @see #invalidate(int, int, int, int) - * @see #invalidate(Rect) - */ - public void postInvalidate(int left, int top, int right, int bottom) { - postInvalidateDelayed(0, left, top, right, bottom); - } - - /** - * Cause an invalidate to happen on a subsequent cycle through the event - * loop. Waits for the specified amount of time. - * - * @param delayMilliseconds the duration in milliseconds to delay the - * invalidation by - */ - public void postInvalidateDelayed(long delayMilliseconds) { - // We try only with the AttachInfo because there's no point in invalidating - // if we are not attached to our window - if (mAttachInfo != null) { - Message msg = Message.obtain(); - msg.what = AttachInfo.INVALIDATE_MSG; - msg.obj = this; - mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds); - } - } - - /** - * Cause an invalidate of the specified area to happen on a subsequent cycle - * through the event loop. Waits for the specified amount of time. - * - * @param delayMilliseconds the duration in milliseconds to delay the - * invalidation by - * @param left The left coordinate of the rectangle to invalidate. - * @param top The top coordinate of the rectangle to invalidate. - * @param right The right coordinate of the rectangle to invalidate. - * @param bottom The bottom coordinate of the rectangle to invalidate. - */ - public void postInvalidateDelayed(long delayMilliseconds, int left, int top, - int right, int bottom) { - - // We try only with the AttachInfo because there's no point in invalidating - // if we are not attached to our window - if (mAttachInfo != null) { - final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire(); - info.target = this; - info.left = left; - info.top = top; - info.right = right; - info.bottom = bottom; - - final Message msg = Message.obtain(); - msg.what = AttachInfo.INVALIDATE_RECT_MSG; - msg.obj = info; - mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds); - } - } - - /** - * Called by a parent to request that a child update its values for mScrollX - * and mScrollY if necessary. This will typically be done if the child is - * animating a scroll using a {@link android.widget.Scroller Scroller} - * object. - */ - public void computeScroll() { - } - - /** - * <p>Indicate whether the horizontal edges are faded when the view is - * scrolled horizontally.</p> - * - * @return true if the horizontal edges should are faded on scroll, false - * otherwise - * - * @see #setHorizontalFadingEdgeEnabled(boolean) - * @attr ref android.R.styleable#View_fadingEdge - */ - public boolean isHorizontalFadingEdgeEnabled() { - return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL; - } - - /** - * <p>Define whether the horizontal edges should be faded when this view - * is scrolled horizontally.</p> - * - * @param horizontalFadingEdgeEnabled true if the horizontal edges should - * be faded when the view is scrolled - * horizontally - * - * @see #isHorizontalFadingEdgeEnabled() - * @attr ref android.R.styleable#View_fadingEdge - */ - public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) { - if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) { - if (horizontalFadingEdgeEnabled) { - initScrollCache(); - } - - mViewFlags ^= FADING_EDGE_HORIZONTAL; - } - } - - /** - * <p>Indicate whether the vertical edges are faded when the view is - * scrolled horizontally.</p> - * - * @return true if the vertical edges should are faded on scroll, false - * otherwise - * - * @see #setVerticalFadingEdgeEnabled(boolean) - * @attr ref android.R.styleable#View_fadingEdge - */ - public boolean isVerticalFadingEdgeEnabled() { - return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL; - } - - /** - * <p>Define whether the vertical edges should be faded when this view - * is scrolled vertically.</p> - * - * @param verticalFadingEdgeEnabled true if the vertical edges should - * be faded when the view is scrolled - * vertically - * - * @see #isVerticalFadingEdgeEnabled() - * @attr ref android.R.styleable#View_fadingEdge - */ - public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) { - if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) { - if (verticalFadingEdgeEnabled) { - initScrollCache(); - } - - mViewFlags ^= FADING_EDGE_VERTICAL; - } - } - - /** - * Returns the strength, or intensity, of the top faded edge. The strength is - * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation - * returns 0.0 or 1.0 but no value in between. - * - * Subclasses should override this method to provide a smoother fade transition - * when scrolling occurs. - * - * @return the intensity of the top fade as a float between 0.0f and 1.0f - */ - protected float getTopFadingEdgeStrength() { - return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f; - } - - /** - * Returns the strength, or intensity, of the bottom faded edge. The strength is - * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation - * returns 0.0 or 1.0 but no value in between. - * - * Subclasses should override this method to provide a smoother fade transition - * when scrolling occurs. - * - * @return the intensity of the bottom fade as a float between 0.0f and 1.0f - */ - protected float getBottomFadingEdgeStrength() { - return computeVerticalScrollOffset() + computeVerticalScrollExtent() < - computeVerticalScrollRange() ? 1.0f : 0.0f; - } - - /** - * Returns the strength, or intensity, of the left faded edge. The strength is - * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation - * returns 0.0 or 1.0 but no value in between. - * - * Subclasses should override this method to provide a smoother fade transition - * when scrolling occurs. - * - * @return the intensity of the left fade as a float between 0.0f and 1.0f - */ - protected float getLeftFadingEdgeStrength() { - return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f; - } - - /** - * Returns the strength, or intensity, of the right faded edge. The strength is - * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation - * returns 0.0 or 1.0 but no value in between. - * - * Subclasses should override this method to provide a smoother fade transition - * when scrolling occurs. - * - * @return the intensity of the right fade as a float between 0.0f and 1.0f - */ - protected float getRightFadingEdgeStrength() { - return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() < - computeHorizontalScrollRange() ? 1.0f : 0.0f; - } - - /** - * <p>Indicate whether the horizontal scrollbar should be drawn or not. The - * scrollbar is not drawn by default.</p> - * - * @return true if the horizontal scrollbar should be painted, false - * otherwise - * - * @see #setHorizontalScrollBarEnabled(boolean) - */ - public boolean isHorizontalScrollBarEnabled() { - return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; - } - - /** - * <p>Define whether the horizontal scrollbar should be drawn or not. The - * scrollbar is not drawn by default.</p> - * - * @param horizontalScrollBarEnabled true if the horizontal scrollbar should - * be painted - * - * @see #isHorizontalScrollBarEnabled() - */ - public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) { - if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) { - mViewFlags ^= SCROLLBARS_HORIZONTAL; - recomputePadding(); - } - } - - /** - * <p>Indicate whether the vertical scrollbar should be drawn or not. The - * scrollbar is not drawn by default.</p> - * - * @return true if the vertical scrollbar should be painted, false - * otherwise - * - * @see #setVerticalScrollBarEnabled(boolean) - */ - public boolean isVerticalScrollBarEnabled() { - return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL; - } - - /** - * <p>Define whether the vertical scrollbar should be drawn or not. The - * scrollbar is not drawn by default.</p> - * - * @param verticalScrollBarEnabled true if the vertical scrollbar should - * be painted - * - * @see #isVerticalScrollBarEnabled() - */ - public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) { - if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) { - mViewFlags ^= SCROLLBARS_VERTICAL; - recomputePadding(); - } - } - - private void recomputePadding() { - setPadding(mPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); - } - - /** - * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or - * inset. When inset, they add to the padding of the view. And the scrollbars - * can be drawn inside the padding area or on the edge of the view. For example, - * if a view has a background drawable and you want to draw the scrollbars - * inside the padding specified by the drawable, you can use - * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to - * appear at the edge of the view, ignoring the padding, then you can use - * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p> - * @param style the style of the scrollbars. Should be one of - * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET, - * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET. - * @see #SCROLLBARS_INSIDE_OVERLAY - * @see #SCROLLBARS_INSIDE_INSET - * @see #SCROLLBARS_OUTSIDE_OVERLAY - * @see #SCROLLBARS_OUTSIDE_INSET - */ - public void setScrollBarStyle(int style) { - if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) { - mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK); - recomputePadding(); - } - } - - /** - * <p>Returns the current scrollbar style.</p> - * @return the current scrollbar style - * @see #SCROLLBARS_INSIDE_OVERLAY - * @see #SCROLLBARS_INSIDE_INSET - * @see #SCROLLBARS_OUTSIDE_OVERLAY - * @see #SCROLLBARS_OUTSIDE_INSET - */ - public int getScrollBarStyle() { - return mViewFlags & SCROLLBARS_STYLE_MASK; - } - - /** - * <p>Compute the horizontal range that the horizontal scrollbar - * represents.</p> - * - * <p>The range is expressed in arbitrary units that must be the same as the - * units used by {@link #computeHorizontalScrollExtent()} and - * {@link #computeHorizontalScrollOffset()}.</p> - * - * <p>The default range is the drawing width of this view.</p> - * - * @return the total horizontal range represented by the horizontal - * scrollbar - * - * @see #computeHorizontalScrollExtent() - * @see #computeHorizontalScrollOffset() - * @see android.widget.ScrollBarDrawable - */ - protected int computeHorizontalScrollRange() { - return getWidth(); - } - - /** - * <p>Compute the horizontal offset of the horizontal scrollbar's thumb - * within the horizontal range. This value is used to compute the position - * of the thumb within the scrollbar's track.</p> - * - * <p>The range is expressed in arbitrary units that must be the same as the - * units used by {@link #computeHorizontalScrollRange()} and - * {@link #computeHorizontalScrollExtent()}.</p> - * - * <p>The default offset is the scroll offset of this view.</p> - * - * @return the horizontal offset of the scrollbar's thumb - * - * @see #computeHorizontalScrollRange() - * @see #computeHorizontalScrollExtent() - * @see android.widget.ScrollBarDrawable - */ - protected int computeHorizontalScrollOffset() { - return mScrollX; - } - - /** - * <p>Compute the horizontal extent of the horizontal scrollbar's thumb - * within the horizontal range. This value is used to compute the length - * of the thumb within the scrollbar's track.</p> - * - * <p>The range is expressed in arbitrary units that must be the same as the - * units used by {@link #computeHorizontalScrollRange()} and - * {@link #computeHorizontalScrollOffset()}.</p> - * - * <p>The default extent is the drawing width of this view.</p> - * - * @return the horizontal extent of the scrollbar's thumb - * - * @see #computeHorizontalScrollRange() - * @see #computeHorizontalScrollOffset() - * @see android.widget.ScrollBarDrawable - */ - protected int computeHorizontalScrollExtent() { - return getWidth(); - } - - /** - * <p>Compute the vertical range that the vertical scrollbar represents.</p> - * - * <p>The range is expressed in arbitrary units that must be the same as the - * units used by {@link #computeVerticalScrollExtent()} and - * {@link #computeVerticalScrollOffset()}.</p> - * - * @return the total vertical range represented by the vertical scrollbar - * - * <p>The default range is the drawing height of this view.</p> - * - * @see #computeVerticalScrollExtent() - * @see #computeVerticalScrollOffset() - * @see android.widget.ScrollBarDrawable - */ - protected int computeVerticalScrollRange() { - return getHeight(); - } - - /** - * <p>Compute the vertical offset of the vertical scrollbar's thumb - * within the horizontal range. This value is used to compute the position - * of the thumb within the scrollbar's track.</p> - * - * <p>The range is expressed in arbitrary units that must be the same as the - * units used by {@link #computeVerticalScrollRange()} and - * {@link #computeVerticalScrollExtent()}.</p> - * - * <p>The default offset is the scroll offset of this view.</p> - * - * @return the vertical offset of the scrollbar's thumb - * - * @see #computeVerticalScrollRange() - * @see #computeVerticalScrollExtent() - * @see android.widget.ScrollBarDrawable - */ - protected int computeVerticalScrollOffset() { - return mScrollY; - } - - /** - * <p>Compute the vertical extent of the horizontal scrollbar's thumb - * within the vertical range. This value is used to compute the length - * of the thumb within the scrollbar's track.</p> - * - * <p>The range is expressed in arbitrary units that must be the same as the - * units used by {@link #computeHorizontalScrollRange()} and - * {@link #computeVerticalScrollOffset()}.</p> - * - * <p>The default extent is the drawing height of this view.</p> - * - * @return the vertical extent of the scrollbar's thumb - * - * @see #computeVerticalScrollRange() - * @see #computeVerticalScrollOffset() - * @see android.widget.ScrollBarDrawable - */ - protected int computeVerticalScrollExtent() { - return getHeight(); - } - - /** - * <p>Request the drawing of the horizontal and the vertical scrollbar. The - * scrollbars are painted only if they have been awakened first.</p> - * - * @param canvas the canvas on which to draw the scrollbars - */ - private void onDrawScrollBars(Canvas canvas) { - // scrollbars are drawn only when the animation is running - final ScrollabilityCache cache = mScrollCache; - if (cache != null) { - final int viewFlags = mViewFlags; - - final boolean drawHorizontalScrollBar = - (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; - final boolean drawVerticalScrollBar = - (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL - && !isVerticalScrollBarHidden(); - - if (drawVerticalScrollBar || drawHorizontalScrollBar) { - final int width = mRight - mLeft; - final int height = mBottom - mTop; - - final ScrollBarDrawable scrollBar = cache.scrollBar; - int size = scrollBar.getSize(false); - if (size <= 0) { - size = cache.scrollBarSize; - } - - if (drawHorizontalScrollBar) { - onDrawHorizontalScrollBar(canvas, scrollBar, width, height, size); - } - - if (drawVerticalScrollBar) { - onDrawVerticalScrollBar(canvas, scrollBar, width, height, size); - } - } - } - } - - /** - * Override this if the vertical scrollbar needs to be hidden in a subclass, like when - * FastScroller is visible. - * @return whether to temporarily hide the vertical scrollbar - * @hide - */ - protected boolean isVerticalScrollBarHidden() { - return false; - } - - /** - * <p>Draw the horizontal scrollbar if - * {@link #isHorizontalScrollBarEnabled()} returns true.</p> - * - * <p>The length of the scrollbar and its thumb is computed according to the - * values returned by {@link #computeHorizontalScrollRange()}, - * {@link #computeHorizontalScrollExtent()} and - * {@link #computeHorizontalScrollOffset()}. Refer to - * {@link android.widget.ScrollBarDrawable} for more information about how - * these values relate to each other.</p> - * - * @param canvas the canvas on which to draw the scrollbar - * @param scrollBar the scrollbar's drawable - * @param width the width of the drawing surface - * @param height the height of the drawing surface - * @param size the size of the scrollbar - * - * @see #isHorizontalScrollBarEnabled() - * @see #computeHorizontalScrollRange() - * @see #computeHorizontalScrollExtent() - * @see #computeHorizontalScrollOffset() - * @see android.widget.ScrollBarDrawable - */ - private void onDrawHorizontalScrollBar(Canvas canvas, ScrollBarDrawable scrollBar, int width, - int height, int size) { - - final int viewFlags = mViewFlags; - final int scrollX = mScrollX; - final int scrollY = mScrollY; - final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; - final int top = scrollY + height - size - (mUserPaddingBottom & inside); - - final int verticalScrollBarGap = - (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL ? - getVerticalScrollbarWidth() : 0; - - scrollBar.setBounds(scrollX + (mPaddingLeft & inside) + getScrollBarPaddingLeft(), top, - scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap, top + size); - scrollBar.setParameters( - computeHorizontalScrollRange(), - computeHorizontalScrollOffset(), - computeHorizontalScrollExtent(), false); - scrollBar.draw(canvas); - } - - /** - * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()} - * returns true.</p> - * - * <p>The length of the scrollbar and its thumb is computed according to the - * values returned by {@link #computeVerticalScrollRange()}, - * {@link #computeVerticalScrollExtent()} and - * {@link #computeVerticalScrollOffset()}. Refer to - * {@link android.widget.ScrollBarDrawable} for more information about how - * these values relate to each other.</p> - * - * @param canvas the canvas on which to draw the scrollbar - * @param scrollBar the scrollbar's drawable - * @param width the width of the drawing surface - * @param height the height of the drawing surface - * @param size the size of the scrollbar - * - * @see #isVerticalScrollBarEnabled() - * @see #computeVerticalScrollRange() - * @see #computeVerticalScrollExtent() - * @see #computeVerticalScrollOffset() - * @see android.widget.ScrollBarDrawable - */ - private void onDrawVerticalScrollBar(Canvas canvas, ScrollBarDrawable scrollBar, int width, - int height, int size) { - - final int scrollX = mScrollX; - final int scrollY = mScrollY; - final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; - // TODO: Deal with RTL languages to position scrollbar on left - final int left = scrollX + width - size - (mUserPaddingRight & inside); - - scrollBar.setBounds(left, scrollY + (mPaddingTop & inside), - left + size, scrollY + height - (mUserPaddingBottom & inside)); - scrollBar.setParameters( - computeVerticalScrollRange(), - computeVerticalScrollOffset(), - computeVerticalScrollExtent(), true); - scrollBar.draw(canvas); - } - - /** - * Implement this to do your drawing. - * - * @param canvas the canvas on which the background will be drawn - */ - protected void onDraw(Canvas canvas) { - } - - /* - * Caller is responsible for calling requestLayout if necessary. - * (This allows addViewInLayout to not request a new layout.) - */ - void assignParent(ViewParent parent) { - if (mParent == null) { - mParent = parent; - } else if (parent == null) { - mParent = null; - } else { - throw new RuntimeException("view " + this + " being added, but" - + " it already has a parent"); - } - } - - /** - * This is called when the view is attached to a window. At this point it - * has a Surface and will start drawing. Note that this function is - * guaranteed to be called before {@link #onDraw}, however it may be called - * any time before the first onDraw -- including before or after - * {@link #onMeasure}. - * - * @see #onDetachedFromWindow() - */ - protected void onAttachedToWindow() { - if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) { - mParent.requestTransparentRegion(this); - } - } - - /** - * This is called when the view is detached from a window. At this point it - * no longer has a surface for drawing. - * - * @see #onAttachedToWindow() - */ - protected void onDetachedFromWindow() { - if (mPendingCheckForLongPress != null) { - removeCallbacks(mPendingCheckForLongPress); - } - destroyDrawingCache(); - } - - /** - * @return The number of times this view has been attached to a window - */ - protected int getWindowAttachCount() { - return mWindowAttachCount; - } - - /** - * Retrieve a unique token identifying the window this view is attached to. - * @return Return the window's token for use in - * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}. - */ - public IBinder getWindowToken() { - return mAttachInfo != null ? mAttachInfo.mWindowToken : null; - } - - /** - * Retrieve a unique token identifying the top-level "real" window of - * the window that this view is attached to. That is, this is like - * {@link #getWindowToken}, except if the window this view in is a panel - * window (attached to another containing window), then the token of - * the containing window is returned instead. - * - * @return Returns the associated window token, either - * {@link #getWindowToken()} or the containing window's token. - */ - public IBinder getApplicationWindowToken() { - AttachInfo ai = mAttachInfo; - if (ai != null) { - IBinder appWindowToken = ai.mPanelParentWindowToken; - if (appWindowToken == null) { - appWindowToken = ai.mWindowToken; - } - return appWindowToken; - } - return null; - } - - /** - * Retrieve private session object this view hierarchy is using to - * communicate with the window manager. - * @return the session object to communicate with the window manager - */ - /*package*/ IWindowSession getWindowSession() { - return mAttachInfo != null ? mAttachInfo.mSession : null; - } - - /** - * @param info the {@link android.view.View.AttachInfo} to associated with - * this view - */ - void dispatchAttachedToWindow(AttachInfo info, int visibility) { - //System.out.println("Attached! " + this); - mAttachInfo = info; - mWindowAttachCount++; - if (mFloatingTreeObserver != null) { - info.mTreeObserver.merge(mFloatingTreeObserver); - mFloatingTreeObserver = null; - } - if ((mPrivateFlags&SCROLL_CONTAINER) != 0) { - mAttachInfo.mScrollContainers.add(this); - mPrivateFlags |= SCROLL_CONTAINER_ADDED; - } - performCollectViewAttributes(visibility); - onAttachedToWindow(); - int vis = info.mWindowVisibility; - if (vis != GONE) { - onWindowVisibilityChanged(vis); - } - } - - void dispatchDetachedFromWindow() { - //System.out.println("Detached! " + this); - AttachInfo info = mAttachInfo; - if (info != null) { - int vis = info.mWindowVisibility; - if (vis != GONE) { - onWindowVisibilityChanged(GONE); - } - } - - onDetachedFromWindow(); - if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) { - mAttachInfo.mScrollContainers.remove(this); - mPrivateFlags &= ~SCROLL_CONTAINER_ADDED; - } - mAttachInfo = null; - } - - /** - * Store this view hierarchy's frozen state into the given container. - * - * @param container The SparseArray in which to save the view's state. - * - * @see #restoreHierarchyState - * @see #dispatchSaveInstanceState - * @see #onSaveInstanceState - */ - public void saveHierarchyState(SparseArray<Parcelable> container) { - dispatchSaveInstanceState(container); - } - - /** - * Called by {@link #saveHierarchyState} to store the state for this view and its children. - * May be overridden to modify how freezing happens to a view's children; for example, some - * views may want to not store state for their children. - * - * @param container The SparseArray in which to save the view's state. - * - * @see #dispatchRestoreInstanceState - * @see #saveHierarchyState - * @see #onSaveInstanceState - */ - protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { - if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) { - mPrivateFlags &= ~SAVE_STATE_CALLED; - Parcelable state = onSaveInstanceState(); - if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) { - throw new IllegalStateException( - "Derived class did not call super.onSaveInstanceState()"); - } - if (state != null) { - // Log.i("View", "Freezing #" + Integer.toHexString(mID) - // + ": " + state); - container.put(mID, state); - } - } - } - - /** - * Hook allowing a view to generate a representation of its internal state - * that can later be used to create a new instance with that same state. - * This state should only contain information that is not persistent or can - * not be reconstructed later. For example, you will never store your - * current position on screen because that will be computed again when a - * new instance of the view is placed in its view hierarchy. - * <p> - * Some examples of things you may store here: the current cursor position - * in a text view (but usually not the text itself since that is stored in a - * content provider or other persistent storage), the currently selected - * item in a list view. - * - * @return Returns a Parcelable object containing the view's current dynamic - * state, or null if there is nothing interesting to save. The - * default implementation returns null. - * @see #onRestoreInstanceState - * @see #saveHierarchyState - * @see #dispatchSaveInstanceState - * @see #setSaveEnabled(boolean) - */ - protected Parcelable onSaveInstanceState() { - mPrivateFlags |= SAVE_STATE_CALLED; - return BaseSavedState.EMPTY_STATE; - } - - /** - * Restore this view hierarchy's frozen state from the given container. - * - * @param container The SparseArray which holds previously frozen states. - * - * @see #saveHierarchyState - * @see #dispatchRestoreInstanceState - * @see #onRestoreInstanceState - */ - public void restoreHierarchyState(SparseArray<Parcelable> container) { - dispatchRestoreInstanceState(container); - } - - /** - * Called by {@link #restoreHierarchyState} to retrieve the state for this view and its - * children. May be overridden to modify how restoreing happens to a view's children; for - * example, some views may want to not store state for their children. - * - * @param container The SparseArray which holds previously saved state. - * - * @see #dispatchSaveInstanceState - * @see #restoreHierarchyState - * @see #onRestoreInstanceState - */ - protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { - if (mID != NO_ID) { - Parcelable state = container.get(mID); - if (state != null) { - // Log.i("View", "Restoreing #" + Integer.toHexString(mID) - // + ": " + state); - mPrivateFlags &= ~SAVE_STATE_CALLED; - onRestoreInstanceState(state); - if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) { - throw new IllegalStateException( - "Derived class did not call super.onRestoreInstanceState()"); - } - } - } - } - - /** - * Hook allowing a view to re-apply a representation of its internal state that had previously - * been generated by {@link #onSaveInstanceState}. This function will never be called with a - * null state. - * - * @param state The frozen state that had previously been returned by - * {@link #onSaveInstanceState}. - * - * @see #onSaveInstanceState - * @see #restoreHierarchyState - * @see #dispatchRestoreInstanceState - */ - protected void onRestoreInstanceState(Parcelable state) { - mPrivateFlags |= SAVE_STATE_CALLED; - if (state != BaseSavedState.EMPTY_STATE && state != null) { - throw new IllegalArgumentException("Wrong state class -- expecting View State"); - } - } - - /** - * <p>Return the time at which the drawing of the view hierarchy started.</p> - * - * @return the drawing start time in milliseconds - */ - public long getDrawingTime() { - return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0; - } - - /** - * <p>Enables or disables the duplication of the parent's state into this view. When - * duplication is enabled, this view gets its drawable state from its parent rather - * than from its own internal properties.</p> - * - * <p>Note: in the current implementation, setting this property to true after the - * view was added to a ViewGroup might have no effect at all. This property should - * always be used from XML or set to true before adding this view to a ViewGroup.</p> - * - * <p>Note: if this view's parent addStateFromChildren property is enabled and this - * property is enabled, an exception will be thrown.</p> - * - * @param enabled True to enable duplication of the parent's drawable state, false - * to disable it. - * - * @see #getDrawableState() - * @see #isDuplicateParentStateEnabled() - */ - public void setDuplicateParentStateEnabled(boolean enabled) { - setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE); - } - - /** - * <p>Indicates whether this duplicates its drawable state from its parent.</p> - * - * @return True if this view's drawable state is duplicated from the parent, - * false otherwise - * - * @see #getDrawableState() - * @see #setDuplicateParentStateEnabled(boolean) - */ - public boolean isDuplicateParentStateEnabled() { - return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE; - } - - /** - * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call - * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a - * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when - * the cache is enabled. To benefit from the cache, you must request the drawing cache by - * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not - * null.</p> - * - * @param enabled true to enable the drawing cache, false otherwise - * - * @see #isDrawingCacheEnabled() - * @see #getDrawingCache() - * @see #buildDrawingCache() - */ - public void setDrawingCacheEnabled(boolean enabled) { - setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED); - } - - /** - * <p>Indicates whether the drawing cache is enabled for this view.</p> - * - * @return true if the drawing cache is enabled - * - * @see #setDrawingCacheEnabled(boolean) - * @see #getDrawingCache() - */ - @ViewDebug.ExportedProperty - public boolean isDrawingCacheEnabled() { - return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED; - } - - /** - * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap - * is null when caching is disabled. If caching is enabled and the cache is not ready, - * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not - * draw from the cache when the cache is enabled. To benefit from the cache, you must - * request the drawing cache by calling this method and draw it on screen if the - * returned bitmap is not null.</p> - * - * @return a bitmap representing this view or null if cache is disabled - * - * @see #setDrawingCacheEnabled(boolean) - * @see #isDrawingCacheEnabled() - * @see #buildDrawingCache() - * @see #destroyDrawingCache() - */ - public Bitmap getDrawingCache() { - if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) { - return null; - } - if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED && - ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mDrawingCache == null)) { - buildDrawingCache(); - } - return mDrawingCache; - } - - /** - * <p>Frees the resources used by the drawing cache. If you call - * {@link #buildDrawingCache()} manually without calling - * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you - * should cleanup the cache with this method afterwards.</p> - * - * @see #setDrawingCacheEnabled(boolean) - * @see #buildDrawingCache() - * @see #getDrawingCache() - */ - public void destroyDrawingCache() { - if (mDrawingCache != null) { - mDrawingCache.recycle(); - mDrawingCache = null; - } - } - - /** - * Setting a solid background color for the drawing cache's bitmaps will improve - * perfromance and memory usage. Note, though that this should only be used if this - * view will always be drawn on top of a solid color. - * - * @param color The background color to use for the drawing cache's bitmap - * - * @see #setDrawingCacheEnabled(boolean) - * @see #buildDrawingCache() - * @see #getDrawingCache() - */ - public void setDrawingCacheBackgroundColor(int color) { - mDrawingCacheBackgroundColor = color; - } - - /** - * @see #setDrawingCacheBackgroundColor(int) - * - * @return The background color to used for the drawing cache's bitmap - */ - public int getDrawingCacheBackgroundColor() { - return mDrawingCacheBackgroundColor; - } - - /** - * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p> - * - * <p>If you call {@link #buildDrawingCache()} manually without calling - * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you - * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p> - * - * @see #getDrawingCache() - * @see #destroyDrawingCache() - */ - public void buildDrawingCache() { - if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mDrawingCache == null) { - if (ViewDebug.TRACE_HIERARCHY) { - ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE); - } - if (ViewRoot.PROFILE_DRAWING) { - EventLog.writeEvent(60002, hashCode()); - } - - final int width = mRight - mLeft; - final int height = mBottom - mTop; - - final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; - final boolean opaque = drawingCacheBackgroundColor != 0 || - (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE); - - if (width <= 0 || height <= 0 || - (width * height * (opaque ? 2 : 4) >= // Projected bitmap size in bytes - ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) { - if (mDrawingCache != null) { - mDrawingCache.recycle(); - } - mDrawingCache = null; - return; - } - - boolean clear = true; - Bitmap bitmap = mDrawingCache; - - if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { - - Bitmap.Config quality; - if (!opaque) { - switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { - case DRAWING_CACHE_QUALITY_AUTO: - quality = Bitmap.Config.ARGB_8888; - break; - case DRAWING_CACHE_QUALITY_LOW: - quality = Bitmap.Config.ARGB_4444; - break; - case DRAWING_CACHE_QUALITY_HIGH: - quality = Bitmap.Config.ARGB_8888; - break; - default: - quality = Bitmap.Config.ARGB_8888; - break; - } - } else { - quality = Bitmap.Config.RGB_565; - } - - // Try to cleanup memory - if (mDrawingCache != null) { - mDrawingCache.recycle(); - } - - try { - mDrawingCache = bitmap = Bitmap.createBitmap(width, height, quality); - } catch (OutOfMemoryError e) { - // If there is not enough memory to create the bitmap cache, just - // ignore the issue as bitmap caches are not required to draw the - // view hierarchy - mDrawingCache = null; - return; - } - - clear = drawingCacheBackgroundColor != 0; - } - - Canvas canvas; - final AttachInfo attachInfo = mAttachInfo; - if (attachInfo != null) { - canvas = attachInfo.mCanvas; - if (canvas == null) { - canvas = new Canvas(); - } - canvas.setBitmap(bitmap); - // Temporarily clobber the cached Canvas in case one of our children - // is also using a drawing cache. Without this, the children would - // steal the canvas by attaching their own bitmap to it and bad, bad - // thing would happen (invisible views, corrupted drawings, etc.) - attachInfo.mCanvas = null; - } else { - // This case should hopefully never or seldom happen - canvas = new Canvas(bitmap); - } - - if (clear) { - bitmap.eraseColor(drawingCacheBackgroundColor); - } - - computeScroll(); - final int restoreCount = canvas.save(); - canvas.translate(-mScrollX, -mScrollY); - - mPrivateFlags |= DRAWN; - - // Fast path for layouts with no backgrounds - if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { - if (ViewDebug.TRACE_HIERARCHY) { - ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); - } - dispatchDraw(canvas); - } else { - draw(canvas); - } - - canvas.restoreToCount(restoreCount); - - if (attachInfo != null) { - // Restore the cached Canvas for our siblings - attachInfo.mCanvas = canvas; - } - mPrivateFlags |= DRAWING_CACHE_VALID; - } - } - - /** - * Indicates whether this View is currently in edit mode. A View is usually - * in edit mode when displayed within a developer tool. For instance, if - * this View is being drawn by a visual user interface builder, this method - * should return true. - * - * Subclasses should check the return value of this method to provide - * different behaviors if their normal behavior might interfere with the - * host environment. For instance: the class spawns a thread in its - * constructor, the drawing code relies on device-specific features, etc. - * - * This method is usually checked in the drawing code of custom widgets. - * - * @return True if this View is in edit mode, false otherwise. - */ - public boolean isInEditMode() { - return false; - } - - /** - * If the View draws content inside its padding and enables fading edges, - * it needs to support padding offsets. Padding offsets are added to the - * fading edges to extend the length of the fade so that it covers pixels - * drawn inside the padding. - * - * Subclasses of this class should override this method if they need - * to draw content inside the padding. - * - * @return True if padding offset must be applied, false otherwise. - * - * @see #getLeftPaddingOffset() - * @see #getRightPaddingOffset() - * @see #getTopPaddingOffset() - * @see #getBottomPaddingOffset() - * - * @since CURRENT - */ - protected boolean isPaddingOffsetRequired() { - return false; - } - - /** - * Amount by which to extend the left fading region. Called only when - * {@link #isPaddingOffsetRequired()} returns true. - * - * @return The left padding offset in pixels. - * - * @see #isPaddingOffsetRequired() - * - * @since CURRENT - */ - protected int getLeftPaddingOffset() { - return 0; - } - - /** - * Amount by which to extend the right fading region. Called only when - * {@link #isPaddingOffsetRequired()} returns true. - * - * @return The right padding offset in pixels. - * - * @see #isPaddingOffsetRequired() - * - * @since CURRENT - */ - protected int getRightPaddingOffset() { - return 0; - } - - /** - * Amount by which to extend the top fading region. Called only when - * {@link #isPaddingOffsetRequired()} returns true. - * - * @return The top padding offset in pixels. - * - * @see #isPaddingOffsetRequired() - * - * @since CURRENT - */ - protected int getTopPaddingOffset() { - return 0; - } - - /** - * Amount by which to extend the bottom fading region. Called only when - * {@link #isPaddingOffsetRequired()} returns true. - * - * @return The bottom padding offset in pixels. - * - * @see #isPaddingOffsetRequired() - * - * @since CURRENT - */ - protected int getBottomPaddingOffset() { - return 0; - } - - /** - * Manually render this view (and all of its children) to the given Canvas. - * The view must have already done a full layout before this function is - * called. When implementing a view, do not override this method; instead, - * you should implement {@link #onDraw}. - * - * @param canvas The Canvas to which the View is rendered. - */ - public void draw(Canvas canvas) { - if (ViewDebug.TRACE_HIERARCHY) { - ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); - } - - mPrivateFlags |= DRAWN; - - /* - * Draw traversal performs several drawing steps which must be executed - * in the appropriate order: - * - * 1. Draw the background - * 2. If necessary, save the canvas' layers to prepare for fading - * 3. Draw view's content - * 4. Draw children - * 5. If necessary, draw the fading edges and restore layers - * 6. Draw decorations (scrollbars for instance) - */ - - // Step 1, draw the background, if needed - int saveCount; - - final Drawable background = mBGDrawable; - if (background != null) { - final int scrollX = mScrollX; - final int scrollY = mScrollY; - - if (mBackgroundSizeChanged) { - background.setBounds(0, 0, mRight - mLeft, mBottom - mTop); - mBackgroundSizeChanged = false; - } - - if ((scrollX | scrollY) == 0) { - background.draw(canvas); - } else { - canvas.translate(scrollX, scrollY); - background.draw(canvas); - canvas.translate(-scrollX, -scrollY); - } - } - - // skip step 2 & 5 if possible (common case) - final int viewFlags = mViewFlags; - boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; - boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; - if (!verticalEdges && !horizontalEdges) { - // Step 3, draw the content - onDraw(canvas); - - // Step 4, draw the children - dispatchDraw(canvas); - - // Step 6, draw decorations (scrollbars) - onDrawScrollBars(canvas); - - // we're done... - return; - } - - /* - * Here we do the full fledged routine... - * (this is an uncommon case where speed matters less, - * this is why we repeat some of the tests that have been - * done above) - */ - - boolean drawTop = false; - boolean drawBottom = false; - boolean drawLeft = false; - boolean drawRight = false; - - float topFadeStrength = 0.0f; - float bottomFadeStrength = 0.0f; - float leftFadeStrength = 0.0f; - float rightFadeStrength = 0.0f; - - // Step 2, save the canvas' layers - int paddingLeft = mPaddingLeft; - int paddingTop = mPaddingTop; - - final boolean offsetRequired = isPaddingOffsetRequired(); - if (offsetRequired) { - paddingLeft += getLeftPaddingOffset(); - paddingTop += getTopPaddingOffset(); - } - - int left = mScrollX + paddingLeft; - int right = left + mRight - mLeft - mPaddingRight - paddingLeft; - int top = mScrollY + paddingTop; - int bottom = top + mBottom - mTop - mPaddingBottom - paddingTop; - - if (offsetRequired) { - right += getRightPaddingOffset(); - bottom += getBottomPaddingOffset(); - } - - final ScrollabilityCache scrollabilityCache = mScrollCache; - int length = scrollabilityCache.fadingEdgeLength; - - // clip the fade length if top and bottom fades overlap - // overlapping fades produce odd-looking artifacts - if (verticalEdges && (top + length > bottom - length)) { - length = (bottom - top) / 2; - } - - // also clip horizontal fades if necessary - if (horizontalEdges && (left + length > right - length)) { - length = (right - left) / 2; - } - - if (verticalEdges) { - topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength())); - drawTop = topFadeStrength >= 0.0f; - bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength())); - drawBottom = bottomFadeStrength >= 0.0f; - } - - if (horizontalEdges) { - leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength())); - drawLeft = leftFadeStrength >= 0.0f; - rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength())); - drawRight = rightFadeStrength >= 0.0f; - } - - saveCount = canvas.getSaveCount(); - - int solidColor = getSolidColor(); - if (solidColor == 0) { - final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; - - if (drawTop) { - canvas.saveLayer(left, top, right, top + length, null, flags); - } - - if (drawBottom) { - canvas.saveLayer(left, bottom - length, right, bottom, null, flags); - } - - if (drawLeft) { - canvas.saveLayer(left, top, left + length, bottom, null, flags); - } - - if (drawRight) { - canvas.saveLayer(right - length, top, right, bottom, null, flags); - } - } else { - scrollabilityCache.setFadeColor(solidColor); - } - - // Step 3, draw the content - onDraw(canvas); - - // Step 4, draw the children - dispatchDraw(canvas); - - // Step 5, draw the fade effect and restore layers - final Paint p = scrollabilityCache.paint; - final Matrix matrix = scrollabilityCache.matrix; - final Shader fade = scrollabilityCache.shader; - final float fadeHeight = scrollabilityCache.fadingEdgeLength; - - if (drawTop) { - matrix.setScale(1, fadeHeight * topFadeStrength); - matrix.postTranslate(left, top); - fade.setLocalMatrix(matrix); - canvas.drawRect(left, top, right, top + length, p); - } - - if (drawBottom) { - matrix.setScale(1, fadeHeight * bottomFadeStrength); - matrix.postRotate(180); - matrix.postTranslate(left, bottom); - fade.setLocalMatrix(matrix); - canvas.drawRect(left, bottom - length, right, bottom, p); - } - - if (drawLeft) { - matrix.setScale(1, fadeHeight * leftFadeStrength); - matrix.postRotate(-90); - matrix.postTranslate(left, top); - fade.setLocalMatrix(matrix); - canvas.drawRect(left, top, left + length, bottom, p); - } - - if (drawRight) { - matrix.setScale(1, fadeHeight * rightFadeStrength); - matrix.postRotate(90); - matrix.postTranslate(right, top); - fade.setLocalMatrix(matrix); - canvas.drawRect(right - length, top, right, bottom, p); - } - - canvas.restoreToCount(saveCount); - - // Step 6, draw decorations (scrollbars) - onDrawScrollBars(canvas); - } - - /** - * Override this if your view is known to always be drawn on top of a solid color background, - * and needs to draw fading edges. Returning a non-zero color enables the view system to - * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha - * should be set to 0xFF. - * - * @see #setVerticalFadingEdgeEnabled - * @see #setHorizontalFadingEdgeEnabled - * - * @return The known solid color background for this view, or 0 if the color may vary - */ - public int getSolidColor() { - return 0; - } - - /** - * Build a human readable string representation of the specified view flags. - * - * @param flags the view flags to convert to a string - * @return a String representing the supplied flags - */ - private static String printFlags(int flags) { - String output = ""; - int numFlags = 0; - if ((flags & FOCUSABLE_MASK) == FOCUSABLE) { - output += "TAKES_FOCUS"; - numFlags++; - } - - switch (flags & VISIBILITY_MASK) { - case INVISIBLE: - if (numFlags > 0) { - output += " "; - } - output += "INVISIBLE"; - // USELESS HERE numFlags++; - break; - case GONE: - if (numFlags > 0) { - output += " "; - } - output += "GONE"; - // USELESS HERE numFlags++; - break; - default: - break; - } - return output; - } - - /** - * Build a human readable string representation of the specified private - * view flags. - * - * @param privateFlags the private view flags to convert to a string - * @return a String representing the supplied flags - */ - private static String printPrivateFlags(int privateFlags) { - String output = ""; - int numFlags = 0; - - if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) { - output += "WANTS_FOCUS"; - numFlags++; - } - - if ((privateFlags & FOCUSED) == FOCUSED) { - if (numFlags > 0) { - output += " "; - } - output += "FOCUSED"; - numFlags++; - } - - if ((privateFlags & SELECTED) == SELECTED) { - if (numFlags > 0) { - output += " "; - } - output += "SELECTED"; - numFlags++; - } - - if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) { - if (numFlags > 0) { - output += " "; - } - output += "IS_ROOT_NAMESPACE"; - numFlags++; - } - - if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) { - if (numFlags > 0) { - output += " "; - } - output += "HAS_BOUNDS"; - numFlags++; - } - - if ((privateFlags & DRAWN) == DRAWN) { - if (numFlags > 0) { - output += " "; - } - output += "DRAWN"; - // USELESS HERE numFlags++; - } - return output; - } - - /** - * <p>Indicates whether or not this view's layout will be requested during - * the next hierarchy layout pass.</p> - * - * @return true if the layout will be forced during next layout pass - */ - public boolean isLayoutRequested() { - return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT; - } - - /** - * Assign a size and position to a view and all of its - * descendants - * - * <p>This is the second phase of the layout mechanism. - * (The first is measuring). In this phase, each parent calls - * layout on all of its children to position them. - * This is typically done using the child measurements - * that were stored in the measure pass(). - * - * Derived classes with children should override - * onLayout. In that method, they should - * call layout on each of their their children. - * - * @param l Left position, relative to parent - * @param t Top position, relative to parent - * @param r Right position, relative to parent - * @param b Bottom position, relative to parent - */ - public final void layout(int l, int t, int r, int b) { - boolean changed = setFrame(l, t, r, b); - if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) { - if (ViewDebug.TRACE_HIERARCHY) { - ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT); - } - - onLayout(changed, l, t, r, b); - mPrivateFlags &= ~LAYOUT_REQUIRED; - } - mPrivateFlags &= ~FORCE_LAYOUT; - } - - /** - * Called from layout when this view should - * assign a size and position to each of its children. - * - * Derived classes with children should override - * this method and call layout on each of - * their their children. - * @param changed This is a new size or position for this view - * @param left Left position, relative to parent - * @param top Top position, relative to parent - * @param right Right position, relative to parent - * @param bottom Bottom position, relative to parent - */ - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - } - - /** - * Assign a size and position to this view. - * - * This is called from layout. - * - * @param left Left position, relative to parent - * @param top Top position, relative to parent - * @param right Right position, relative to parent - * @param bottom Bottom position, relative to parent - * @return true if the new size and position are different than the - * previous ones - * {@hide} - */ - protected boolean setFrame(int left, int top, int right, int bottom) { - boolean changed = false; - - if (DBG) { - System.out.println(this + " View.setFrame(" + left + "," + top + "," - + right + "," + bottom + ")"); - } - - if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) { - changed = true; - - // Remember our drawn bit - int drawn = mPrivateFlags & DRAWN; - - // Invalidate our old position - invalidate(); - - - int oldWidth = mRight - mLeft; - int oldHeight = mBottom - mTop; - - mLeft = left; - mTop = top; - mRight = right; - mBottom = bottom; - - mPrivateFlags |= HAS_BOUNDS; - - int newWidth = right - left; - int newHeight = bottom - top; - - if (newWidth != oldWidth || newHeight != oldHeight) { - onSizeChanged(newWidth, newHeight, oldWidth, oldHeight); - } - - if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) { - // If we are visible, force the DRAWN bit to on so that - // this invalidate will go through (at least to our parent). - // This is because someone may have invalidated this view - // before this call to setFrame came in, therby clearing - // the DRAWN bit. - mPrivateFlags |= DRAWN; - invalidate(); - } - - // Reset drawn bit to original value (invalidate turns it off) - mPrivateFlags |= drawn; - - mBackgroundSizeChanged = true; - } - return changed; - } - - /** - * Finalize inflating a view from XML. This is called as the last phase - * of inflation, after all child views have been added. - * - * <p>Even if the subclass overrides onFinishInflate, they should always be - * sure to call the super method, so that we get called. - */ - protected void onFinishInflate() { - } - - /** - * Returns the resources associated with this view. - * - * @return Resources object. - */ - public Resources getResources() { - return mResources; - } - - /** - * Invalidates the specified Drawable. - * - * @param drawable the drawable to invalidate - */ - public void invalidateDrawable(Drawable drawable) { - if (verifyDrawable(drawable)) { - final Rect dirty = drawable.getBounds(); - final int scrollX = mScrollX; - final int scrollY = mScrollY; - - invalidate(dirty.left + scrollX, dirty.top + scrollY, - dirty.right + scrollX, dirty.bottom + scrollY); - } - } - - /** - * Schedules an action on a drawable to occur at a specified time. - * - * @param who the recipient of the action - * @param what the action to run on the drawable - * @param when the time at which the action must occur. Uses the - * {@link SystemClock#uptimeMillis} timebase. - */ - public void scheduleDrawable(Drawable who, Runnable what, long when) { - if (verifyDrawable(who) && what != null && mAttachInfo != null) { - mAttachInfo.mHandler.postAtTime(what, who, when); - } - } - - /** - * Cancels a scheduled action on a drawable. - * - * @param who the recipient of the action - * @param what the action to cancel - */ - public void unscheduleDrawable(Drawable who, Runnable what) { - if (verifyDrawable(who) && what != null && mAttachInfo != null) { - mAttachInfo.mHandler.removeCallbacks(what, who); - } - } - - /** - * Unschedule any events associated with the given Drawable. This can be - * used when selecting a new Drawable into a view, so that the previous - * one is completely unscheduled. - * - * @param who The Drawable to unschedule. - * - * @see #drawableStateChanged - */ - public void unscheduleDrawable(Drawable who) { - if (mAttachInfo != null) { - mAttachInfo.mHandler.removeCallbacksAndMessages(who); - } - } - - /** - * If your view subclass is displaying its own Drawable objects, it should - * override this function and return true for any Drawable it is - * displaying. This allows animations for those drawables to be - * scheduled. - * - * <p>Be sure to call through to the super class when overriding this - * function. - * - * @param who The Drawable to verify. Return true if it is one you are - * displaying, else return the result of calling through to the - * super class. - * - * @return boolean If true than the Drawable is being displayed in the - * view; else false and it is not allowed to animate. - * - * @see #unscheduleDrawable - * @see #drawableStateChanged - */ - protected boolean verifyDrawable(Drawable who) { - return who == mBGDrawable; - } - - /** - * This function is called whenever the state of the view changes in such - * a way that it impacts the state of drawables being shown. - * - * <p>Be sure to call through to the superclass when overriding this - * function. - * - * @see Drawable#setState - */ - protected void drawableStateChanged() { - Drawable d = mBGDrawable; - if (d != null && d.isStateful()) { - d.setState(getDrawableState()); - } - } - - /** - * Call this to force a view to update its drawable state. This will cause - * drawableStateChanged to be called on this view. Views that are interested - * in the new state should call getDrawableState. - * - * @see #drawableStateChanged - * @see #getDrawableState - */ - public void refreshDrawableState() { - mPrivateFlags |= DRAWABLE_STATE_DIRTY; - drawableStateChanged(); - - ViewParent parent = mParent; - if (parent != null) { - parent.childDrawableStateChanged(this); - } - } - - /** - * Return an array of resource IDs of the drawable states representing the - * current state of the view. - * - * @return The current drawable state - * - * @see Drawable#setState - * @see #drawableStateChanged - * @see #onCreateDrawableState - */ - public final int[] getDrawableState() { - if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) { - return mDrawableState; - } else { - mDrawableState = onCreateDrawableState(0); - mPrivateFlags &= ~DRAWABLE_STATE_DIRTY; - return mDrawableState; - } - } - - /** - * Generate the new {@link android.graphics.drawable.Drawable} state for - * this view. This is called by the view - * system when the cached Drawable state is determined to be invalid. To - * retrieve the current state, you should use {@link #getDrawableState}. - * - * @param extraSpace if non-zero, this is the number of extra entries you - * would like in the returned array in which you can place your own - * states. - * - * @return Returns an array holding the current {@link Drawable} state of - * the view. - * - * @see #mergeDrawableStates - */ - protected int[] onCreateDrawableState(int extraSpace) { - if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE && - mParent instanceof View) { - return ((View) mParent).onCreateDrawableState(extraSpace); - } - - int[] drawableState; - - int privateFlags = mPrivateFlags; - - int viewStateIndex = (((privateFlags & PRESSED) != 0) ? 1 : 0); - - viewStateIndex = (viewStateIndex << 1) - + (((mViewFlags & ENABLED_MASK) == ENABLED) ? 1 : 0); - - viewStateIndex = (viewStateIndex << 1) + (isFocused() ? 1 : 0); - - viewStateIndex = (viewStateIndex << 1) - + (((privateFlags & SELECTED) != 0) ? 1 : 0); - - final boolean hasWindowFocus = hasWindowFocus(); - viewStateIndex = (viewStateIndex << 1) + (hasWindowFocus ? 1 : 0); - - drawableState = VIEW_STATE_SETS[viewStateIndex]; - - //noinspection ConstantIfStatement - if (false) { - Log.i("View", "drawableStateIndex=" + viewStateIndex); - Log.i("View", toString() - + " pressed=" + ((privateFlags & PRESSED) != 0) - + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED) - + " fo=" + hasFocus() - + " sl=" + ((privateFlags & SELECTED) != 0) - + " wf=" + hasWindowFocus - + ": " + Arrays.toString(drawableState)); - } - - if (extraSpace == 0) { - return drawableState; - } - - final int[] fullState; - if (drawableState != null) { - fullState = new int[drawableState.length + extraSpace]; - System.arraycopy(drawableState, 0, fullState, 0, drawableState.length); - } else { - fullState = new int[extraSpace]; - } - - return fullState; - } - - /** - * Merge your own state values in <var>additionalState</var> into the base - * state values <var>baseState</var> that were returned by - * {@link #onCreateDrawableState}. - * - * @param baseState The base state values returned by - * {@link #onCreateDrawableState}, which will be modified to also hold your - * own additional state values. - * - * @param additionalState The additional state values you would like - * added to <var>baseState</var>; this array is not modified. - * - * @return As a convenience, the <var>baseState</var> array you originally - * passed into the function is returned. - * - * @see #onCreateDrawableState - */ - protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) { - final int N = baseState.length; - int i = N - 1; - while (i >= 0 && baseState[i] == 0) { - i--; - } - System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length); - return baseState; - } - - /** - * Sets the background color for this view. - * @param color the color of the background - */ - public void setBackgroundColor(int color) { - setBackgroundDrawable(new ColorDrawable(color)); - } - - /** - * Set the background to a given resource. The resource should refer to - * a Drawable object. - * @param resid The identifier of the resource. - * @attr ref android.R.styleable#View_background - */ - public void setBackgroundResource(int resid) { - if (resid != 0 && resid == mBackgroundResource) { - return; - } - - Drawable d= null; - if (resid != 0) { - d = mResources.getDrawable(resid); - } - setBackgroundDrawable(d); - - mBackgroundResource = resid; - } - - /** - * Set the background to a given Drawable, or remove the background. If the - * background has padding, this View's padding is set to the background's - * padding. However, when a background is removed, this View's padding isn't - * touched. If setting the padding is desired, please use - * {@link #setPadding(int, int, int, int)}. - * - * @param d The Drawable to use as the background, or null to remove the - * background - */ - public void setBackgroundDrawable(Drawable d) { - boolean requestLayout = false; - - mBackgroundResource = 0; - - /* - * Regardless of whether we're setting a new background or not, we want - * to clear the previous drawable. - */ - if (mBGDrawable != null) { - mBGDrawable.setCallback(null); - unscheduleDrawable(mBGDrawable); - } - - if (d != null) { - Rect padding = sThreadLocal.get(); - if (padding == null) { - padding = new Rect(); - sThreadLocal.set(padding); - } - if (d.getPadding(padding)) { - setPadding(padding.left, padding.top, padding.right, padding.bottom); - } - - // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or - // if it has a different minimum size, we should layout again - if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() || - mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) { - requestLayout = true; - } - - d.setCallback(this); - if (d.isStateful()) { - d.setState(getDrawableState()); - } - d.setVisible(getVisibility() == VISIBLE, false); - mBGDrawable = d; - - if ((mPrivateFlags & SKIP_DRAW) != 0) { - mPrivateFlags &= ~SKIP_DRAW; - mPrivateFlags |= ONLY_DRAWS_BACKGROUND; - requestLayout = true; - } - } else { - /* Remove the background */ - mBGDrawable = null; - - if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) { - /* - * This view ONLY drew the background before and we're removing - * the background, so now it won't draw anything - * (hence we SKIP_DRAW) - */ - mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND; - mPrivateFlags |= SKIP_DRAW; - } - - /* - * When the background is set, we try to apply its padding to this - * View. When the background is removed, we don't touch this View's - * padding. This is noted in the Javadocs. Hence, we don't need to - * requestLayout(), the invalidate() below is sufficient. - */ - - // The old background's minimum size could have affected this - // View's layout, so let's requestLayout - requestLayout = true; - } - - if (requestLayout) { - requestLayout(); - } - - mBackgroundSizeChanged = true; - invalidate(); - } - - /** - * Gets the background drawable - * @return The drawable used as the background for this view, if any. - */ - public Drawable getBackground() { - return mBGDrawable; - } - - private int getScrollBarPaddingLeft() { - // TODO: Deal with RTL languages - return 0; - } - - /* - * Returns the pixels occupied by the vertical scrollbar, if not overlaid - */ - private int getScrollBarPaddingRight() { - // TODO: Deal with RTL languages - if ((mViewFlags & SCROLLBARS_VERTICAL) == 0) { - return 0; - } - return (mViewFlags & SCROLLBARS_INSET_MASK) == 0 ? 0 : getVerticalScrollbarWidth(); - } - - /* - * Returns the pixels occupied by the horizontal scrollbar, if not overlaid - */ - private int getScrollBarPaddingBottom() { - if ((mViewFlags & SCROLLBARS_HORIZONTAL) == 0) { - return 0; - } - return (mViewFlags & SCROLLBARS_INSET_MASK) == 0 ? 0 : getHorizontalScrollbarHeight(); - } - - /** - * Sets the padding. The view may add on the space required to display - * the scrollbars, depending on the style and visibility of the scrollbars. - * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop}, - * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different - * from the values set in this call. - * - * @attr ref android.R.styleable#View_padding - * @attr ref android.R.styleable#View_paddingBottom - * @attr ref android.R.styleable#View_paddingLeft - * @attr ref android.R.styleable#View_paddingRight - * @attr ref android.R.styleable#View_paddingTop - * @param left the left padding in pixels - * @param top the top padding in pixels - * @param right the right padding in pixels - * @param bottom the bottom padding in pixels - */ - public void setPadding(int left, int top, int right, int bottom) { - boolean changed = false; - - mUserPaddingRight = right; - mUserPaddingBottom = bottom; - - if (mPaddingLeft != left + getScrollBarPaddingLeft()) { - changed = true; - mPaddingLeft = left; - } - if (mPaddingTop != top) { - changed = true; - mPaddingTop = top; - } - if (mPaddingRight != right + getScrollBarPaddingRight()) { - changed = true; - mPaddingRight = right + getScrollBarPaddingRight(); - } - if (mPaddingBottom != bottom + getScrollBarPaddingBottom()) { - changed = true; - mPaddingBottom = bottom + getScrollBarPaddingBottom(); - } - - if (changed) { - requestLayout(); - } - } - - /** - * Returns the top padding of this view. - * - * @return the top padding in pixels - */ - public int getPaddingTop() { - return mPaddingTop; - } - - /** - * Returns the bottom padding of this view. If there are inset and enabled - * scrollbars, this value may include the space required to display the - * scrollbars as well. - * - * @return the bottom padding in pixels - */ - public int getPaddingBottom() { - return mPaddingBottom; - } - - /** - * Returns the left padding of this view. If there are inset and enabled - * scrollbars, this value may include the space required to display the - * scrollbars as well. - * - * @return the left padding in pixels - */ - public int getPaddingLeft() { - return mPaddingLeft; - } - - /** - * Returns the right padding of this view. If there are inset and enabled - * scrollbars, this value may include the space required to display the - * scrollbars as well. - * - * @return the right padding in pixels - */ - public int getPaddingRight() { - return mPaddingRight; - } - - /** - * 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; - * the selected view is the view that is highlighted. - * - * @param selected true if the view must be selected, false otherwise - */ - public void setSelected(boolean selected) { - if (((mPrivateFlags & SELECTED) != 0) != selected) { - mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0); - invalidate(); - refreshDrawableState(); - dispatchSetSelected(selected); - } - } - - /** - * Dispatch setSelected to all of this View's children. - * - * @see #setSelected(boolean) - * - * @param selected The new selected state - */ - protected void dispatchSetSelected(boolean selected) { - } - - /** - * Indicates the selection state of this view. - * - * @return true if the view is selected, false otherwise - */ - @ViewDebug.ExportedProperty - public boolean isSelected() { - return (mPrivateFlags & SELECTED) != 0; - } - - /** - * Returns the ViewTreeObserver for this view's hierarchy. The view tree - * observer can be used to get notifications when global events, like - * layout, happen. - * - * The returned ViewTreeObserver observer is not guaranteed to remain - * valid for the lifetime of this View. If the caller of this method keeps - * a long-lived reference to ViewTreeObserver, it should always check for - * the return value of {@link ViewTreeObserver#isAlive()}. - * - * @return The ViewTreeObserver for this view's hierarchy. - */ - public ViewTreeObserver getViewTreeObserver() { - if (mAttachInfo != null) { - return mAttachInfo.mTreeObserver; - } - if (mFloatingTreeObserver == null) { - mFloatingTreeObserver = new ViewTreeObserver(); - } - return mFloatingTreeObserver; - } - - /** - * <p>Finds the topmost view in the current view hierarchy.</p> - * - * @return the topmost view containing this view - */ - public View getRootView() { - if (mAttachInfo != null) { - final View v = mAttachInfo.mRootView; - if (v != null) { - return v; - } - } - - View parent = this; - - while (parent.mParent != null && parent.mParent instanceof View) { - parent = (View) parent.mParent; - } - - return parent; - } - - /** - * <p>Computes the coordinates of this view on the screen. The argument - * must be an array of two integers. After the method returns, the array - * contains the x and y location in that order.</p> - * - * @param location an array of two integers in which to hold the coordinates - */ - public void getLocationOnScreen(int[] location) { - getLocationInWindow(location); - - final AttachInfo info = mAttachInfo; - location[0] += info.mWindowLeft; - location[1] += info.mWindowTop; - } - - /** - * <p>Computes the coordinates of this view in its window. The argument - * must be an array of two integers. After the method returns, the array - * contains the x and y location in that order.</p> - * - * @param location an array of two integers in which to hold the coordinates - */ - public void getLocationInWindow(int[] location) { - if (location == null || location.length < 2) { - throw new IllegalArgumentException("location must be an array of " - + "two integers"); - } - - location[0] = mLeft; - location[1] = mTop; - - ViewParent viewParent = mParent; - while (viewParent instanceof View) { - final View view = (View)viewParent; - location[0] += view.mLeft - view.mScrollX; - location[1] += view.mTop - view.mScrollY; - viewParent = view.mParent; - } - - if (viewParent instanceof ViewRoot) { - // *cough* - final ViewRoot vr = (ViewRoot)viewParent; - location[1] -= vr.mCurScrollY; - } - } - - /** - * {@hide} - * @param id the id of the view to be found - * @return the view of the specified id, null if cannot be found - */ - protected View findViewTraversal(int id) { - if (id == mID) { - return this; - } - return null; - } - - /** - * {@hide} - * @param tag the tag of the view to be found - * @return the view of specified tag, null if cannot be found - */ - protected View findViewWithTagTraversal(Object tag) { - if (tag != null && tag.equals(mTag)) { - return this; - } - return null; - } - - /** - * Look for a child view with the given id. If this view has the given - * id, return this view. - * - * @param id The id to search for. - * @return The view that has the given id in the hierarchy or null - */ - public final View findViewById(int id) { - if (id < 0) { - return null; - } - return findViewTraversal(id); - } - - /** - * Look for a child view with the given tag. If this view has the given - * tag, return this view. - * - * @param tag The tag to search for, using "tag.equals(getTag())". - * @return The View that has the given tag in the hierarchy or null - */ - public final View findViewWithTag(Object tag) { - if (tag == null) { - return null; - } - return findViewWithTagTraversal(tag); - } - - /** - * Sets the identifier for this view. The identifier does not have to be - * unique in this view's hierarchy. The identifier should be a positive - * number. - * - * @see #NO_ID - * @see #getId - * @see #findViewById - * - * @param id a number used to identify the view - * - * @attr ref android.R.styleable#View_id - */ - public void setId(int id) { - mID = id; - } - - /** - * {@hide} - * - * @param isRoot true if the view belongs to the root namespace, false - * otherwise - */ - public void setIsRootNamespace(boolean isRoot) { - if (isRoot) { - mPrivateFlags |= IS_ROOT_NAMESPACE; - } else { - mPrivateFlags &= ~IS_ROOT_NAMESPACE; - } - } - - /** - * {@hide} - * - * @return true if the view belongs to the root namespace, false otherwise - */ - public boolean isRootNamespace() { - return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0; - } - - /** - * Returns this view's identifier. - * - * @return a positive integer used to identify the view or {@link #NO_ID} - * if the view has no ID - * - * @see #setId - * @see #findViewById - * @attr ref android.R.styleable#View_id - */ - @ViewDebug.CapturedViewProperty - public int getId() { - return mID; - } - - /** - * Returns this view's tag. - * - * @return the Object stored in this view as a tag - */ - @ViewDebug.ExportedProperty - public Object getTag() { - return mTag; - } - - /** - * Sets the tag associated with this view. A tag can be used to mark - * a view in its hierarchy and does not have to be unique within the - * hierarchy. Tags can also be used to store data within a view without - * resorting to another data structure. - * - * @param tag an Object to tag the view with - */ - public void setTag(final Object tag) { - mTag = tag; - } - - /** - * Prints information about this view in the log output, with the tag - * {@link #VIEW_LOG_TAG}. - * - * @hide - */ - public void debug() { - debug(0); - } - - /** - * Prints information about this view in the log output, with the tag - * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an - * indentation defined by the <code>depth</code>. - * - * @param depth the indentation level - * - * @hide - */ - protected void debug(int depth) { - String output = debugIndent(depth - 1); - - output += "+ " + this; - int id = getId(); - if (id != -1) { - output += " (id=" + id + ")"; - } - Object tag = getTag(); - if (tag != null) { - output += " (tag=" + tag + ")"; - } - Log.d(VIEW_LOG_TAG, output); - - if ((mPrivateFlags & FOCUSED) != 0) { - output = debugIndent(depth) + " FOCUSED"; - Log.d(VIEW_LOG_TAG, output); - } - - output = debugIndent(depth); - output += "frame={" + mLeft + ", " + mTop + ", " + mRight - + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY - + "} "; - Log.d(VIEW_LOG_TAG, output); - - if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0 - || mPaddingBottom != 0) { - output = debugIndent(depth); - output += "padding={" + mPaddingLeft + ", " + mPaddingTop - + ", " + mPaddingRight + ", " + mPaddingBottom + "}"; - Log.d(VIEW_LOG_TAG, output); - } - - output = debugIndent(depth); - output += "mMeasureWidth=" + mMeasuredWidth + - " mMeasureHeight=" + mMeasuredHeight; - Log.d(VIEW_LOG_TAG, output); - - output = debugIndent(depth); - if (mLayoutParams == null) { - output += "BAD! no layout params"; - } else { - output = mLayoutParams.debug(output); - } - Log.d(VIEW_LOG_TAG, output); - - output = debugIndent(depth); - output += "flags={"; - output += View.printFlags(mViewFlags); - output += "}"; - Log.d(VIEW_LOG_TAG, output); - - output = debugIndent(depth); - output += "privateFlags={"; - output += View.printPrivateFlags(mPrivateFlags); - output += "}"; - Log.d(VIEW_LOG_TAG, output); - } - - /** - * Creates an string of whitespaces used for indentation. - * - * @param depth the indentation level - * @return a String containing (depth * 2 + 3) * 2 white spaces - * - * @hide - */ - protected static String debugIndent(int depth) { - StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2); - for (int i = 0; i < (depth * 2) + 3; i++) { - spaces.append(' ').append(' '); - } - return spaces.toString(); - } - - /** - * <p>Return the offset of the widget's text baseline from the widget's top - * boundary. If this widget does not support baseline alignment, this - * method returns -1. </p> - * - * @return the offset of the baseline within the widget's bounds or -1 - * if baseline alignment is not supported - */ - @ViewDebug.ExportedProperty - public int getBaseline() { - return -1; - } - - /** - * Call this when something has changed which has invalidated the - * layout of this view. This will schedule a layout pass of the view - * tree. - */ - public void requestLayout() { - if (ViewDebug.TRACE_HIERARCHY) { - ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT); - } - - mPrivateFlags |= FORCE_LAYOUT; - - if (mParent != null && !mParent.isLayoutRequested()) { - mParent.requestLayout(); - } - } - - /** - * Forces this view to be laid out during the next layout pass. - * This method does not call requestLayout() or forceLayout() - * on the parent. - */ - public void forceLayout() { - mPrivateFlags |= FORCE_LAYOUT; - } - - /** - * <p> - * This is called to find out how big a view should be. The parent - * supplies constraint information in the width and height parameters. - * </p> - * - * <p> - * The actual mesurement work of a view is performed in - * {@link #onMeasure(int, int)}, called by this method. Therefore, only - * {@link #onMeasure(int, int)} can and must be overriden by subclasses. - * </p> - * - * - * @param widthMeasureSpec Horizontal space requirements as imposed by the - * parent - * @param heightMeasureSpec Vertical space requirements as imposed by the - * parent - * - * @see #onMeasure(int, int) - */ - public final void measure(int widthMeasureSpec, int heightMeasureSpec) { - if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT || - widthMeasureSpec != mOldWidthMeasureSpec || - heightMeasureSpec != mOldHeightMeasureSpec) { - - // first clears the measured dimension flag - mPrivateFlags &= ~MEASURED_DIMENSION_SET; - - if (ViewDebug.TRACE_HIERARCHY) { - ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE); - } - - // measure ourselves, this should set the measured dimension flag back - onMeasure(widthMeasureSpec, heightMeasureSpec); - - // flag not set, setMeasuredDimension() was not invoked, we raise - // an exception to warn the developer - if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) { - throw new IllegalStateException("onMeasure() did not set the" - + " measured dimension by calling" - + " setMeasuredDimension()"); - } - - mPrivateFlags |= LAYOUT_REQUIRED; - } - - mOldWidthMeasureSpec = widthMeasureSpec; - mOldHeightMeasureSpec = heightMeasureSpec; - } - - /** - * <p> - * Measure the view and its content to determine the measured width and the - * measured height. This method is invoked by {@link #measure(int, int)} and - * should be overriden by subclasses to provide accurate and efficient - * measurement of their contents. - * </p> - * - * <p> - * <strong>CONTRACT:</strong> When overriding this method, you - * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the - * measured width and height of this view. Failure to do so will trigger an - * <code>IllegalStateException</code>, thrown by - * {@link #measure(int, int)}. Calling the superclass' - * {@link #onMeasure(int, int)} is a valid use. - * </p> - * - * <p> - * The base class implementation of measure defaults to the background size, - * unless a larger size is allowed by the MeasureSpec. Subclasses should - * override {@link #onMeasure(int, int)} to provide better measurements of - * their content. - * </p> - * - * <p> - * If this method is overridden, it is the subclass's responsibility to make - * sure the measured height and width are at least the view's minimum height - * and width ({@link #getSuggestedMinimumHeight()} and - * {@link #getSuggestedMinimumWidth()}). - * </p> - * - * @param widthMeasureSpec horizontal space requirements as imposed by the parent. - * The requirements are encoded with - * {@link android.view.View.MeasureSpec}. - * @param heightMeasureSpec vertical space requirements as imposed by the parent. - * The requirements are encoded with - * {@link android.view.View.MeasureSpec}. - * - * @see #getMeasuredWidth() - * @see #getMeasuredHeight() - * @see #setMeasuredDimension(int, int) - * @see #getSuggestedMinimumHeight() - * @see #getSuggestedMinimumWidth() - * @see android.view.View.MeasureSpec#getMode(int) - * @see android.view.View.MeasureSpec#getSize(int) - */ - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), - getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); - } - - /** - * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the - * measured width and measured height. Failing to do so will trigger an - * exception at measurement time.</p> - * - * @param measuredWidth the measured width of this view - * @param measuredHeight the measured height of this view - */ - protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { - mMeasuredWidth = measuredWidth; - mMeasuredHeight = measuredHeight; - - mPrivateFlags |= MEASURED_DIMENSION_SET; - } - - /** - * Utility to reconcile a desired size with constraints imposed by a MeasureSpec. - * Will take the desired size, unless a different size is imposed by the constraints. - * - * @param size How big the view wants to be - * @param measureSpec Constraints imposed by the parent - * @return The size this view should be. - */ - public static int resolveSize(int size, int measureSpec) { - int result = size; - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - switch (specMode) { - case MeasureSpec.UNSPECIFIED: - result = size; - break; - case MeasureSpec.AT_MOST: - result = Math.min(size, specSize); - break; - case MeasureSpec.EXACTLY: - result = specSize; - break; - } - return result; - } - - /** - * Utility to return a default size. Uses the supplied size if the - * MeasureSpec imposed no contraints. Will get larger if allowed - * by the MeasureSpec. - * - * @param size Default size for this view - * @param measureSpec Constraints imposed by the parent - * @return The size this view should be. - */ - public static int getDefaultSize(int size, int measureSpec) { - int result = size; - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - - switch (specMode) { - case MeasureSpec.UNSPECIFIED: - result = size; - break; - case MeasureSpec.AT_MOST: - case MeasureSpec.EXACTLY: - result = specSize; - break; - } - return result; - } - - /** - * Returns the suggested minimum height that the view should use. This - * returns the maximum of the view's minimum height - * and the background's minimum height - * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}). - * <p> - * When being used in {@link #onMeasure(int, int)}, the caller should still - * ensure the returned height is within the requirements of the parent. - * - * @return The suggested minimum height of the view. - */ - protected int getSuggestedMinimumHeight() { - int suggestedMinHeight = mMinHeight; - - if (mBGDrawable != null) { - final int bgMinHeight = mBGDrawable.getMinimumHeight(); - if (suggestedMinHeight < bgMinHeight) { - suggestedMinHeight = bgMinHeight; - } - } - - return suggestedMinHeight; - } - - /** - * Returns the suggested minimum width that the view should use. This - * returns the maximum of the view's minimum width) - * and the background's minimum width - * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}). - * <p> - * When being used in {@link #onMeasure(int, int)}, the caller should still - * ensure the returned width is within the requirements of the parent. - * - * @return The suggested minimum width of the view. - */ - protected int getSuggestedMinimumWidth() { - int suggestedMinWidth = mMinWidth; - - if (mBGDrawable != null) { - final int bgMinWidth = mBGDrawable.getMinimumWidth(); - if (suggestedMinWidth < bgMinWidth) { - suggestedMinWidth = bgMinWidth; - } - } - - return suggestedMinWidth; - } - - /** - * Sets the minimum height of the view. It is not guaranteed the view will - * be able to achieve this minimum height (for example, if its parent layout - * constrains it with less available height). - * - * @param minHeight The minimum height the view will try to be. - */ - public void setMinimumHeight(int minHeight) { - mMinHeight = minHeight; - } - - /** - * Sets the minimum width of the view. It is not guaranteed the view will - * be able to achieve this minimum width (for example, if its parent layout - * constrains it with less available width). - * - * @param minWidth The minimum width the view will try to be. - */ - public void setMinimumWidth(int minWidth) { - mMinWidth = minWidth; - } - - /** - * Get the animation currently associated with this view. - * - * @return The animation that is currently playing or - * scheduled to play for this view. - */ - public Animation getAnimation() { - return mCurrentAnimation; - } - - /** - * Start the specified animation now. - * - * @param animation the animation to start now - */ - public void startAnimation(Animation animation) { - animation.setStartTime(Animation.START_ON_FIRST_FRAME); - setAnimation(animation); - invalidate(); - } - - /** - * Cancels any animations for this view. - */ - public void clearAnimation() { - mCurrentAnimation = null; - } - - /** - * Sets the next animation to play for this view. - * If you want the animation to play immediately, use - * startAnimation. This method provides allows fine-grained - * control over the start time and invalidation, but you - * must make sure that 1) the animation has a start time set, and - * 2) the view will be invalidated when the animation is supposed to - * start. - * - * @param animation The next animation, or null. - */ - public void setAnimation(Animation animation) { - mCurrentAnimation = animation; - if (animation != null) { - animation.reset(); - } - } - - /** - * Invoked by a parent ViewGroup to notify the start of the animation - * currently associated with this view. If you override this method, - * always call super.onAnimationStart(); - * - * @see #setAnimation(android.view.animation.Animation) - * @see #getAnimation() - */ - protected void onAnimationStart() { - mPrivateFlags |= ANIMATION_STARTED; - } - - /** - * Invoked by a parent ViewGroup to notify the end of the animation - * currently associated with this view. If you override this method, - * always call super.onAnimationEnd(); - * - * @see #setAnimation(android.view.animation.Animation) - * @see #getAnimation() - */ - protected void onAnimationEnd() { - mPrivateFlags &= ~ANIMATION_STARTED; - } - - /** - * Invoked if there is a Transform that involves alpha. Subclass that can - * draw themselves with the specified alpha should return true, and then - * respect that alpha when their onDraw() is called. If this returns false - * then the view may be redirected to draw into an offscreen buffer to - * fulfill the request, which will look fine, but may be slower than if the - * subclass handles it internally. The default implementation returns false. - * - * @param alpha The alpha (0..255) to apply to the view's drawing - * @return true if the view can draw with the specified alpha. - */ - protected boolean onSetAlpha(int alpha) { - return false; - } - - /** - * This is used by the RootView to perform an optimization when - * the view hierarchy contains one or several SurfaceView. - * SurfaceView is always considered transparent, but its children are not, - * therefore all View objects remove themselves from the global transparent - * region (passed as a parameter to this function). - * - * @param region The transparent region for this ViewRoot (window). - * - * @return Returns true if the effective visibility of the view at this - * point is opaque, regardless of the transparent region; returns false - * if it is possible for underlying windows to be seen behind the view. - * - * {@hide} - */ - public boolean gatherTransparentRegion(Region region) { - final AttachInfo attachInfo = mAttachInfo; - if (region != null && attachInfo != null) { - final int pflags = mPrivateFlags; - if ((pflags & SKIP_DRAW) == 0) { - // The SKIP_DRAW flag IS NOT set, so this view draws. We need to - // remove it from the transparent region. - final int[] location = attachInfo.mTransparentLocation; - getLocationInWindow(location); - region.op(location[0], location[1], location[0] + mRight - mLeft, - location[1] + mBottom - mTop, Region.Op.DIFFERENCE); - } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) { - // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable - // exists, so we remove the background drawable's non-transparent - // parts from this transparent region. - applyDrawableToTransparentRegion(mBGDrawable, region); - } - } - return true; - } - - /** - * Play a sound effect for this view. - * - * <p>The framework will play sound effects for some built in actions, such as - * clicking, but you may wish to play these effects in your widget, - * for instance, for internal navigation. - * - * <p>The sound effect will only be played if sound effects are enabled by the user, and - * {@link #isSoundEffectsEnabled()} is true. - * - * @param soundConstant One of the constants defined in {@link SoundEffectConstants} - */ - public void playSoundEffect(int soundConstant) { - if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) { - return; - } - mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant); - } - - /** - * Provide haptic feedback to the user for this view. - * - * <p>The framework will provide haptic feedback for some built in actions, - * such as long presses, but you may wish to provide feedback for your - * own widget. - * - * <p>The feedback will only be performed if - * {@link #isHapticFeedbackEnabled()} is true. - * - * @param feedbackConstant One of the constants defined in - * {@link HapticFeedbackConstants} - */ - public boolean performHapticFeedback(int feedbackConstant) { - return performHapticFeedback(feedbackConstant, 0); - } - - /** - * Like {@link #performHapticFeedback(int)}, with additional options. - * - * @param feedbackConstant One of the constants defined in - * {@link HapticFeedbackConstants} - * @param flags Additional flags as per {@link HapticFeedbackConstants}. - */ - public boolean performHapticFeedback(int feedbackConstant, int flags) { - if (mAttachInfo == null) { - return false; - } - if ((flags&HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0 - && !isHapticFeedbackEnabled()) { - return false; - } - return mAttachInfo.mRootCallbacks.performHapticFeedback( - feedbackConstant, - (flags&HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0); - } - - /** - * Given a Drawable whose bounds have been set to draw into this view, - * update a Region being computed for {@link #gatherTransparentRegion} so - * that any non-transparent parts of the Drawable are removed from the - * given transparent region. - * - * @param dr The Drawable whose transparency is to be applied to the region. - * @param region A Region holding the current transparency information, - * where any parts of the region that are set are considered to be - * transparent. On return, this region will be modified to have the - * transparency information reduced by the corresponding parts of the - * Drawable that are not transparent. - * {@hide} - */ - public void applyDrawableToTransparentRegion(Drawable dr, Region region) { - if (DBG) { - Log.i("View", "Getting transparent region for: " + this); - } - final Region r = dr.getTransparentRegion(); - final Rect db = dr.getBounds(); - final AttachInfo attachInfo = mAttachInfo; - if (r != null && attachInfo != null) { - final int w = getRight()-getLeft(); - final int h = getBottom()-getTop(); - if (db.left > 0) { - //Log.i("VIEW", "Drawable left " + db.left + " > view 0"); - r.op(0, 0, db.left, h, Region.Op.UNION); - } - if (db.right < w) { - //Log.i("VIEW", "Drawable right " + db.right + " < view " + w); - r.op(db.right, 0, w, h, Region.Op.UNION); - } - if (db.top > 0) { - //Log.i("VIEW", "Drawable top " + db.top + " > view 0"); - r.op(0, 0, w, db.top, Region.Op.UNION); - } - if (db.bottom < h) { - //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h); - r.op(0, db.bottom, w, h, Region.Op.UNION); - } - final int[] location = attachInfo.mTransparentLocation; - getLocationInWindow(location); - r.translate(location[0], location[1]); - region.op(r, Region.Op.INTERSECT); - } else { - region.op(db, Region.Op.DIFFERENCE); - } - } - - private void postCheckForLongClick() { - mHasPerformedLongPress = false; - - if (mPendingCheckForLongPress == null) { - mPendingCheckForLongPress = new CheckForLongPress(); - } - mPendingCheckForLongPress.rememberWindowAttachCount(); - postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout()); - } - - private static int[] stateSetUnion(final int[] stateSet1, - final int[] stateSet2) { - final int stateSet1Length = stateSet1.length; - final int stateSet2Length = stateSet2.length; - final int[] newSet = new int[stateSet1Length + stateSet2Length]; - int k = 0; - int i = 0; - int j = 0; - // This is a merge of the two input state sets and assumes that the - // input sets are sorted by the order imposed by ViewDrawableStates. - for (int viewState : R.styleable.ViewDrawableStates) { - if (i < stateSet1Length && stateSet1[i] == viewState) { - newSet[k++] = viewState; - i++; - } else if (j < stateSet2Length && stateSet2[j] == viewState) { - newSet[k++] = viewState; - j++; - } - if (k > 1) { - assert(newSet[k - 1] > newSet[k - 2]); - } - } - return newSet; - } - - /** - * Inflate a view from an XML resource. This convenience method wraps the {@link - * LayoutInflater} class, which provides a full range of options for view inflation. - * - * @param context The Context object for your activity or application. - * @param resource The resource ID to inflate - * @param root A view group that will be the parent. Used to properly inflate the - * layout_* parameters. - * @see LayoutInflater - */ - public static View inflate(Context context, int resource, ViewGroup root) { - LayoutInflater factory = LayoutInflater.from(context); - return factory.inflate(resource, root); - } - - /** - * A MeasureSpec encapsulates the layout requirements passed from parent to child. - * Each MeasureSpec represents a requirement for either the width or the height. - * A MeasureSpec is comprised of a size and a mode. There are three possible - * modes: - * <dl> - * <dt>UNSPECIFIED</dt> - * <dd> - * The parent has not imposed any constraint on the child. It can be whatever size - * it wants. - * </dd> - * - * <dt>EXACTLY</dt> - * <dd> - * The parent has determined an exact size for the child. The child is going to be - * given those bounds regardless of how big it wants to be. - * </dd> - * - * <dt>AT_MOST</dt> - * <dd> - * The child can be as large as it wants up to the specified size. - * </dd> - * </dl> - * - * MeasureSpecs are implemented as ints to reduce object allocation. This class - * is provided to pack and unpack the <size, mode> tuple into the int. - */ - public static class MeasureSpec { - private static final int MODE_SHIFT = 30; - private static final int MODE_MASK = 0x3 << MODE_SHIFT; - - /** - * Measure specification mode: The parent has not imposed any constraint - * on the child. It can be whatever size it wants. - */ - public static final int UNSPECIFIED = 0 << MODE_SHIFT; - - /** - * Measure specification mode: The parent has determined an exact size - * for the child. The child is going to be given those bounds regardless - * of how big it wants to be. - */ - public static final int EXACTLY = 1 << MODE_SHIFT; - - /** - * Measure specification mode: The child can be as large as it wants up - * to the specified size. - */ - public static final int AT_MOST = 2 << MODE_SHIFT; - - /** - * Creates a measure specification based on the supplied size and mode. - * - * The mode must always be one of the following: - * <ul> - * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li> - * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li> - * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li> - * </ul> - * - * @param size the size of the measure specification - * @param mode the mode of the measure specification - * @return the measure specification based on size and mode - */ - public static int makeMeasureSpec(int size, int mode) { - return size + mode; - } - - /** - * Extracts the mode from the supplied measure specification. - * - * @param measureSpec the measure specification to extract the mode from - * @return {@link android.view.View.MeasureSpec#UNSPECIFIED}, - * {@link android.view.View.MeasureSpec#AT_MOST} or - * {@link android.view.View.MeasureSpec#EXACTLY} - */ - public static int getMode(int measureSpec) { - return (measureSpec & MODE_MASK); - } - - /** - * Extracts the size from the supplied measure specification. - * - * @param measureSpec the measure specification to extract the size from - * @return the size in pixels defined in the supplied measure specification - */ - public static int getSize(int measureSpec) { - return (measureSpec & ~MODE_MASK); - } - - /** - * Returns a String representation of the specified measure - * specification. - * - * @param measureSpec the measure specification to convert to a String - * @return a String with the following format: "MeasureSpec: MODE SIZE" - */ - public static String toString(int measureSpec) { - int mode = getMode(measureSpec); - int size = getSize(measureSpec); - - StringBuilder sb = new StringBuilder("MeasureSpec: "); - - if (mode == UNSPECIFIED) - sb.append("UNSPECIFIED "); - else if (mode == EXACTLY) - sb.append("EXACTLY "); - else if (mode == AT_MOST) - sb.append("AT_MOST "); - else - sb.append(mode).append(" "); - - sb.append(size); - return sb.toString(); - } - } - - class CheckForLongPress implements Runnable { - - private int mOriginalWindowAttachCount; - - public void run() { - if (isPressed() && (mParent != null) && hasWindowFocus() - && mOriginalWindowAttachCount == mWindowAttachCount) { - if (performLongClick()) { - mHasPerformedLongPress = true; - } - } - } - - public void rememberWindowAttachCount() { - mOriginalWindowAttachCount = mWindowAttachCount; - } - } - - /** - * Interface definition for a callback to be invoked when a key event is - * dispatched to this view. The callback will be invoked before the key - * event is given to the view. - */ - public interface OnKeyListener { - /** - * Called when a key is dispatched to a view. This allows listeners to - * get a chance to respond before the target view. - * - * @param v The view the key has been dispatched to. - * @param keyCode The code for the physical key that was pressed - * @param event The KeyEvent object containing full information about - * the event. - * @return True if the listener has consumed the event, false otherwise. - */ - boolean onKey(View v, int keyCode, KeyEvent event); - } - - /** - * Interface definition for a callback to be invoked when a touch event is - * dispatched to this view. The callback will be invoked before the touch - * event is given to the view. - */ - public interface OnTouchListener { - /** - * Called when a touch event is dispatched to a view. This allows listeners to - * get a chance to respond before the target view. - * - * @param v The view the touch event has been dispatched to. - * @param event The MotionEvent object containing full information about - * the event. - * @return True if the listener has consumed the event, false otherwise. - */ - boolean onTouch(View v, MotionEvent event); - } - - /** - * Interface definition for a callback to be invoked when a view has been clicked and held. - */ - public interface OnLongClickListener { - /** - * Called when a view has been clicked and held. - * - * @param v The view that was clicked and held. - * - * return True if the callback consumed the long click, false otherwise - */ - boolean onLongClick(View v); - } - - /** - * Interface definition for a callback to be invoked when the focus state of - * a view changed. - */ - public interface OnFocusChangeListener { - /** - * Called when the focus state of a view has changed. - * - * @param v The view whose state has changed. - * @param hasFocus The new focus state of v. - */ - void onFocusChange(View v, boolean hasFocus); - } - - /** - * Interface definition for a callback to be invoked when a view is clicked. - */ - public interface OnClickListener { - /** - * Called when a view has been clicked. - * - * @param v The view that was clicked. - */ - void onClick(View v); - } - - /** - * Interface definition for a callback to be invoked when the context menu - * for this view is being built. - */ - public interface OnCreateContextMenuListener { - /** - * Called when the context menu for this view is being built. It is not - * safe to hold onto the menu after this method returns. - * - * @param menu The context menu that is being built - * @param v The view for which the context menu is being built - * @param menuInfo Extra information about the item for which the - * context menu should be shown. This information will vary - * depending on the class of v. - */ - void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo); - } - - private final class UnsetPressedState implements Runnable { - public void run() { - setPressed(false); - } - } - - /** - * Base class for derived classes that want to save and restore their own - * state in {@link android.view.View#onSaveInstanceState()}. - */ - public static class BaseSavedState extends AbsSavedState { - /** - * Constructor used when reading from a parcel. Reads the state of the superclass. - * - * @param source - */ - public BaseSavedState(Parcel source) { - super(source); - } - - /** - * Constructor called by derived classes when creating their SavedState objects - * - * @param superState The state of the superclass of this view - */ - public BaseSavedState(Parcelable superState) { - super(superState); - } - - public static final Parcelable.Creator<BaseSavedState> CREATOR = - new Parcelable.Creator<BaseSavedState>() { - public BaseSavedState createFromParcel(Parcel in) { - return new BaseSavedState(in); - } - - public BaseSavedState[] newArray(int size) { - return new BaseSavedState[size]; - } - }; - } - - /** - * A set of information given to a view when it is attached to its parent - * window. - */ - static class AttachInfo { - - interface Callbacks { - void playSoundEffect(int effectId); - boolean performHapticFeedback(int effectId, boolean always); - } - - /** - * InvalidateInfo is used to post invalidate(int, int, int, int) messages - * to a Handler. This class contains the target (View) to invalidate and - * the coordinates of the dirty rectangle. - * - * For performance purposes, this class also implements a pool of up to - * POOL_LIMIT objects that get reused. This reduces memory allocations - * whenever possible. - * - * The pool is implemented as a linked list of InvalidateInfo object with - * the root pointing to the next available InvalidateInfo. If the root - * is null (i.e. when all instances from the pool have been acquired), - * then a new InvalidateInfo is created and returned to the caller. - * - * An InvalidateInfo is sent back to the pool by calling its release() - * method. If the pool is full the object is simply discarded. - * - * This implementation follows the object pool pattern used in the - * MotionEvent class. - */ - static class InvalidateInfo { - private static final int POOL_LIMIT = 10; - private static final Object sLock = new Object(); - - private static int sAcquiredCount = 0; - private static InvalidateInfo sRoot; - - private InvalidateInfo next; - - View target; - - int left; - int top; - int right; - int bottom; - - static InvalidateInfo acquire() { - synchronized (sLock) { - if (sRoot == null) { - return new InvalidateInfo(); - } - - InvalidateInfo info = sRoot; - sRoot = info.next; - sAcquiredCount--; - - return info; - } - } - - void release() { - synchronized (sLock) { - if (sAcquiredCount < POOL_LIMIT) { - sAcquiredCount++; - next = sRoot; - sRoot = this; - } - } - } - } - - final IWindowSession mSession; - - final IWindow mWindow; - - final IBinder mWindowToken; - - final Callbacks mRootCallbacks; - - /** - * The top view of the hierarchy. - */ - View mRootView; - - IBinder mPanelParentWindowToken; - Surface mSurface; - - /** - * Left position of this view's window - */ - int mWindowLeft; - - /** - * Top position of this view's window - */ - int mWindowTop; - - /** - * For windows that are full-screen but using insets to layout inside - * of the screen decorations, these are the current insets for the - * content of the window. - */ - final Rect mContentInsets = new Rect(); - - /** - * For windows that are full-screen but using insets to layout inside - * of the screen decorations, these are the current insets for the - * actual visible parts of the window. - */ - final Rect mVisibleInsets = new Rect(); - - /** - * The internal insets given by this window. This value is - * supplied by the client (through - * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will - * be given to the window manager when changed to be used in laying - * out windows behind it. - */ - final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets - = new ViewTreeObserver.InternalInsetsInfo(); - - /** - * All views in the window's hierarchy that serve as scroll containers, - * used to determine if the window can be resized or must be panned - * to adjust for a soft input area. - */ - final ArrayList<View> mScrollContainers = new ArrayList<View>(); - - /** - * Indicates whether the view's window currently has the focus. - */ - boolean mHasWindowFocus; - - /** - * The current visibility of the window. - */ - int mWindowVisibility; - - /** - * Indicates the time at which drawing started to occur. - */ - long mDrawingTime; - - /** - * Indicates whether the view's window is currently in touch mode. - */ - boolean mInTouchMode; - - /** - * Indicates that ViewRoot should trigger a global layout change - * the next time it performs a traversal - */ - boolean mRecomputeGlobalAttributes; - - /** - * Set to true when attributes (like mKeepScreenOn) need to be - * recomputed. - */ - boolean mAttributesChanged; - - /** - * Set during a traveral if any views want to keep the screen on. - */ - boolean mKeepScreenOn; - - /** - * Set if the visibility of any views has changed. - */ - boolean mViewVisibilityChanged; - - /** - * Set to true if a view has been scrolled. - */ - boolean mViewScrollChanged; - - /** - * Global to the view hierarchy used as a temporary for dealing with - * x/y points in the transparent region computations. - */ - final int[] mTransparentLocation = new int[2]; - - /** - * Global to the view hierarchy used as a temporary for dealing with - * x/y points in the ViewGroup.invalidateChild implementation. - */ - final int[] mInvalidateChildLocation = new int[2]; - - /** - * The view tree observer used to dispatch global events like - * layout, pre-draw, touch mode change, etc. - */ - final ViewTreeObserver mTreeObserver = new ViewTreeObserver(); - - /** - * A Canvas used by the view hierarchy to perform bitmap caching. - */ - Canvas mCanvas; - - /** - * A Handler supplied by a view's {@link android.view.ViewRoot}. This - * handler can be used to pump events in the UI events queue. - */ - final Handler mHandler; - - /** - * Identifier for messages requesting the view to be invalidated. - * Such messages should be sent to {@link #mHandler}. - */ - static final int INVALIDATE_MSG = 0x1; - - /** - * Identifier for messages requesting the view to invalidate a region. - * Such messages should be sent to {@link #mHandler}. - */ - static final int INVALIDATE_RECT_MSG = 0x2; - - /** - * Temporary for use in computing invalidate rectangles while - * calling up the hierarchy. - */ - final Rect mTmpInvalRect = new Rect(); - - /** - * Creates a new set of attachment information with the specified - * events handler and thread. - * - * @param handler the events handler the view must use - */ - AttachInfo(IWindowSession session, IWindow window, - Handler handler, Callbacks effectPlayer) { - mSession = session; - mWindow = window; - mWindowToken = window.asBinder(); - mHandler = handler; - mRootCallbacks = effectPlayer; - } - } - - /** - * <p>ScrollabilityCache holds various fields used by a View when scrolling - * is supported. This avoids keeping too many unused fields in most - * instances of View.</p> - */ - private static class ScrollabilityCache { - public int fadingEdgeLength; - - public int scrollBarSize; - public ScrollBarDrawable scrollBar; - - public final Paint paint; - public final Matrix matrix; - public Shader shader; - - private int mLastColor; - - public ScrollabilityCache(ViewConfiguration configuration) { - fadingEdgeLength = configuration.getScaledFadingEdgeLength(); - scrollBarSize = configuration.getScaledScrollBarSize(); - - paint = new Paint(); - matrix = new Matrix(); - // use use a height of 1, and then wack the matrix each time we - // actually use it. - shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); - - paint.setShader(shader); - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); - } - - public void setFadeColor(int color) { - if (color != 0 && color != mLastColor) { - mLastColor = color; - color |= 0xFF000000; - - shader = new LinearGradient(0, 0, 0, 1, color, 0, Shader.TileMode.CLAMP); - - paint.setShader(shader); - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); - } - } - } -} diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java deleted file mode 100644 index 2f7b0d1..0000000 --- a/core/java/android/view/ViewConfiguration.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.content.Context; -import android.util.DisplayMetrics; -import android.util.SparseArray; - -/** - * Contains methods to standard constants used in the UI for timeouts, sizes, and distances. - */ -public class ViewConfiguration { - /** - * Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in - * pixels - */ - private static final int SCROLL_BAR_SIZE = 10; - - /** - * Defines the length of the fading edges in pixels - */ - private static final int FADING_EDGE_LENGTH = 12; - - /** - * Defines the duration in milliseconds of the pressed state in child - * components. - */ - private static final int PRESSED_STATE_DURATION = 85; - - /** - * Defines the duration in milliseconds before a press turns into - * a long press - */ - private static final int LONG_PRESS_TIMEOUT = 500; - - /** - * Defines the duration in milliseconds a user needs to hold down the - * appropriate button to bring up the global actions dialog (power off, - * lock screen, etc). - */ - private static final int GLOBAL_ACTIONS_KEY_TIMEOUT = 500; - - /** - * Defines the duration in milliseconds we will wait to see if a touch event - * is a top or a scroll. If the user does not move within this interval, it is - * considered to be a tap. - */ - private static final int TAP_TIMEOUT = 100; - - /** - * Defines the duration in milliseconds we will wait to see if a touch event - * is a jump tap. If the user does not complete the jump tap within this interval, it is - * considered to be a tap. - */ - private static final int JUMP_TAP_TIMEOUT = 500; - - /** - * Defines the duration in milliseconds between the first tap's up event and - * the second tap's down event for an interaction to be considered a - * double-tap. - */ - private static final int DOUBLE_TAP_TIMEOUT = 300; - - /** - * Defines the duration in milliseconds we want to display zoom controls in response - * to a user panning within an application. - */ - private static final int ZOOM_CONTROLS_TIMEOUT = 3000; - - /** - * Inset in pixels to look for touchable content when the user touches the edge of the screen - */ - private static final int EDGE_SLOP = 12; - - /** - * Distance a touch can wander before we think the user is scrolling in pixels - */ - private static final int TOUCH_SLOP = 25; - - /** - * Distance between the first touch and second touch to still be considered a double tap - */ - private static final int DOUBLE_TAP_SLOP = 100; - - /** - * Distance a touch needs to be outside of a window's bounds for it to - * count as outside for purposes of dismissing the window. - */ - private static final int WINDOW_TOUCH_SLOP = 16; - - /** - * Minimum velocity to initiate a fling, as measured in pixels per second - */ - private static final int MINIMUM_FLING_VELOCITY = 50; - - /** - * The maximum size of View's drawing cache, expressed in bytes. This size - * should be at least equal to the size of the screen in ARGB888 format. - */ - @Deprecated - private static final int MAXIMUM_DRAWING_CACHE_SIZE = 320 * 480 * 4; // HVGA screen, ARGB8888 - - /** - * The coefficient of friction applied to flings/scrolls. - */ - private static float SCROLL_FRICTION = 0.015f; - - private final int mEdgeSlop; - private final int mFadingEdgeLength; - private final int mMinimumFlingVelocity; - private final int mScrollbarSize; - private final int mTouchSlop; - private final int mDoubleTapSlop; - private final int mWindowTouchSlop; - private final int mMaximumDrawingCacheSize; - - private static final SparseArray<ViewConfiguration> sConfigurations = - new SparseArray<ViewConfiguration>(2); - - /** - * @deprecated Use {@link android.view.ViewConfiguration#get(android.content.Context)} instead. - */ - @Deprecated - public ViewConfiguration() { - mEdgeSlop = EDGE_SLOP; - mFadingEdgeLength = FADING_EDGE_LENGTH; - mMinimumFlingVelocity = MINIMUM_FLING_VELOCITY; - mScrollbarSize = SCROLL_BAR_SIZE; - mTouchSlop = TOUCH_SLOP; - mDoubleTapSlop = DOUBLE_TAP_SLOP; - mWindowTouchSlop = WINDOW_TOUCH_SLOP; - //noinspection deprecation - mMaximumDrawingCacheSize = MAXIMUM_DRAWING_CACHE_SIZE; - } - - /** - * Creates a new configuration for the specified context. The configuration depends on - * various parameters of the context, like the dimension of the display or the density - * of the display. - * - * @param context The application context used to initialize this view configuration. - * - * @see #get(android.content.Context) - * @see android.util.DisplayMetrics - */ - private ViewConfiguration(Context context) { - final DisplayMetrics metrics = context.getResources().getDisplayMetrics(); - final float density = metrics.density; - - mEdgeSlop = (int) (density * EDGE_SLOP + 0.5f); - mFadingEdgeLength = (int) (density * FADING_EDGE_LENGTH + 0.5f); - mMinimumFlingVelocity = (int) (density * MINIMUM_FLING_VELOCITY + 0.5f); - mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f); - mTouchSlop = (int) (density * TOUCH_SLOP + 0.5f); - mDoubleTapSlop = (int) (density * DOUBLE_TAP_SLOP + 0.5f); - mWindowTouchSlop = (int) (density * WINDOW_TOUCH_SLOP + 0.5f); - - // Size of the screen in bytes, in ARGB_8888 format - mMaximumDrawingCacheSize = 4 * metrics.widthPixels * metrics.heightPixels; - } - - /** - * Returns a configuration for the specified context. The configuration depends on - * various parameters of the context, like the dimension of the display or the - * density of the display. - * - * @param context The application context used to initialize the view configuration. - */ - public static ViewConfiguration get(Context context) { - final DisplayMetrics metrics = context.getResources().getDisplayMetrics(); - final int density = (int) (100.0f * metrics.density); - - ViewConfiguration configuration = sConfigurations.get(density); - if (configuration == null) { - configuration = new ViewConfiguration(context); - sConfigurations.put(density, configuration); - } - - return configuration; - } - - /** - * @return The width of the horizontal scrollbar and the height of the vertical - * scrollbar in pixels - * - * @deprecated Use {@link #getScaledScrollBarSize()} instead. - */ - @Deprecated - public static int getScrollBarSize() { - return SCROLL_BAR_SIZE; - } - - /** - * @return The width of the horizontal scrollbar and the height of the vertical - * scrollbar in pixels - */ - public int getScaledScrollBarSize() { - return mScrollbarSize; - } - - /** - * @return Defines the length of the fading edges in pixels - * - * @deprecated Use {@link #getScaledFadingEdgeLength()} instead. - */ - @Deprecated - public static int getFadingEdgeLength() { - return FADING_EDGE_LENGTH; - } - - /** - * @return Defines the length of the fading edges in pixels - */ - public int getScaledFadingEdgeLength() { - return mFadingEdgeLength; - } - - /** - * @return Defines the duration in milliseconds of the pressed state in child - * components. - */ - public static int getPressedStateDuration() { - return PRESSED_STATE_DURATION; - } - - /** - * @return Defines the duration in milliseconds before a press turns into - * a long press - */ - public static int getLongPressTimeout() { - return LONG_PRESS_TIMEOUT; - } - - /** - * @return Defines the duration in milliseconds we will wait to see if a touch event - * is a top or a scroll. If the user does not move within this interval, it is - * considered to be a tap. - */ - public static int getTapTimeout() { - return TAP_TIMEOUT; - } - - /** - * @return Defines the duration in milliseconds we will wait to see if a touch event - * is a jump tap. If the user does not move within this interval, it is - * considered to be a tap. - */ - public static int getJumpTapTimeout() { - return JUMP_TAP_TIMEOUT; - } - - /** - * @return Defines the duration in milliseconds between the first tap's up event and - * the second tap's down event for an interaction to be considered a - * double-tap. - * @hide pending API council - */ - public static int getDoubleTapTimeout() { - return DOUBLE_TAP_TIMEOUT; - } - - /** - * @return Inset in pixels to look for touchable content when the user touches the edge of the - * screen - * - * @deprecated Use {@link #getScaledEdgeSlop()} instead. - */ - @Deprecated - public static int getEdgeSlop() { - return EDGE_SLOP; - } - - /** - * @return Inset in pixels to look for touchable content when the user touches the edge of the - * screen - */ - public int getScaledEdgeSlop() { - return mEdgeSlop; - } - - /** - * @return Distance a touch can wander before we think the user is scrolling in pixels - * - * @deprecated Use {@link #getScaledTouchSlop()} instead. - */ - @Deprecated - public static int getTouchSlop() { - return TOUCH_SLOP; - } - - /** - * @return Distance a touch can wander before we think the user is scrolling in pixels - */ - public int getScaledTouchSlop() { - return mTouchSlop; - } - - /** - * @return Distance between the first touch and second touch to still be - * considered a double tap - * @deprecated Use {@link #getScaledDoubleTapSlop()} instead. - * @hide The only client of this should be GestureDetector, which needs this - * for clients that still use its deprecated constructor. - */ - @Deprecated - public static int getDoubleTapSlop() { - return DOUBLE_TAP_SLOP; - } - - /** - * @return Distance between the first touch and second touch to still be - * considered a double tap - * @hide pending API council - */ - public int getScaledDoubleTapSlop() { - return mDoubleTapSlop; - } - - /** - * @return Distance a touch must be outside the bounds of a window for it - * to be counted as outside the window for purposes of dismissing that - * window. - * - * @deprecated Use {@link #getScaledWindowTouchSlop()} instead. - */ - @Deprecated - public static int getWindowTouchSlop() { - return WINDOW_TOUCH_SLOP; - } - - /** - * @return Distance a touch must be outside the bounds of a window for it - * to be counted as outside the window for purposes of dismissing that - * window. - */ - public int getScaledWindowTouchSlop() { - return mWindowTouchSlop; - } - - /** - * @return Minimum velocity to initiate a fling, as measured in pixels per second. - * - * @deprecated Use {@link #getScaledMinimumFlingVelocity()} instead. - */ - @Deprecated - public static int getMinimumFlingVelocity() { - return MINIMUM_FLING_VELOCITY; - } - - /** - * @return Minimum velocity to initiate a fling, as measured in pixels per second. - */ - public int getScaledMinimumFlingVelocity() { - return mMinimumFlingVelocity; - } - - /** - * The maximum drawing cache size expressed in bytes. - * - * @return the maximum size of View's drawing cache expressed in bytes - * - * @deprecated Use {@link #getScaledMaximumDrawingCacheSize()} instead. - */ - @Deprecated - public static int getMaximumDrawingCacheSize() { - //noinspection deprecation - return MAXIMUM_DRAWING_CACHE_SIZE; - } - - /** - * The maximum drawing cache size expressed in bytes. - * - * @return the maximum size of View's drawing cache expressed in bytes - */ - public int getScaledMaximumDrawingCacheSize() { - return mMaximumDrawingCacheSize; - } - - /** - * The amount of time that the zoom controls should be - * displayed on the screen expressed in milliseconds. - * - * @return the time the zoom controls should be visible expressed - * in milliseconds. - */ - public static long getZoomControlsTimeout() { - return ZOOM_CONTROLS_TIMEOUT; - } - - /** - * The amount of time a user needs to press the relevant key to bring up - * the global actions dialog. - * - * @return how long a user needs to press the relevant key to bring up - * the global actions dialog. - */ - public static long getGlobalActionKeyTimeout() { - return GLOBAL_ACTIONS_KEY_TIMEOUT; - } - - /** - * The amount of friction applied to scrolls and flings. - * - * @return A scalar dimensionless value representing the coefficient of - * friction. - */ - public static float getScrollFriction() { - return SCROLL_FRICTION; - } -} diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java deleted file mode 100644 index 883c7bd..0000000 --- a/core/java/android/view/ViewDebug.java +++ /dev/null @@ -1,1128 +0,0 @@ -/* - * Copyright (C) 2007 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.view; - -import android.util.Log; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.os.Environment; - -import java.io.File; -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.io.FileOutputStream; -import java.io.DataOutputStream; -import java.io.OutputStreamWriter; -import java.io.BufferedOutputStream; -import java.io.OutputStream; -import java.util.List; -import java.util.LinkedList; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.lang.annotation.Target; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; - -/** - * Various debugging/tracing tools related to {@link View} and the view hierarchy. - */ -public class ViewDebug { - /** - * Enables or disables view hierarchy tracing. Any invoker of - * {@link #trace(View, android.view.ViewDebug.HierarchyTraceType)} should first - * check that this value is set to true as not to affect performance. - */ - public static final boolean TRACE_HIERARCHY = false; - - /** - * Enables or disables view recycler tracing. Any invoker of - * {@link #trace(View, android.view.ViewDebug.RecyclerTraceType, int[])} should first - * check that this value is set to true as not to affect performance. - */ - public static final boolean TRACE_RECYCLER = false; - - /** - * The system property of dynamic switch for capturing view information - * when it is set, we dump interested fields and methods for the view on focus - */ - static final String SYSTEM_PROPERTY_CAPTURE_VIEW = "debug.captureview"; - - /** - * The system property of dynamic switch for capturing event information - * when it is set, we log key events, touch/motion and trackball events - */ - static final String SYSTEM_PROPERTY_CAPTURE_EVENT = "debug.captureevent"; - - /** - * This annotation can be used to mark fields and methods to be dumped by - * the view server. Only non-void methods with no arguments can be annotated - * by this annotation. - */ - @Target({ ElementType.FIELD, ElementType.METHOD }) - @Retention(RetentionPolicy.RUNTIME) - public @interface ExportedProperty { - /** - * When resolveId is true, and if the annotated field/method return value - * is an int, the value is converted to an Android's resource name. - * - * @return true if the property's value must be transformed into an Android - * resource name, false otherwise - */ - boolean resolveId() default false; - - /** - * A mapping can be defined to map int values to specific strings. For - * instance, View.getVisibility() returns 0, 4 or 8. However, these values - * actually mean VISIBLE, INVISIBLE and GONE. A mapping can be used to see - * these human readable values: - * - * <pre> - * @ViewDebug.ExportedProperty(mapping = { - * @ViewDebug.IntToString(from = 0, to = "VISIBLE"), - * @ViewDebug.IntToString(from = 4, to = "INVISIBLE"), - * @ViewDebug.IntToString(from = 8, to = "GONE") - * }) - * public int getVisibility() { ... - * <pre> - * - * @return An array of int to String mappings - * - * @see android.view.ViewDebug.IntToString - */ - IntToString[] mapping() default { }; - - /** - * When deep export is turned on, this property is not dumped. Instead, the - * properties contained in this property are dumped. Each child property - * is prefixed with the name of this property. - * - * @return true if the properties of this property should be dumped - * - * @see #prefix() - */ - boolean deepExport() default false; - - /** - * The prefix to use on child properties when deep export is enabled - * - * @return a prefix as a String - * - * @see #deepExport() - */ - String prefix() default ""; - } - - /** - * Defines a mapping from an int value to a String. Such a mapping can be used - * in a @ExportedProperty to provide more meaningful values to the end user. - * - * @see android.view.ViewDebug.ExportedProperty - */ - @Target({ ElementType.TYPE }) - @Retention(RetentionPolicy.RUNTIME) - public @interface IntToString { - /** - * The original int value to map to a String. - * - * @return An arbitrary int value. - */ - int from(); - - /** - * The String to use in place of the original int value. - * - * @return An arbitrary non-null String. - */ - String to(); - } - - /** - * This annotation can be used to mark fields and methods to be dumped when - * the view is captured. Methods with this annotation must have no arguments - * and must return <some type of data>. - * - * @hide pending API Council approval - */ - @Target({ ElementType.FIELD, ElementType.METHOD }) - @Retention(RetentionPolicy.RUNTIME) - public @interface CapturedViewProperty { - /** - * When retrieveReturn is true, we need to retrieve second level methods - * e.g., we need myView.getFirstLevelMethod().getSecondLevelMethod() - * we will set retrieveReturn = true on the annotation of - * myView.getFirstLevelMethod() - * @return true if we need the second level methods - */ - boolean retrieveReturn() default false; - } - - private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null; - private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null; - - // Maximum delay in ms after which we stop trying to capture a View's drawing - private static final int CAPTURE_TIMEOUT = 4000; - - private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE"; - private static final String REMOTE_COMMAND_DUMP = "DUMP"; - private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE"; - private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT"; - - private static HashMap<Class<?>, Field[]> sFieldsForClasses; - private static HashMap<Class<?>, Method[]> sMethodsForClasses; - - /** - * Defines the type of hierarhcy trace to output to the hierarchy traces file. - */ - public enum HierarchyTraceType { - INVALIDATE, - INVALIDATE_CHILD, - INVALIDATE_CHILD_IN_PARENT, - REQUEST_LAYOUT, - ON_LAYOUT, - ON_MEASURE, - DRAW, - BUILD_CACHE - } - - private static BufferedWriter sHierarchyTraces; - private static ViewRoot sHierarhcyRoot; - private static String sHierarchyTracePrefix; - - /** - * Defines the type of recycler trace to output to the recycler traces file. - */ - public enum RecyclerTraceType { - NEW_VIEW, - BIND_VIEW, - RECYCLE_FROM_ACTIVE_HEAP, - RECYCLE_FROM_SCRAP_HEAP, - MOVE_TO_ACTIVE_HEAP, - MOVE_TO_SCRAP_HEAP, - MOVE_FROM_ACTIVE_TO_SCRAP_HEAP - } - - private static class RecyclerTrace { - public int view; - public RecyclerTraceType type; - public int position; - public int indexOnScreen; - } - - private static View sRecyclerOwnerView; - private static List<View> sRecyclerViews; - private static List<RecyclerTrace> sRecyclerTraces; - private static String sRecyclerTracePrefix; - - /** - * Returns the number of instanciated Views. - * - * @return The number of Views instanciated in the current process. - * - * @hide - */ - public static long getViewInstanceCount() { - return View.sInstanceCount; - } - - /** - * Returns the number of instanciated ViewRoots. - * - * @return The number of ViewRoots instanciated in the current process. - * - * @hide - */ - public static long getViewRootInstanceCount() { - return ViewRoot.getInstanceCount(); - } - - /** - * Outputs a trace to the currently opened recycler traces. The trace records the type of - * recycler action performed on the supplied view as well as a number of parameters. - * - * @param view the view to trace - * @param type the type of the trace - * @param parameters parameters depending on the type of the trace - */ - public static void trace(View view, RecyclerTraceType type, int... parameters) { - if (sRecyclerOwnerView == null || sRecyclerViews == null) { - return; - } - - if (!sRecyclerViews.contains(view)) { - sRecyclerViews.add(view); - } - - final int index = sRecyclerViews.indexOf(view); - - RecyclerTrace trace = new RecyclerTrace(); - trace.view = index; - trace.type = type; - trace.position = parameters[0]; - trace.indexOnScreen = parameters[1]; - - sRecyclerTraces.add(trace); - } - - /** - * Starts tracing the view recycler of the specified view. The trace is identified by a prefix, - * used to build the traces files names: <code>/EXTERNAL/view-recycler/PREFIX.traces</code> and - * <code>/EXTERNAL/view-recycler/PREFIX.recycler</code>. - * - * Only one view recycler can be traced at the same time. After calling this method, any - * other invocation will result in a <code>IllegalStateException</code> unless - * {@link #stopRecyclerTracing()} is invoked before. - * - * Traces files are created only after {@link #stopRecyclerTracing()} is invoked. - * - * This method will return immediately if TRACE_RECYCLER is false. - * - * @param prefix the traces files name prefix - * @param view the view whose recycler must be traced - * - * @see #stopRecyclerTracing() - * @see #trace(View, android.view.ViewDebug.RecyclerTraceType, int[]) - */ - public static void startRecyclerTracing(String prefix, View view) { - //noinspection PointlessBooleanExpression,ConstantConditions - if (!TRACE_RECYCLER) { - return; - } - - if (sRecyclerOwnerView != null) { - throw new IllegalStateException("You must call stopRecyclerTracing() before running" + - " a new trace!"); - } - - sRecyclerTracePrefix = prefix; - sRecyclerOwnerView = view; - sRecyclerViews = new ArrayList<View>(); - sRecyclerTraces = new LinkedList<RecyclerTrace>(); - } - - /** - * Stops the current view recycer tracing. - * - * Calling this method creates the file <code>/EXTERNAL/view-recycler/PREFIX.traces</code> - * containing all the traces (or method calls) relative to the specified view's recycler. - * - * Calling this method creates the file <code>/EXTERNAL/view-recycler/PREFIX.recycler</code> - * containing all of the views used by the recycler of the view supplied to - * {@link #startRecyclerTracing(String, View)}. - * - * This method will return immediately if TRACE_RECYCLER is false. - * - * @see #startRecyclerTracing(String, View) - * @see #trace(View, android.view.ViewDebug.RecyclerTraceType, int[]) - */ - public static void stopRecyclerTracing() { - //noinspection PointlessBooleanExpression,ConstantConditions - if (!TRACE_RECYCLER) { - return; - } - - if (sRecyclerOwnerView == null || sRecyclerViews == null) { - throw new IllegalStateException("You must call startRecyclerTracing() before" + - " stopRecyclerTracing()!"); - } - - File recyclerDump = new File(Environment.getExternalStorageDirectory(), "view-recycler/"); - recyclerDump.mkdirs(); - - recyclerDump = new File(recyclerDump, sRecyclerTracePrefix + ".recycler"); - try { - final BufferedWriter out = new BufferedWriter(new FileWriter(recyclerDump), 8 * 1024); - - for (View view : sRecyclerViews) { - final String name = view.getClass().getName(); - out.write(name); - out.newLine(); - } - - out.close(); - } catch (IOException e) { - Log.e("View", "Could not dump recycler content"); - return; - } - - recyclerDump = new File(Environment.getExternalStorageDirectory(), "view-recycler/"); - recyclerDump = new File(recyclerDump, sRecyclerTracePrefix + ".traces"); - try { - final FileOutputStream file = new FileOutputStream(recyclerDump); - final DataOutputStream out = new DataOutputStream(file); - - for (RecyclerTrace trace : sRecyclerTraces) { - out.writeInt(trace.view); - out.writeInt(trace.type.ordinal()); - out.writeInt(trace.position); - out.writeInt(trace.indexOnScreen); - out.flush(); - } - - out.close(); - } catch (IOException e) { - Log.e("View", "Could not dump recycler traces"); - return; - } - - sRecyclerViews.clear(); - sRecyclerViews = null; - - sRecyclerTraces.clear(); - sRecyclerTraces = null; - - sRecyclerOwnerView = null; - } - - /** - * Outputs a trace to the currently opened traces file. The trace contains the class name - * and instance's hashcode of the specified view as well as the supplied trace type. - * - * @param view the view to trace - * @param type the type of the trace - */ - public static void trace(View view, HierarchyTraceType type) { - if (sHierarchyTraces == null) { - return; - } - - try { - sHierarchyTraces.write(type.name()); - sHierarchyTraces.write(' '); - sHierarchyTraces.write(view.getClass().getName()); - sHierarchyTraces.write('@'); - sHierarchyTraces.write(Integer.toHexString(view.hashCode())); - sHierarchyTraces.newLine(); - } catch (IOException e) { - Log.w("View", "Error while dumping trace of type " + type + " for view " + view); - } - } - - /** - * Starts tracing the view hierarchy of the specified view. The trace is identified by a prefix, - * used to build the traces files names: <code>/EXTERNAL/view-hierarchy/PREFIX.traces</code> and - * <code>/EXTERNAL/view-hierarchy/PREFIX.tree</code>. - * - * Only one view hierarchy can be traced at the same time. After calling this method, any - * other invocation will result in a <code>IllegalStateException</code> unless - * {@link #stopHierarchyTracing()} is invoked before. - * - * Calling this method creates the file <code>/EXTERNAL/view-hierarchy/PREFIX.traces</code> - * containing all the traces (or method calls) relative to the specified view's hierarchy. - * - * This method will return immediately if TRACE_HIERARCHY is false. - * - * @param prefix the traces files name prefix - * @param view the view whose hierarchy must be traced - * - * @see #stopHierarchyTracing() - * @see #trace(View, android.view.ViewDebug.HierarchyTraceType) - */ - public static void startHierarchyTracing(String prefix, View view) { - //noinspection PointlessBooleanExpression,ConstantConditions - if (!TRACE_HIERARCHY) { - return; - } - - if (sHierarhcyRoot != null) { - throw new IllegalStateException("You must call stopHierarchyTracing() before running" + - " a new trace!"); - } - - File hierarchyDump = new File(Environment.getExternalStorageDirectory(), "view-hierarchy/"); - hierarchyDump.mkdirs(); - - hierarchyDump = new File(hierarchyDump, prefix + ".traces"); - sHierarchyTracePrefix = prefix; - - try { - sHierarchyTraces = new BufferedWriter(new FileWriter(hierarchyDump), 8 * 1024); - } catch (IOException e) { - Log.e("View", "Could not dump view hierarchy"); - return; - } - - sHierarhcyRoot = (ViewRoot) view.getRootView().getParent(); - } - - /** - * Stops the current view hierarchy tracing. This method closes the file - * <code>/EXTERNAL/view-hierarchy/PREFIX.traces</code>. - * - * Calling this method creates the file <code>/EXTERNAL/view-hierarchy/PREFIX.tree</code> - * containing the view hierarchy of the view supplied to - * {@link #startHierarchyTracing(String, View)}. - * - * This method will return immediately if TRACE_HIERARCHY is false. - * - * @see #startHierarchyTracing(String, View) - * @see #trace(View, android.view.ViewDebug.HierarchyTraceType) - */ - public static void stopHierarchyTracing() { - //noinspection PointlessBooleanExpression,ConstantConditions - if (!TRACE_HIERARCHY) { - return; - } - - if (sHierarhcyRoot == null || sHierarchyTraces == null) { - throw new IllegalStateException("You must call startHierarchyTracing() before" + - " stopHierarchyTracing()!"); - } - - try { - sHierarchyTraces.close(); - } catch (IOException e) { - Log.e("View", "Could not write view traces"); - } - sHierarchyTraces = null; - - File hierarchyDump = new File(Environment.getExternalStorageDirectory(), "view-hierarchy/"); - hierarchyDump.mkdirs(); - hierarchyDump = new File(hierarchyDump, sHierarchyTracePrefix + ".tree"); - - BufferedWriter out; - try { - out = new BufferedWriter(new FileWriter(hierarchyDump), 8 * 1024); - } catch (IOException e) { - Log.e("View", "Could not dump view hierarchy"); - return; - } - - View view = sHierarhcyRoot.getView(); - if (view instanceof ViewGroup) { - ViewGroup group = (ViewGroup) view; - dumpViewHierarchy(group, out, 0); - try { - out.close(); - } catch (IOException e) { - Log.e("View", "Could not dump view hierarchy"); - } - } - - sHierarhcyRoot = null; - } - - static void dispatchCommand(View view, String command, String parameters, - OutputStream clientStream) throws IOException { - - // Paranoid but safe... - view = view.getRootView(); - - if (REMOTE_COMMAND_DUMP.equalsIgnoreCase(command)) { - dump(view, clientStream); - } else { - final String[] params = parameters.split(" "); - if (REMOTE_COMMAND_CAPTURE.equalsIgnoreCase(command)) { - capture(view, clientStream, params[0]); - } else if (REMOTE_COMMAND_INVALIDATE.equalsIgnoreCase(command)) { - invalidate(view, params[0]); - } else if (REMOTE_COMMAND_REQUEST_LAYOUT.equalsIgnoreCase(command)) { - requestLayout(view, params[0]); - } - } - } - - private static View findViewByHashCode(View root, String parameter) { - final String[] ids = parameter.split("@"); - final String className = ids[0]; - final int hashCode = Integer.parseInt(ids[1], 16); - - View view = root.getRootView(); - if (view instanceof ViewGroup) { - return findView((ViewGroup) view, className, hashCode); - } - - return null; - } - - private static void invalidate(View root, String parameter) { - final View view = findViewByHashCode(root, parameter); - if (view != null) { - view.postInvalidate(); - } - } - - private static void requestLayout(View root, String parameter) { - final View view = findViewByHashCode(root, parameter); - if (view != null) { - root.post(new Runnable() { - public void run() { - view.requestLayout(); - } - }); - } - } - - private static void capture(View root, final OutputStream clientStream, String parameter) - throws IOException { - - final CountDownLatch latch = new CountDownLatch(1); - final View captureView = findViewByHashCode(root, parameter); - - if (captureView != null) { - final Bitmap[] cache = new Bitmap[1]; - - final boolean hasCache = captureView.isDrawingCacheEnabled(); - final boolean willNotCache = captureView.willNotCacheDrawing(); - - if (willNotCache) { - captureView.setWillNotCacheDrawing(false); - } - - root.post(new Runnable() { - public void run() { - try { - if (!hasCache) { - captureView.buildDrawingCache(); - } - - cache[0] = captureView.getDrawingCache(); - } finally { - latch.countDown(); - } - } - }); - - try { - latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS); - - if (cache[0] != null) { - BufferedOutputStream out = null; - try { - out = new BufferedOutputStream(clientStream, 32 * 1024); - cache[0].compress(Bitmap.CompressFormat.PNG, 100, out); - out.flush(); - } finally { - if (out != null) { - out.close(); - } - } - } - } catch (InterruptedException e) { - Log.w("View", "Could not complete the capture of the view " + captureView); - } finally { - if (willNotCache) { - captureView.setWillNotCacheDrawing(true); - } - if (!hasCache) { - captureView.destroyDrawingCache(); - } - } - } - } - - private static void dump(View root, OutputStream clientStream) throws IOException { - BufferedWriter out = null; - try { - out = new BufferedWriter(new OutputStreamWriter(clientStream), 32 * 1024); - View view = root.getRootView(); - if (view instanceof ViewGroup) { - ViewGroup group = (ViewGroup) view; - dumpViewHierarchyWithProperties(group, out, 0); - } - out.write("DONE."); - out.newLine(); - } finally { - if (out != null) { - out.close(); - } - } - } - - private static View findView(ViewGroup group, String className, int hashCode) { - if (isRequestedView(group, className, hashCode)) { - return group; - } - - final int count = group.getChildCount(); - for (int i = 0; i < count; i++) { - final View view = group.getChildAt(i); - if (view instanceof ViewGroup) { - final View found = findView((ViewGroup) view, className, hashCode); - if (found != null) { - return found; - } - } else if (isRequestedView(view, className, hashCode)) { - return view; - } - } - - return null; - } - - private static boolean isRequestedView(View view, String className, int hashCode) { - return view.getClass().getName().equals(className) && view.hashCode() == hashCode; - } - - private static void dumpViewHierarchyWithProperties(ViewGroup group, - BufferedWriter out, int level) { - if (!dumpViewWithProperties(group, out, level)) { - return; - } - - final int count = group.getChildCount(); - for (int i = 0; i < count; i++) { - final View view = group.getChildAt(i); - if (view instanceof ViewGroup) { - dumpViewHierarchyWithProperties((ViewGroup) view, out, level + 1); - } else { - dumpViewWithProperties(view, out, level + 1); - } - } - } - - private static boolean dumpViewWithProperties(View view, BufferedWriter out, int level) { - try { - for (int i = 0; i < level; i++) { - out.write(' '); - } - out.write(view.getClass().getName()); - out.write('@'); - out.write(Integer.toHexString(view.hashCode())); - out.write(' '); - dumpViewProperties(view, out); - out.newLine(); - } catch (IOException e) { - Log.w("View", "Error while dumping hierarchy tree"); - return false; - } - return true; - } - - private static Field[] getExportedPropertyFields(Class<?> klass) { - if (sFieldsForClasses == null) { - sFieldsForClasses = new HashMap<Class<?>, Field[]>(); - } - final HashMap<Class<?>, Field[]> map = sFieldsForClasses; - - Field[] fields = map.get(klass); - if (fields != null) { - return fields; - } - - final ArrayList<Field> foundFields = new ArrayList<Field>(); - fields = klass.getDeclaredFields(); - - int count = fields.length; - for (int i = 0; i < count; i++) { - final Field field = fields[i]; - if (field.isAnnotationPresent(ExportedProperty.class)) { - field.setAccessible(true); - foundFields.add(field); - } - } - - fields = foundFields.toArray(new Field[foundFields.size()]); - map.put(klass, fields); - - return fields; - } - - private static Method[] getExportedPropertyMethods(Class<?> klass) { - if (sMethodsForClasses == null) { - sMethodsForClasses = new HashMap<Class<?>, Method[]>(); - } - final HashMap<Class<?>, Method[]> map = sMethodsForClasses; - - Method[] methods = map.get(klass); - if (methods != null) { - return methods; - } - - final ArrayList<Method> foundMethods = new ArrayList<Method>(); - methods = klass.getDeclaredMethods(); - - int count = methods.length; - for (int i = 0; i < count; i++) { - final Method method = methods[i]; - if (method.getParameterTypes().length == 0 && - method.isAnnotationPresent(ExportedProperty.class) && - method.getReturnType() != Void.class) { - method.setAccessible(true); - foundMethods.add(method); - } - } - - methods = foundMethods.toArray(new Method[foundMethods.size()]); - map.put(klass, methods); - - return methods; - } - - private static void dumpViewProperties(Object view, BufferedWriter out) throws IOException { - dumpViewProperties(view, out, ""); - } - - private static void dumpViewProperties(Object view, BufferedWriter out, String prefix) - throws IOException { - Class<?> klass = view.getClass(); - - do { - exportFields(view, out, klass, prefix); - exportMethods(view, out, klass, prefix); - klass = klass.getSuperclass(); - } while (klass != Object.class); - } - - private static void exportMethods(Object view, BufferedWriter out, Class<?> klass, - String prefix) throws IOException { - - final Method[] methods = getExportedPropertyMethods(klass); - - int count = methods.length; - for (int i = 0; i < count; i++) { - final Method method = methods[i]; - //noinspection EmptyCatchBlock - try { - // TODO: This should happen on the UI thread - Object methodValue = method.invoke(view, (Object[]) null); - final Class<?> returnType = method.getReturnType(); - - if (returnType == int.class) { - ExportedProperty property = method.getAnnotation(ExportedProperty.class); - if (property.resolveId() && view instanceof View) { - final Resources resources = ((View) view).getContext().getResources(); - final int id = (Integer) methodValue; - if (id >= 0) { - try { - methodValue = resources.getResourceTypeName(id) + '/' + - resources.getResourceEntryName(id); - } catch (Resources.NotFoundException e) { - methodValue = "UNKNOWN"; - } - } else { - methodValue = "NO_ID"; - } - } else { - final IntToString[] mapping = property.mapping(); - if (mapping.length > 0) { - final int intValue = (Integer) methodValue; - boolean mapped = false; - int mappingCount = mapping.length; - for (int j = 0; j < mappingCount; j++) { - final IntToString mapper = mapping[j]; - if (mapper.from() == intValue) { - methodValue = mapper.to(); - mapped = true; - break; - } - } - - if (!mapped) { - methodValue = intValue; - } - } - } - } else if (!returnType.isPrimitive()) { - ExportedProperty property = method.getAnnotation(ExportedProperty.class); - if (property.deepExport()) { - dumpViewProperties(methodValue, out, prefix + property.prefix()); - continue; - } - } - - out.write(prefix); - out.write(method.getName()); - out.write("()="); - - if (methodValue != null) { - final String value = methodValue.toString().replace("\n", "\\n"); - out.write(String.valueOf(value.length())); - out.write(","); - out.write(value); - } else { - out.write("4,null"); - } - - out.write(' '); - } catch (IllegalAccessException e) { - } catch (InvocationTargetException e) { - } - } - } - - private static void exportFields(Object view, BufferedWriter out, Class<?> klass, String prefix) - throws IOException { - final Field[] fields = getExportedPropertyFields(klass); - - int count = fields.length; - for (int i = 0; i < count; i++) { - final Field field = fields[i]; - - //noinspection EmptyCatchBlock - try { - Object fieldValue = null; - final Class<?> type = field.getType(); - - if (type == int.class) { - ExportedProperty property = field.getAnnotation(ExportedProperty.class); - if (property.resolveId() && view instanceof View) { - final Resources resources = ((View) view).getContext().getResources(); - final int id = field.getInt(view); - if (id >= 0) { - try { - fieldValue = resources.getResourceTypeName(id) + '/' + - resources.getResourceEntryName(id); - } catch (Resources.NotFoundException e) { - fieldValue = "UNKNOWN"; - } - } else { - fieldValue = "NO_ID"; - } - } else { - final IntToString[] mapping = property.mapping(); - if (mapping.length > 0) { - final int intValue = field.getInt(view); - int mappingCount = mapping.length; - for (int j = 0; j < mappingCount; j++) { - final IntToString mapped = mapping[j]; - if (mapped.from() == intValue) { - fieldValue = mapped.to(); - break; - } - } - - if (fieldValue == null) { - fieldValue = intValue; - } - } - } - } else if (!type.isPrimitive()) { - ExportedProperty property = field.getAnnotation(ExportedProperty.class); - if (property.deepExport()) { - dumpViewProperties(field.get(view), out, prefix + property.prefix()); - continue; - } - } - - if (fieldValue == null) { - fieldValue = field.get(view); - } - - out.write(prefix); - out.write(field.getName()); - out.write('='); - - if (fieldValue != null) { - final String value = fieldValue.toString().replace("\n", "\\n"); - out.write(String.valueOf(value.length())); - out.write(","); - out.write(value); - } else { - out.write("4,null"); - } - - out.write(' '); - } catch (IllegalAccessException e) { - } - } - } - - private static void dumpViewHierarchy(ViewGroup group, BufferedWriter out, int level) { - if (!dumpView(group, out, level)) { - return; - } - - final int count = group.getChildCount(); - for (int i = 0; i < count; i++) { - final View view = group.getChildAt(i); - if (view instanceof ViewGroup) { - dumpViewHierarchy((ViewGroup) view, out, level + 1); - } else { - dumpView(view, out, level + 1); - } - } - } - - private static boolean dumpView(Object view, BufferedWriter out, int level) { - try { - for (int i = 0; i < level; i++) { - out.write(' '); - } - out.write(view.getClass().getName()); - out.write('@'); - out.write(Integer.toHexString(view.hashCode())); - out.newLine(); - } catch (IOException e) { - Log.w("View", "Error while dumping hierarchy tree"); - return false; - } - return true; - } - - private static Field[] capturedViewGetPropertyFields(Class<?> klass) { - if (mCapturedViewFieldsForClasses == null) { - mCapturedViewFieldsForClasses = new HashMap<Class<?>, Field[]>(); - } - final HashMap<Class<?>, Field[]> map = mCapturedViewFieldsForClasses; - - Field[] fields = map.get(klass); - if (fields != null) { - return fields; - } - - final ArrayList<Field> foundFields = new ArrayList<Field>(); - fields = klass.getFields(); - - int count = fields.length; - for (int i = 0; i < count; i++) { - final Field field = fields[i]; - if (field.isAnnotationPresent(CapturedViewProperty.class)) { - field.setAccessible(true); - foundFields.add(field); - } - } - - fields = foundFields.toArray(new Field[foundFields.size()]); - map.put(klass, fields); - - return fields; - } - - private static Method[] capturedViewGetPropertyMethods(Class<?> klass) { - if (mCapturedViewMethodsForClasses == null) { - mCapturedViewMethodsForClasses = new HashMap<Class<?>, Method[]>(); - } - final HashMap<Class<?>, Method[]> map = mCapturedViewMethodsForClasses; - - Method[] methods = map.get(klass); - if (methods != null) { - return methods; - } - - final ArrayList<Method> foundMethods = new ArrayList<Method>(); - methods = klass.getMethods(); - - int count = methods.length; - for (int i = 0; i < count; i++) { - final Method method = methods[i]; - if (method.getParameterTypes().length == 0 && - method.isAnnotationPresent(CapturedViewProperty.class) && - method.getReturnType() != Void.class) { - method.setAccessible(true); - foundMethods.add(method); - } - } - - methods = foundMethods.toArray(new Method[foundMethods.size()]); - map.put(klass, methods); - - return methods; - } - - private static String capturedViewExportMethods(Object obj, Class<?> klass, - String prefix) { - - if (obj == null) { - return "null"; - } - - StringBuilder sb = new StringBuilder(); - final Method[] methods = capturedViewGetPropertyMethods(klass); - - int count = methods.length; - for (int i = 0; i < count; i++) { - final Method method = methods[i]; - try { - Object methodValue = method.invoke(obj, (Object[]) null); - final Class<?> returnType = method.getReturnType(); - - CapturedViewProperty property = method.getAnnotation(CapturedViewProperty.class); - if (property.retrieveReturn()) { - //we are interested in the second level data only - sb.append(capturedViewExportMethods(methodValue, returnType, method.getName() + "#")); - } else { - sb.append(prefix); - sb.append(method.getName()); - sb.append("()="); - - if (methodValue != null) { - final String value = methodValue.toString().replace("\n", "\\n"); - sb.append(value); - } else { - sb.append("null"); - } - sb.append("; "); - } - } catch (IllegalAccessException e) { - //Exception IllegalAccess, it is OK here - //we simply ignore this method - } catch (InvocationTargetException e) { - //Exception InvocationTarget, it is OK here - //we simply ignore this method - } - } - return sb.toString(); - } - - private static String capturedViewExportFields(Object obj, Class<?> klass, String prefix) { - - if (obj == null) { - return "null"; - } - - StringBuilder sb = new StringBuilder(); - final Field[] fields = capturedViewGetPropertyFields(klass); - - int count = fields.length; - for (int i = 0; i < count; i++) { - final Field field = fields[i]; - try { - Object fieldValue = field.get(obj); - - sb.append(prefix); - sb.append(field.getName()); - sb.append("="); - - if (fieldValue != null) { - final String value = fieldValue.toString().replace("\n", "\\n"); - sb.append(value); - } else { - sb.append("null"); - } - sb.append(' '); - } catch (IllegalAccessException e) { - //Exception IllegalAccess, it is OK here - //we simply ignore this field - } - } - return sb.toString(); - } - - /** - * dump view info for id based instrument test generation - * (and possibly further data analysis). The results are dumped - * to the log. - * @param tag for log - * @param view for dump - * - * @hide pending API Council approval - */ - public static void dumpCapturedView(String tag, Object view) { - Class<?> klass = view.getClass(); - StringBuilder sb = new StringBuilder(klass.getName() + ": "); - sb.append(capturedViewExportFields(view, klass, "")); - sb.append(capturedViewExportMethods(view, klass, "")); - Log.d(tag, sb.toString()); - } -} diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java deleted file mode 100644 index 70cc2a9..0000000 --- a/core/java/android/view/ViewGroup.java +++ /dev/null @@ -1,3478 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import com.android.internal.R; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.Region; -import android.graphics.RectF; -import android.os.Parcelable; -import android.os.SystemClock; -import android.util.AttributeSet; -import android.util.EventLog; -import android.util.Log; -import android.util.SparseArray; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.view.animation.LayoutAnimationController; -import android.view.animation.Transformation; - -import java.util.ArrayList; - -/** - * <p> - * A <code>ViewGroup</code> is a special view that can contain other views - * (called children.) The view group is the base class for layouts and views - * containers. This class also defines the - * {@link android.view.ViewGroup.LayoutParams} class which serves as the base - * class for layouts parameters. - * </p> - * - * <p> - * Also see {@link LayoutParams} for layout attributes. - * </p> - */ -public abstract class ViewGroup extends View implements ViewParent, ViewManager { - private static final boolean DBG = false; - - /** - * Views which have been hidden or removed which need to be animated on - * their way out. - * This field should be made private, so it is hidden from the SDK. - * {@hide} - */ - protected ArrayList<View> mDisappearingChildren; - - /** - * Listener used to propagate events indicating when children are added - * and/or removed from a view group. - * This field should be made private, so it is hidden from the SDK. - * {@hide} - */ - protected OnHierarchyChangeListener mOnHierarchyChangeListener; - - // The view contained within this ViewGroup that has or contains focus. - private View mFocused; - - // The current transformation to apply on the child being drawn - private Transformation mChildTransformation; - private RectF mInvalidateRegion; - - // Target of Motion events - private View mMotionTarget; - private final Rect mTempRect = new Rect(); - - // Layout animation - private LayoutAnimationController mLayoutAnimationController; - private Animation.AnimationListener mAnimationListener; - - /** - * Internal flags. - * - * This field should be made private, so it is hidden from the SDK. - * {@hide} - */ - protected int mGroupFlags; - - // When set, ViewGroup invalidates only the child's rectangle - // Set by default - private static final int FLAG_CLIP_CHILDREN = 0x1; - - // When set, ViewGroup excludes the padding area from the invalidate rectangle - // Set by default - private static final int FLAG_CLIP_TO_PADDING = 0x2; - - // When set, dispatchDraw() will invoke invalidate(); this is set by drawChild() when - // a child needs to be invalidated and FLAG_OPTIMIZE_INVALIDATE is set - private static final int FLAG_INVALIDATE_REQUIRED = 0x4; - - // When set, dispatchDraw() will run the layout animation and unset the flag - private static final int FLAG_RUN_ANIMATION = 0x8; - - // When set, there is either no layout animation on the ViewGroup or the layout - // animation is over - // Set by default - private static final int FLAG_ANIMATION_DONE = 0x10; - - // If set, this ViewGroup has padding; if unset there is no padding and we don't need - // to clip it, even if FLAG_CLIP_TO_PADDING is set - private static final int FLAG_PADDING_NOT_NULL = 0x20; - - // When set, this ViewGroup caches its children in a Bitmap before starting a layout animation - // Set by default - private static final int FLAG_ANIMATION_CACHE = 0x40; - - // When set, this ViewGroup converts calls to invalidate(Rect) to invalidate() during a - // layout animation; this avoid clobbering the hierarchy - // Automatically set when the layout animation starts, depending on the animation's - // characteristics - private static final int FLAG_OPTIMIZE_INVALIDATE = 0x80; - - // When set, the next call to drawChild() will clear mChildTransformation's matrix - private static final int FLAG_CLEAR_TRANSFORMATION = 0x100; - - // When set, this ViewGroup invokes mAnimationListener.onAnimationEnd() and removes - // the children's Bitmap caches if necessary - // This flag is set when the layout animation is over (after FLAG_ANIMATION_DONE is set) - private static final int FLAG_NOTIFY_ANIMATION_LISTENER = 0x200; - - /** - * When set, the drawing method will call {@link #getChildDrawingOrder(int, int)} - * to get the index of the child to draw for that iteration. - */ - protected static final int FLAG_USE_CHILD_DRAWING_ORDER = 0x400; - - /** - * When set, this ViewGroup supports static transformations on children; this causes - * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} to be - * invoked when a child is drawn. - * - * Any subclass overriding - * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} should - * set this flags in {@link #mGroupFlags}. - * - * {@hide} - */ - protected static final int FLAG_SUPPORT_STATIC_TRANSFORMATIONS = 0x800; - - // When the previous drawChild() invocation used an alpha value that was lower than - // 1.0 and set it in mCachePaint - private static final int FLAG_ALPHA_LOWER_THAN_ONE = 0x1000; - - /** - * When set, this ViewGroup's drawable states also include those - * of its children. - */ - private static final int FLAG_ADD_STATES_FROM_CHILDREN = 0x2000; - - /** - * When set, this ViewGroup tries to always draw its children using their drawing cache. - */ - private static final int FLAG_ALWAYS_DRAWN_WITH_CACHE = 0x4000; - - /** - * When set, and if FLAG_ALWAYS_DRAWN_WITH_CACHE is not set, this ViewGroup will try to - * draw its children with their drawing cache. - */ - private static final int FLAG_CHILDREN_DRAWN_WITH_CACHE = 0x8000; - - /** - * When set, this group will go through its list of children to notify them of - * any drawable state change. - */ - private static final int FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE = 0x10000; - - private static final int FLAG_MASK_FOCUSABILITY = 0x60000; - - /** - * This view will get focus before any of its descendants. - */ - public static final int FOCUS_BEFORE_DESCENDANTS = 0x20000; - - /** - * This view will get focus only if none of its descendants want it. - */ - public static final int FOCUS_AFTER_DESCENDANTS = 0x40000; - - /** - * This view will block any of its descendants from getting focus, even - * if they are focusable. - */ - public static final int FOCUS_BLOCK_DESCENDANTS = 0x60000; - - /** - * Used to map between enum in attrubutes and flag values. - */ - private static final int[] DESCENDANT_FOCUSABILITY_FLAGS = - {FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS, - FOCUS_BLOCK_DESCENDANTS}; - - /** - * When set, this ViewGroup should not intercept touch events. - */ - private static final int FLAG_DISALLOW_INTERCEPT = 0x80000; - - /** - * Indicates which types of drawing caches are to be kept in memory. - * This field should be made private, so it is hidden from the SDK. - * {@hide} - */ - protected int mPersistentDrawingCache; - - /** - * Used to indicate that no drawing cache should be kept in memory. - */ - public static final int PERSISTENT_NO_CACHE = 0x0; - - /** - * Used to indicate that the animation drawing cache should be kept in memory. - */ - public static final int PERSISTENT_ANIMATION_CACHE = 0x1; - - /** - * Used to indicate that the scrolling drawing cache should be kept in memory. - */ - public static final int PERSISTENT_SCROLLING_CACHE = 0x2; - - /** - * Used to indicate that all drawing caches should be kept in memory. - */ - public static final int PERSISTENT_ALL_CACHES = 0x3; - - /** - * We clip to padding when FLAG_CLIP_TO_PADDING and FLAG_PADDING_NOT_NULL - * are set at the same time. - */ - protected static final int CLIP_TO_PADDING_MASK = FLAG_CLIP_TO_PADDING | FLAG_PADDING_NOT_NULL; - - // Index of the child's left position in the mLocation array - private static final int CHILD_LEFT_INDEX = 0; - // Index of the child's top position in the mLocation array - private static final int CHILD_TOP_INDEX = 1; - - // Child views of this ViewGroup - private View[] mChildren; - // Number of valid children in the mChildren array, the rest should be null or not - // considered as children - private int mChildrenCount; - - private static final int ARRAY_INITIAL_CAPACITY = 12; - private static final int ARRAY_CAPACITY_INCREMENT = 12; - - // Used to draw cached views - private final Paint mCachePaint = new Paint(); - - public ViewGroup(Context context) { - super(context); - initViewGroup(); - } - - public ViewGroup(Context context, AttributeSet attrs) { - super(context, attrs); - initViewGroup(); - initFromAttributes(context, attrs); - } - - public ViewGroup(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - initViewGroup(); - initFromAttributes(context, attrs); - } - - private void initViewGroup() { - // ViewGroup doesn't draw by default - setFlags(WILL_NOT_DRAW, DRAW_MASK); - mGroupFlags |= FLAG_CLIP_CHILDREN; - mGroupFlags |= FLAG_CLIP_TO_PADDING; - mGroupFlags |= FLAG_ANIMATION_DONE; - mGroupFlags |= FLAG_ANIMATION_CACHE; - mGroupFlags |= FLAG_ALWAYS_DRAWN_WITH_CACHE; - - setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS); - - mChildren = new View[ARRAY_INITIAL_CAPACITY]; - mChildrenCount = 0; - - mCachePaint.setDither(false); - - mPersistentDrawingCache = PERSISTENT_SCROLLING_CACHE; - } - - private void initFromAttributes(Context context, AttributeSet attrs) { - TypedArray a = context.obtainStyledAttributes(attrs, - R.styleable.ViewGroup); - - final int N = a.getIndexCount(); - for (int i = 0; i < N; i++) { - int attr = a.getIndex(i); - switch (attr) { - case R.styleable.ViewGroup_clipChildren: - setClipChildren(a.getBoolean(attr, true)); - break; - case R.styleable.ViewGroup_clipToPadding: - setClipToPadding(a.getBoolean(attr, true)); - break; - case R.styleable.ViewGroup_animationCache: - setAnimationCacheEnabled(a.getBoolean(attr, true)); - break; - case R.styleable.ViewGroup_persistentDrawingCache: - setPersistentDrawingCache(a.getInt(attr, PERSISTENT_SCROLLING_CACHE)); - break; - case R.styleable.ViewGroup_addStatesFromChildren: - setAddStatesFromChildren(a.getBoolean(attr, false)); - break; - case R.styleable.ViewGroup_alwaysDrawnWithCache: - setAlwaysDrawnWithCacheEnabled(a.getBoolean(attr, true)); - break; - case R.styleable.ViewGroup_layoutAnimation: - int id = a.getResourceId(attr, -1); - if (id > 0) { - setLayoutAnimation(AnimationUtils.loadLayoutAnimation(mContext, id)); - } - break; - case R.styleable.ViewGroup_descendantFocusability: - setDescendantFocusability(DESCENDANT_FOCUSABILITY_FLAGS[a.getInt(attr, 0)]); - break; - } - } - - a.recycle(); - } - - /** - * Gets the descendant focusability of this view group. The descendant - * focusability defines the relationship between this view group and its - * descendants when looking for a view to take focus in - * {@link #requestFocus(int, android.graphics.Rect)}. - * - * @return one of {@link #FOCUS_BEFORE_DESCENDANTS}, {@link #FOCUS_AFTER_DESCENDANTS}, - * {@link #FOCUS_BLOCK_DESCENDANTS}. - */ - @ViewDebug.ExportedProperty(mapping = { - @ViewDebug.IntToString(from = FOCUS_BEFORE_DESCENDANTS, to = "FOCUS_BEFORE_DESCENDANTS"), - @ViewDebug.IntToString(from = FOCUS_AFTER_DESCENDANTS, to = "FOCUS_AFTER_DESCENDANTS"), - @ViewDebug.IntToString(from = FOCUS_BLOCK_DESCENDANTS, to = "FOCUS_BLOCK_DESCENDANTS") - }) - public int getDescendantFocusability() { - return mGroupFlags & FLAG_MASK_FOCUSABILITY; - } - - /** - * Set the descendant focusability of this view group. This defines the relationship - * between this view group and its descendants when looking for a view to - * take focus in {@link #requestFocus(int, android.graphics.Rect)}. - * - * @param focusability one of {@link #FOCUS_BEFORE_DESCENDANTS}, {@link #FOCUS_AFTER_DESCENDANTS}, - * {@link #FOCUS_BLOCK_DESCENDANTS}. - */ - public void setDescendantFocusability(int focusability) { - switch (focusability) { - case FOCUS_BEFORE_DESCENDANTS: - case FOCUS_AFTER_DESCENDANTS: - case FOCUS_BLOCK_DESCENDANTS: - break; - default: - throw new IllegalArgumentException("must be one of FOCUS_BEFORE_DESCENDANTS, " - + "FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS"); - } - mGroupFlags &= ~FLAG_MASK_FOCUSABILITY; - mGroupFlags |= (focusability & FLAG_MASK_FOCUSABILITY); - } - - /** - * {@inheritDoc} - */ - @Override - void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) { - if (mFocused != null) { - mFocused.unFocus(); - mFocused = null; - } - super.handleFocusGainInternal(direction, previouslyFocusedRect); - } - - /** - * {@inheritDoc} - */ - public void requestChildFocus(View child, View focused) { - if (DBG) { - System.out.println(this + " requestChildFocus()"); - } - if (getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS) { - return; - } - - // Unfocus us, if necessary - super.unFocus(); - - // We had a previous notion of who had focus. Clear it. - if (mFocused != child) { - if (mFocused != null) { - mFocused.unFocus(); - } - - mFocused = child; - } - if (mParent != null) { - mParent.requestChildFocus(this, focused); - } - } - - /** - * {@inheritDoc} - */ - public void focusableViewAvailable(View v) { - if (mParent != null - // shortcut: don't report a new focusable view if we block our descendants from - // getting focus - && (getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS) - // shortcut: don't report a new focusable view if we already are focused - // (and we don't prefer our descendants) - // - // note: knowing that mFocused is non-null is not a good enough reason - // to break the traversal since in that case we'd actually have to find - // the focused view and make sure it wasn't FOCUS_AFTER_DESCENDANTS and - // an ancestor of v; this will get checked for at ViewRoot - && !(isFocused() && getDescendantFocusability() != FOCUS_AFTER_DESCENDANTS)) { - mParent.focusableViewAvailable(v); - } - } - - /** - * {@inheritDoc} - */ - public boolean showContextMenuForChild(View originalView) { - return mParent != null && mParent.showContextMenuForChild(originalView); - } - - /** - * Find the nearest view in the specified direction that wants to take - * focus. - * - * @param focused The view that currently has focus - * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and - * FOCUS_RIGHT, or 0 for not applicable. - */ - public View focusSearch(View focused, int direction) { - if (isRootNamespace()) { - // root namespace means we should consider ourselves the top of the - // tree for focus searching; otherwise we could be focus searching - // into other tabs. see LocalActivityManager and TabHost for more info - return FocusFinder.getInstance().findNextFocus(this, focused, direction); - } else if (mParent != null) { - return mParent.focusSearch(focused, direction); - } - return null; - } - - /** - * {@inheritDoc} - */ - public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean dispatchUnhandledMove(View focused, int direction) { - return mFocused != null && - mFocused.dispatchUnhandledMove(focused, direction); - } - - /** - * {@inheritDoc} - */ - public void clearChildFocus(View child) { - if (DBG) { - System.out.println(this + " clearChildFocus()"); - } - - mFocused = null; - if (mParent != null) { - mParent.clearChildFocus(this); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void clearFocus() { - super.clearFocus(); - - // clear any child focus if it exists - if (mFocused != null) { - mFocused.clearFocus(); - } - } - - /** - * {@inheritDoc} - */ - @Override - void unFocus() { - if (DBG) { - System.out.println(this + " unFocus()"); - } - - super.unFocus(); - if (mFocused != null) { - mFocused.unFocus(); - } - mFocused = null; - } - - /** - * Returns the focused child of this view, if any. The child may have focus - * or contain focus. - * - * @return the focused child or null. - */ - public View getFocusedChild() { - return mFocused; - } - - /** - * Returns true if this view has or contains focus - * - * @return true if this view has or contains focus - */ - @Override - public boolean hasFocus() { - return (mPrivateFlags & FOCUSED) != 0 || mFocused != null; - } - - /* - * (non-Javadoc) - * - * @see android.view.View#findFocus() - */ - @Override - public View findFocus() { - if (DBG) { - System.out.println("Find focus in " + this + ": flags=" - + isFocused() + ", child=" + mFocused); - } - - if (isFocused()) { - return this; - } - - if (mFocused != null) { - return mFocused.findFocus(); - } - return null; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean hasFocusable() { - if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) { - return false; - } - - if (isFocusable()) { - return true; - } - - final int descendantFocusability = getDescendantFocusability(); - if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { - final int count = mChildrenCount; - final View[] children = mChildren; - - for (int i = 0; i < count; i++) { - final View child = children[i]; - if (child.hasFocusable()) { - return true; - } - } - } - - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public void addFocusables(ArrayList<View> views, int direction) { - final int focusableCount = views.size(); - - final int descendantFocusability = getDescendantFocusability(); - - if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { - final int count = mChildrenCount; - final View[] children = mChildren; - - for (int i = 0; i < count; i++) { - final View child = children[i]; - if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { - child.addFocusables(views, direction); - } - } - } - - // we add ourselves (if focusable) in all cases except for when we are - // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is - // to avoid the focus search finding layouts when a more precise search - // among the focusable children would be more interesting. - if ( - descendantFocusability != FOCUS_AFTER_DESCENDANTS || - // No focusable descendants - (focusableCount == views.size())) { - super.addFocusables(views, direction); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void dispatchWindowFocusChanged(boolean hasFocus) { - super.dispatchWindowFocusChanged(hasFocus); - final int count = mChildrenCount; - final View[] children = mChildren; - for (int i = 0; i < count; i++) { - children[i].dispatchWindowFocusChanged(hasFocus); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void addTouchables(ArrayList<View> views) { - super.addTouchables(views); - - final int count = mChildrenCount; - final View[] children = mChildren; - - for (int i = 0; i < count; i++) { - final View child = children[i]; - if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { - child.addTouchables(views); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public void dispatchWindowVisibilityChanged(int visibility) { - super.dispatchWindowVisibilityChanged(visibility); - final int count = mChildrenCount; - final View[] children = mChildren; - for (int i = 0; i < count; i++) { - children[i].dispatchWindowVisibilityChanged(visibility); - } - } - - /** - * {@inheritDoc} - */ - public void recomputeViewAttributes(View child) { - ViewParent parent = mParent; - if (parent != null) parent.recomputeViewAttributes(this); - } - - @Override - void dispatchCollectViewAttributes(int visibility) { - visibility |= mViewFlags&VISIBILITY_MASK; - super.dispatchCollectViewAttributes(visibility); - final int count = mChildrenCount; - final View[] children = mChildren; - for (int i = 0; i < count; i++) { - children[i].dispatchCollectViewAttributes(visibility); - } - } - - /** - * {@inheritDoc} - */ - public void bringChildToFront(View child) { - int index = indexOfChild(child); - if (index >= 0) { - removeFromArray(index); - addInArray(child, mChildrenCount); - child.mParent = this; - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean dispatchKeyEventPreIme(KeyEvent event) { - if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) { - return super.dispatchKeyEventPreIme(event); - } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) { - return mFocused.dispatchKeyEventPreIme(event); - } - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) { - return super.dispatchKeyEvent(event); - } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) { - return mFocused.dispatchKeyEvent(event); - } - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean dispatchKeyShortcutEvent(KeyEvent event) { - if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) { - return super.dispatchKeyShortcutEvent(event); - } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) { - return mFocused.dispatchKeyShortcutEvent(event); - } - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean dispatchTrackballEvent(MotionEvent event) { - if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) { - return super.dispatchTrackballEvent(event); - } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) { - return mFocused.dispatchTrackballEvent(event); - } - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - final int action = ev.getAction(); - final float xf = ev.getX(); - final float yf = ev.getY(); - final float scrolledXFloat = xf + mScrollX; - final float scrolledYFloat = yf + mScrollY; - final Rect frame = mTempRect; - - boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0; - - if (action == MotionEvent.ACTION_DOWN) { - if (mMotionTarget != null) { - // this is weird, we got a pen down, but we thought it was - // already down! - // XXX: We should probably send an ACTION_UP to the current - // target. - mMotionTarget = null; - } - // If we're disallowing intercept or if we're allowing and we didn't - // intercept - if (disallowIntercept || !onInterceptTouchEvent(ev)) { - // reset this event's action (just to protect ourselves) - ev.setAction(MotionEvent.ACTION_DOWN); - // We know we want to dispatch the event down, find a child - // who can handle it, start with the front-most child. - final int scrolledXInt = (int) scrolledXFloat; - final int scrolledYInt = (int) scrolledYFloat; - final View[] children = mChildren; - final int count = mChildrenCount; - for (int i = count - 1; i >= 0; i--) { - final View child = children[i]; - if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE - || child.getAnimation() != null) { - child.getHitRect(frame); - if (frame.contains(scrolledXInt, scrolledYInt)) { - // offset the event to the view's coordinate system - final float xc = scrolledXFloat - child.mLeft; - final float yc = scrolledYFloat - child.mTop; - ev.setLocation(xc, yc); - if (child.dispatchTouchEvent(ev)) { - // Event handled, we have a target now. - mMotionTarget = child; - return true; - } - // The event didn't get handled, try the next view. - // Don't reset the event's location, it's not - // necessary here. - } - } - } - } - } - - boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) || - (action == MotionEvent.ACTION_CANCEL); - - if (isUpOrCancel) { - // Note, we've already copied the previous state to our local - // variable, so this takes effect on the next event - mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT; - } - - // The event wasn't an ACTION_DOWN, dispatch it to our target if - // we have one. - final View target = mMotionTarget; - if (target == null) { - // We don't have a target, this means we're handling the - // event as a regular view. - ev.setLocation(xf, yf); - return super.dispatchTouchEvent(ev); - } - - // if have a target, see if we're allowed to and want to intercept its - // events - if (!disallowIntercept && onInterceptTouchEvent(ev)) { - final float xc = scrolledXFloat - (float) target.mLeft; - final float yc = scrolledYFloat - (float) target.mTop; - ev.setAction(MotionEvent.ACTION_CANCEL); - ev.setLocation(xc, yc); - if (!target.dispatchTouchEvent(ev)) { - // target didn't handle ACTION_CANCEL. not much we can do - // but they should have. - } - // clear the target - mMotionTarget = null; - // Don't dispatch this event to our own view, because we already - // saw it when intercepting; we just want to give the following - // event to the normal onTouchEvent(). - return true; - } - - if (isUpOrCancel) { - mMotionTarget = null; - } - - // finally offset the event to the target's coordinate system and - // dispatch the event. - final float xc = scrolledXFloat - (float) target.mLeft; - final float yc = scrolledYFloat - (float) target.mTop; - ev.setLocation(xc, yc); - - return target.dispatchTouchEvent(ev); - } - - /** - * {@inheritDoc} - */ - public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { - - if (disallowIntercept == ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0)) { - // We're already in this state, assume our ancestors are too - return; - } - - if (disallowIntercept) { - mGroupFlags |= FLAG_DISALLOW_INTERCEPT; - } else { - mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT; - } - - // Pass it up to our parent - if (mParent != null) { - mParent.requestDisallowInterceptTouchEvent(disallowIntercept); - } - } - - /** - * Implement this method to intercept all touch screen motion events. This - * allows you to watch events as they are dispatched to your children, and - * take ownership of the current gesture at any point. - * - * <p>Using this function takes some care, as it has a fairly complicated - * interaction with {@link View#onTouchEvent(MotionEvent) - * View.onTouchEvent(MotionEvent)}, and using it requires implementing - * that method as well as this one in the correct way. Events will be - * received in the following order: - * - * <ol> - * <li> You will receive the down event here. - * <li> The down event will be handled either by a child of this view - * group, or given to your own onTouchEvent() method to handle; this means - * you should implement onTouchEvent() to return true, so you will - * continue to see the rest of the gesture (instead of looking for - * a parent view to handle it). Also, by returning true from - * onTouchEvent(), you will not receive any following - * events in onInterceptTouchEvent() and all touch processing must - * happen in onTouchEvent() like normal. - * <li> For as long as you return false from this function, each following - * event (up to and including the final up) will be delivered first here - * and then to the target's onTouchEvent(). - * <li> If you return true from here, you will not receive any - * following events: the target view will receive the same event but - * with the action {@link MotionEvent#ACTION_CANCEL}, and all further - * events will be delivered to your onTouchEvent() method and no longer - * appear here. - * </ol> - * - * @param ev The motion event being dispatched down the hierarchy. - * @return Return true to steal motion events from the children and have - * them dispatched to this ViewGroup through onTouchEvent(). - * The current target will receive an ACTION_CANCEL event, and no further - * messages will be delivered here. - */ - public boolean onInterceptTouchEvent(MotionEvent ev) { - return false; - } - - /** - * {@inheritDoc} - * - * Looks for a view to give focus to respecting the setting specified by - * {@link #getDescendantFocusability()}. - * - * Uses {@link #onRequestFocusInDescendants(int, android.graphics.Rect)} to - * find focus within the children of this group when appropriate. - * - * @see #FOCUS_BEFORE_DESCENDANTS - * @see #FOCUS_AFTER_DESCENDANTS - * @see #FOCUS_BLOCK_DESCENDANTS - * @see #onRequestFocusInDescendants - */ - @Override - public boolean requestFocus(int direction, Rect previouslyFocusedRect) { - if (DBG) { - System.out.println(this + " ViewGroup.requestFocus direction=" - + direction); - } - int descendantFocusability = getDescendantFocusability(); - - switch (descendantFocusability) { - case FOCUS_BLOCK_DESCENDANTS: - return super.requestFocus(direction, previouslyFocusedRect); - case FOCUS_BEFORE_DESCENDANTS: { - final boolean took = super.requestFocus(direction, previouslyFocusedRect); - return took ? took : onRequestFocusInDescendants(direction, previouslyFocusedRect); - } - case FOCUS_AFTER_DESCENDANTS: { - final boolean took = onRequestFocusInDescendants(direction, previouslyFocusedRect); - return took ? took : super.requestFocus(direction, previouslyFocusedRect); - } - default: - throw new IllegalStateException("descendant focusability must be " - + "one of FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS " - + "but is " + descendantFocusability); - } - } - - /** - * Look for a descendant to call {@link View#requestFocus} on. - * Called by {@link ViewGroup#requestFocus(int, android.graphics.Rect)} - * when it wants to request focus within its children. Override this to - * customize how your {@link ViewGroup} requests focus within its children. - * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT - * @param previouslyFocusedRect The rectangle (in this View's coordinate system) - * to give a finer grained hint about where focus is coming from. May be null - * if there is no hint. - * @return Whether focus was taken. - */ - @SuppressWarnings({"ConstantConditions"}) - protected boolean onRequestFocusInDescendants(int direction, - Rect previouslyFocusedRect) { - int index; - int increment; - int end; - int count = mChildrenCount; - if ((direction & FOCUS_FORWARD) != 0) { - index = 0; - increment = 1; - end = count; - } else { - index = count - 1; - increment = -1; - end = -1; - } - final View[] children = mChildren; - for (int i = index; i != end; i += increment) { - View child = children[i]; - if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { - if (child.requestFocus(direction, previouslyFocusedRect)) { - return true; - } - } - } - return false; - } - - /** - * {@inheritDoc} - */ - @Override - void dispatchAttachedToWindow(AttachInfo info, int visibility) { - super.dispatchAttachedToWindow(info, visibility); - visibility |= mViewFlags & VISIBILITY_MASK; - final int count = mChildrenCount; - final View[] children = mChildren; - for (int i = 0; i < count; i++) { - children[i].dispatchAttachedToWindow(info, visibility); - } - } - - /** - * {@inheritDoc} - */ - @Override - void dispatchDetachedFromWindow() { - // If we still have a motion target, we are still in the process of - // dispatching motion events to a child; we need to get rid of that - // child to avoid dispatching events to it after the window is torn - // down. To make sure we keep the child in a consistent state, we - // first send it an ACTION_CANCEL motion event. - if (mMotionTarget != null) { - final long now = SystemClock.uptimeMillis(); - final MotionEvent event = MotionEvent.obtain(now, now, - MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); - mMotionTarget.dispatchTouchEvent(event); - event.recycle(); - mMotionTarget = null; - } - - final int count = mChildrenCount; - final View[] children = mChildren; - for (int i = 0; i < count; i++) { - children[i].dispatchDetachedFromWindow(); - } - super.dispatchDetachedFromWindow(); - } - - /** - * {@inheritDoc} - */ - @Override - public void setPadding(int left, int top, int right, int bottom) { - super.setPadding(left, top, right, bottom); - - if ((mPaddingLeft | mPaddingTop | mPaddingRight | mPaddingRight) != 0) { - mGroupFlags |= FLAG_PADDING_NOT_NULL; - } else { - mGroupFlags &= ~FLAG_PADDING_NOT_NULL; - } - } - - /** - * {@inheritDoc} - */ - @Override - protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { - super.dispatchSaveInstanceState(container); - final int count = mChildrenCount; - final View[] children = mChildren; - for (int i = 0; i < count; i++) { - children[i].dispatchSaveInstanceState(container); - } - } - - /** - * Perform dispatching of a {@link #saveHierarchyState freeze()} to only this view, - * not to its children. For use when overriding - * {@link #dispatchSaveInstanceState dispatchFreeze()} to allow subclasses to freeze - * their own state but not the state of their children. - * - * @param container the container - */ - protected void dispatchFreezeSelfOnly(SparseArray<Parcelable> container) { - super.dispatchSaveInstanceState(container); - } - - /** - * {@inheritDoc} - */ - @Override - protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { - super.dispatchRestoreInstanceState(container); - final int count = mChildrenCount; - final View[] children = mChildren; - for (int i = 0; i < count; i++) { - children[i].dispatchRestoreInstanceState(container); - } - } - - /** - * Perform dispatching of a {@link #restoreHierarchyState thaw()} to only this view, - * not to its children. For use when overriding - * {@link #dispatchRestoreInstanceState dispatchThaw()} to allow subclasses to thaw - * their own state but not the state of their children. - * - * @param container the container - */ - protected void dispatchThawSelfOnly(SparseArray<Parcelable> container) { - super.dispatchRestoreInstanceState(container); - } - - /** - * Enables or disables the drawing cache for each child of this view group. - * - * @param enabled true to enable the cache, false to dispose of it - */ - protected void setChildrenDrawingCacheEnabled(boolean enabled) { - if (enabled || (mPersistentDrawingCache & PERSISTENT_ALL_CACHES) != PERSISTENT_ALL_CACHES) { - final View[] children = mChildren; - final int count = mChildrenCount; - for (int i = 0; i < count; i++) { - children[i].setDrawingCacheEnabled(enabled); - } - } - } - - @Override - protected void onAnimationStart() { - super.onAnimationStart(); - - // When this ViewGroup's animation starts, build the cache for the children - if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) { - final int count = mChildrenCount; - final View[] children = mChildren; - - for (int i = 0; i < count; i++) { - final View child = children[i]; - if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { - child.setDrawingCacheEnabled(true); - child.buildDrawingCache(); - } - } - - mGroupFlags |= FLAG_CHILDREN_DRAWN_WITH_CACHE; - } - } - - @Override - protected void onAnimationEnd() { - super.onAnimationEnd(); - - // When this ViewGroup's animation ends, destroy the cache of the children - if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) { - mGroupFlags &= ~FLAG_CHILDREN_DRAWN_WITH_CACHE; - - if ((mPersistentDrawingCache & PERSISTENT_ANIMATION_CACHE) == 0) { - setChildrenDrawingCacheEnabled(false); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - protected void dispatchDraw(Canvas canvas) { - final int count = mChildrenCount; - final View[] children = mChildren; - int flags = mGroupFlags; - - if ((flags & FLAG_RUN_ANIMATION) != 0 && canAnimate()) { - final boolean cache = (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE; - - for (int i = 0; i < count; i++) { - final View child = children[i]; - if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { - final LayoutParams params = child.getLayoutParams(); - attachLayoutAnimationParameters(child, params, i, count); - bindLayoutAnimation(child); - if (cache) { - child.setDrawingCacheEnabled(true); - child.buildDrawingCache(); - } - } - } - - final LayoutAnimationController controller = mLayoutAnimationController; - if (controller.willOverlap()) { - mGroupFlags |= FLAG_OPTIMIZE_INVALIDATE; - } - - controller.start(); - - mGroupFlags &= ~FLAG_RUN_ANIMATION; - mGroupFlags &= ~FLAG_ANIMATION_DONE; - - if (cache) { - mGroupFlags |= FLAG_CHILDREN_DRAWN_WITH_CACHE; - } - - if (mAnimationListener != null) { - mAnimationListener.onAnimationStart(controller.getAnimation()); - } - } - - int saveCount = 0; - final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK; - if (clipToPadding) { - saveCount = canvas.save(); - final int scrollX = mScrollX; - final int scrollY = mScrollY; - canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop, - scrollX + mRight - mLeft - mPaddingRight, - scrollY + mBottom - mTop - mPaddingBottom); - - } - - // We will draw our child's animation, let's reset the flag - mPrivateFlags &= ~DRAW_ANIMATION; - mGroupFlags &= ~FLAG_INVALIDATE_REQUIRED; - - boolean more = false; - final long drawingTime = getDrawingTime(); - - if ((flags & FLAG_USE_CHILD_DRAWING_ORDER) == 0) { - for (int i = 0; i < count; i++) { - final View child = children[i]; - if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) { - more |= drawChild(canvas, child, drawingTime); - } - } - } else { - for (int i = 0; i < count; i++) { - final View child = children[getChildDrawingOrder(count, i)]; - if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) { - more |= drawChild(canvas, child, drawingTime); - } - } - } - - // Draw any disappearing views that have animations - if (mDisappearingChildren != null) { - final ArrayList<View> disappearingChildren = mDisappearingChildren; - final int disappearingCount = disappearingChildren.size() - 1; - // Go backwards -- we may delete as animations finish - for (int i = disappearingCount; i >= 0; i--) { - final View child = disappearingChildren.get(i); - more |= drawChild(canvas, child, drawingTime); - } - } - - if (clipToPadding) { - canvas.restoreToCount(saveCount); - } - - // mGroupFlags might have been updated by drawChild() - flags = mGroupFlags; - - if ((flags & FLAG_INVALIDATE_REQUIRED) == FLAG_INVALIDATE_REQUIRED) { - invalidate(); - } - - if ((flags & FLAG_ANIMATION_DONE) == 0 && (flags & FLAG_NOTIFY_ANIMATION_LISTENER) == 0 && - mLayoutAnimationController.isDone() && !more) { - // We want to erase the drawing cache and notify the listener after the - // next frame is drawn because one extra invalidate() is caused by - // drawChild() after the animation is over - mGroupFlags |= FLAG_NOTIFY_ANIMATION_LISTENER; - final Runnable end = new Runnable() { - public void run() { - notifyAnimationListener(); - } - }; - post(end); - } - } - - /** - * Returns the index of the child to draw for this iteration. Override this - * if you want to change the drawing order of children. By default, it - * returns i. - * <p> - * NOTE: In order for this method to be called, the - * {@link #FLAG_USE_CHILD_DRAWING_ORDER} must be set. - * - * @param i The current iteration. - * @return The index of the child to draw this iteration. - */ - protected int getChildDrawingOrder(int childCount, int i) { - return i; - } - - private void notifyAnimationListener() { - mGroupFlags &= ~FLAG_NOTIFY_ANIMATION_LISTENER; - mGroupFlags |= FLAG_ANIMATION_DONE; - - if (mAnimationListener != null) { - final Runnable end = new Runnable() { - public void run() { - mAnimationListener.onAnimationEnd(mLayoutAnimationController.getAnimation()); - } - }; - post(end); - } - - if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) { - mGroupFlags &= ~FLAG_CHILDREN_DRAWN_WITH_CACHE; - if ((mPersistentDrawingCache & PERSISTENT_ANIMATION_CACHE) == 0) { - setChildrenDrawingCacheEnabled(false); - } - } - - invalidate(); - } - - /** - * Draw one child of this View Group. This method is responsible for getting - * the canvas in the right state. This includes clipping, translating so - * that the child's scrolled origin is at 0, 0, and applying any animation - * transformations. - * - * @param canvas The canvas on which to draw the child - * @param child Who to draw - * @param drawingTime The time at which draw is occuring - * @return True if an invalidate() was issued - */ - protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - boolean more = false; - - final int cl = child.mLeft; - final int ct = child.mTop; - final int cr = child.mRight; - final int cb = child.mBottom; - - final int flags = mGroupFlags; - - if ((flags & FLAG_CLEAR_TRANSFORMATION) == FLAG_CLEAR_TRANSFORMATION) { - if (mChildTransformation != null) { - mChildTransformation.clear(); - } - mGroupFlags &= ~FLAG_CLEAR_TRANSFORMATION; - } - - Transformation transformToApply = null; - final Animation a = child.getAnimation(); - boolean concatMatrix = false; - - final int childWidth = cr - cl; - final int childHeight = cb - ct; - - if (a != null) { - if (mInvalidateRegion == null) { - mInvalidateRegion = new RectF(); - } - final RectF region = mInvalidateRegion; - - final boolean initialized = a.isInitialized(); - if (!initialized) { - a.initialize(childWidth, childHeight, getWidth(), getHeight()); - a.initializeInvalidateRegion(0, 0, childWidth, childHeight); - child.onAnimationStart(); - } - - if (mChildTransformation == null) { - mChildTransformation = new Transformation(); - } - more = a.getTransformation(drawingTime, mChildTransformation); - transformToApply = mChildTransformation; - - concatMatrix = a.willChangeTransformationMatrix(); - - if (more) { - if (!a.willChangeBounds()) { - if ((flags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) == - FLAG_OPTIMIZE_INVALIDATE) { - mGroupFlags |= FLAG_INVALIDATE_REQUIRED; - } else if ((flags & FLAG_INVALIDATE_REQUIRED) == 0) { - // The child need to draw an animation, potentially offscreen, so - // make sure we do not cancel invalidate requests - mPrivateFlags |= DRAW_ANIMATION; - invalidate(cl, ct, cr, cb); - } - } else { - a.getInvalidateRegion(0, 0, childWidth, childHeight, region, transformToApply); - - // The child need to draw an animation, potentially offscreen, so - // make sure we do not cancel invalidate requests - mPrivateFlags |= DRAW_ANIMATION; - // Enlarge the invalidate region to account for rounding errors - // in Animation#getInvalidateRegion(); Using 0.5f is unfortunately - // not enough for some types of animations (e.g. scale down.) - final int left = cl + (int) (region.left - 1.0f); - final int top = ct + (int) (region.top - 1.0f); - invalidate(left, top, - left + (int) (region.width() + 1.0f), - top + (int) (region.height() + 1.0f)); - } - } - } else if ((flags & FLAG_SUPPORT_STATIC_TRANSFORMATIONS) == - FLAG_SUPPORT_STATIC_TRANSFORMATIONS) { - if (mChildTransformation == null) { - mChildTransformation = new Transformation(); - } - final boolean hasTransform = getChildStaticTransformation(child, mChildTransformation); - if (hasTransform) { - final int transformType = mChildTransformation.getTransformationType(); - transformToApply = transformType != Transformation.TYPE_IDENTITY ? - mChildTransformation : null; - concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0; - } - } - - if (!concatMatrix && canvas.quickReject(cl, ct, cr, cb, Canvas.EdgeType.BW) && - (child.mPrivateFlags & DRAW_ANIMATION) == 0) { - return more; - } - - child.computeScroll(); - - final int sx = child.mScrollX; - final int sy = child.mScrollY; - - Bitmap cache = null; - if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE || - (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) { - cache = child.getDrawingCache(); - } - - final boolean hasNoCache = cache == null; - - final int restoreTo = canvas.save(); - if (hasNoCache) { - canvas.translate(cl - sx, ct - sy); - } else { - canvas.translate(cl, ct); - } - - float alpha = 1.0f; - - if (transformToApply != null) { - if (concatMatrix) { - int transX = 0; - int transY = 0; - if (hasNoCache) { - transX = -sx; - transY = -sy; - } - // Undo the scroll translation, apply the transformation matrix, - // then redo the scroll translate to get the correct result. - canvas.translate(-transX, -transY); - canvas.concat(transformToApply.getMatrix()); - canvas.translate(transX, transY); - mGroupFlags |= FLAG_CLEAR_TRANSFORMATION; - } - - alpha = transformToApply.getAlpha(); - if (alpha < 1.0f) { - mGroupFlags |= FLAG_CLEAR_TRANSFORMATION; - } - - if (alpha < 1.0f && hasNoCache) { - final int multipliedAlpha = (int) (255 * alpha); - if (!child.onSetAlpha(multipliedAlpha)) { - canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct, multipliedAlpha, - Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); - } else { - child.mPrivateFlags |= ALPHA_SET; - } - } - } else if ((child.mPrivateFlags & ALPHA_SET) == ALPHA_SET) { - child.onSetAlpha(255); - } - - if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) { - if (hasNoCache) { - canvas.clipRect(sx, sy, sx + childWidth, sy + childHeight); - } else { - canvas.clipRect(0, 0, childWidth, childHeight); - } - } - - // Clear the flag as early as possible to allow draw() implementations - // to call invalidate() successfully when doing animations - child.mPrivateFlags |= DRAWN; - - if (hasNoCache) { - // Fast path for layouts with no backgrounds - if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { - if (ViewDebug.TRACE_HIERARCHY) { - ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); - } - child.dispatchDraw(canvas); - } else { - child.draw(canvas); - } - } else { - final Paint cachePaint = mCachePaint; - if (alpha < 1.0f) { - cachePaint.setAlpha((int) (alpha * 255)); - mGroupFlags |= FLAG_ALPHA_LOWER_THAN_ONE; - } else if ((flags & FLAG_ALPHA_LOWER_THAN_ONE) == FLAG_ALPHA_LOWER_THAN_ONE) { - cachePaint.setAlpha(255); - mGroupFlags &= ~FLAG_ALPHA_LOWER_THAN_ONE; - } - if (ViewRoot.PROFILE_DRAWING) { - EventLog.writeEvent(60003, hashCode()); - } - canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint); - } - - canvas.restoreToCount(restoreTo); - - if (a != null && !more) { - child.onSetAlpha(255); - finishAnimatingView(child, a); - } - - return more; - } - - /** - * By default, children are clipped to their bounds before drawing. This - * allows view groups to override this behavior for animations, etc. - * - * @param clipChildren true to clip children to their bounds, - * false otherwise - * @attr ref android.R.styleable#ViewGroup_clipChildren - */ - public void setClipChildren(boolean clipChildren) { - setBooleanFlag(FLAG_CLIP_CHILDREN, clipChildren); - } - - /** - * By default, children are clipped to the padding of the ViewGroup. This - * allows view groups to override this behavior - * - * @param clipToPadding true to clip children to the padding of the - * group, false otherwise - * @attr ref android.R.styleable#ViewGroup_clipToPadding - */ - public void setClipToPadding(boolean clipToPadding) { - setBooleanFlag(FLAG_CLIP_TO_PADDING, clipToPadding); - } - - /** - * {@inheritDoc} - */ - @Override - public void dispatchSetSelected(boolean selected) { - final View[] children = mChildren; - final int count = mChildrenCount; - for (int i = 0; i < count; i++) { - children[i].setSelected(selected); - } - } - - @Override - protected void dispatchSetPressed(boolean pressed) { - final View[] children = mChildren; - final int count = mChildrenCount; - for (int i = 0; i < count; i++) { - children[i].setPressed(pressed); - } - } - - /** - * When this property is set to true, this ViewGroup supports static transformations on - * children; this causes - * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} to be - * invoked when a child is drawn. - * - * Any subclass overriding - * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} should - * set this property to true. - * - * @param enabled True to enable static transformations on children, false otherwise. - * - * @see #FLAG_SUPPORT_STATIC_TRANSFORMATIONS - */ - protected void setStaticTransformationsEnabled(boolean enabled) { - setBooleanFlag(FLAG_SUPPORT_STATIC_TRANSFORMATIONS, enabled); - } - - /** - * {@inheritDoc} - * - * @see #setStaticTransformationsEnabled(boolean) - */ - protected boolean getChildStaticTransformation(View child, Transformation t) { - return false; - } - - /** - * {@hide} - */ - @Override - protected View findViewTraversal(int id) { - if (id == mID) { - return this; - } - - final View[] where = mChildren; - final int len = mChildrenCount; - - for (int i = 0; i < len; i++) { - View v = where[i]; - - if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) { - v = v.findViewById(id); - - if (v != null) { - return v; - } - } - } - - return null; - } - - /** - * {@hide} - */ - @Override - protected View findViewWithTagTraversal(Object tag) { - if (tag != null && tag.equals(mTag)) { - return this; - } - - final View[] where = mChildren; - final int len = mChildrenCount; - - for (int i = 0; i < len; i++) { - View v = where[i]; - - if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) { - v = v.findViewWithTag(tag); - - if (v != null) { - return v; - } - } - } - - return null; - } - - /** - * Adds a child view. If no layout parameters are already set on the child, the - * default parameters for this ViewGroup are set on the child. - * - * @param child the child view to add - * - * @see #generateDefaultLayoutParams() - */ - public void addView(View child) { - addView(child, -1); - } - - /** - * Adds a child view. If no layout parameters are already set on the child, the - * default parameters for this ViewGroup are set on the child. - * - * @param child the child view to add - * @param index the position at which to add the child - * - * @see #generateDefaultLayoutParams() - */ - public void addView(View child, int index) { - LayoutParams params = child.getLayoutParams(); - if (params == null) { - params = generateDefaultLayoutParams(); - if (params == null) { - throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null"); - } - } - addView(child, index, params); - } - - /** - * Adds a child view with this ViewGroup's default layout parameters and the - * specified width and height. - * - * @param child the child view to add - */ - public void addView(View child, int width, int height) { - final LayoutParams params = generateDefaultLayoutParams(); - params.width = width; - params.height = height; - addView(child, -1, params); - } - - /** - * Adds a child view with the specified layout parameters. - * - * @param child the child view to add - * @param params the layout parameters to set on the child - */ - public void addView(View child, LayoutParams params) { - addView(child, -1, params); - } - - /** - * Adds a child view with the specified layout parameters. - * - * @param child the child view to add - * @param index the position at which to add the child - * @param params the layout parameters to set on the child - */ - public void addView(View child, int index, LayoutParams params) { - if (DBG) { - System.out.println(this + " addView"); - } - - // addViewInner() will call child.requestLayout() when setting the new LayoutParams - // therefore, we call requestLayout() on ourselves before, so that the child's request - // will be blocked at our level - requestLayout(); - invalidate(); - addViewInner(child, index, params, false); - } - - /** - * {@inheritDoc} - */ - public void updateViewLayout(View view, ViewGroup.LayoutParams params) { - if (!checkLayoutParams(params)) { - throw new IllegalArgumentException("Invalid LayoutParams supplied to " + this); - } - if (view.mParent != this) { - throw new IllegalArgumentException("Given view not a child of " + this); - } - view.setLayoutParams(params); - } - - /** - * {@inheritDoc} - */ - protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { - return p != null; - } - - /** - * Interface definition for a callback to be invoked when the hierarchy - * within this view changed. The hierarchy changes whenever a child is added - * to or removed from this view. - */ - public interface OnHierarchyChangeListener { - /** - * Called when a new child is added to a parent view. - * - * @param parent the view in which a child was added - * @param child the new child view added in the hierarchy - */ - void onChildViewAdded(View parent, View child); - - /** - * Called when a child is removed from a parent view. - * - * @param parent the view from which the child was removed - * @param child the child removed from the hierarchy - */ - void onChildViewRemoved(View parent, View child); - } - - /** - * Register a callback to be invoked when a child is added to or removed - * from this view. - * - * @param listener the callback to invoke on hierarchy change - */ - public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) { - mOnHierarchyChangeListener = listener; - } - - /** - * Adds a view during layout. This is useful if in your onLayout() method, - * you need to add more views (as does the list view for example). - * - * If index is negative, it means put it at the end of the list. - * - * @param child the view to add to the group - * @param index the index at which the child must be added - * @param params the layout parameters to associate with the child - * @return true if the child was added, false otherwise - */ - protected boolean addViewInLayout(View child, int index, LayoutParams params) { - return addViewInLayout(child, index, params, false); - } - - /** - * Adds a view during layout. This is useful if in your onLayout() method, - * you need to add more views (as does the list view for example). - * - * If index is negative, it means put it at the end of the list. - * - * @param child the view to add to the group - * @param index the index at which the child must be added - * @param params the layout parameters to associate with the child - * @param preventRequestLayout if true, calling this method will not trigger a - * layout request on child - * @return true if the child was added, false otherwise - */ - protected boolean addViewInLayout(View child, int index, LayoutParams params, - boolean preventRequestLayout) { - child.mParent = null; - addViewInner(child, index, params, preventRequestLayout); - child.mPrivateFlags |= DRAWN; - return true; - } - - /** - * Prevents the specified child to be laid out during the next layout pass. - * - * @param child the child on which to perform the cleanup - */ - protected void cleanupLayoutState(View child) { - child.mPrivateFlags &= ~View.FORCE_LAYOUT; - } - - private void addViewInner(View child, int index, LayoutParams params, - boolean preventRequestLayout) { - - if (child.getParent() != null) { - throw new IllegalStateException("The specified child already has a parent. " + - "You must call removeView() on the child's parent first."); - } - - if (!checkLayoutParams(params)) { - params = generateLayoutParams(params); - } - - if (preventRequestLayout) { - child.mLayoutParams = params; - } else { - child.setLayoutParams(params); - } - - if (index < 0) { - index = mChildrenCount; - } - - addInArray(child, index); - - // tell our children - if (preventRequestLayout) { - child.assignParent(this); - } else { - child.mParent = this; - } - - if (child.hasFocus()) { - requestChildFocus(child, child.findFocus()); - } - - AttachInfo ai = mAttachInfo; - if (ai != null) { - boolean lastKeepOn = ai.mKeepScreenOn; - ai.mKeepScreenOn = false; - child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK)); - if (ai.mKeepScreenOn) { - needGlobalAttributesUpdate(true); - } - ai.mKeepScreenOn = lastKeepOn; - } - - if (mOnHierarchyChangeListener != null) { - mOnHierarchyChangeListener.onChildViewAdded(this, child); - } - - if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) { - mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE; - } - } - - private void addInArray(View child, int index) { - View[] children = mChildren; - final int count = mChildrenCount; - final int size = children.length; - if (index == count) { - if (size == count) { - mChildren = new View[size + ARRAY_CAPACITY_INCREMENT]; - System.arraycopy(children, 0, mChildren, 0, size); - children = mChildren; - } - children[mChildrenCount++] = child; - } else if (index < count) { - if (size == count) { - mChildren = new View[size + ARRAY_CAPACITY_INCREMENT]; - System.arraycopy(children, 0, mChildren, 0, index); - System.arraycopy(children, index, mChildren, index + 1, count - index); - children = mChildren; - } else { - System.arraycopy(children, index, children, index + 1, count - index); - } - children[index] = child; - mChildrenCount++; - } else { - throw new IndexOutOfBoundsException("index=" + index + " count=" + count); - } - } - - // This method also sets the child's mParent to null - private void removeFromArray(int index) { - final View[] children = mChildren; - children[index].mParent = null; - final int count = mChildrenCount; - if (index == count - 1) { - children[--mChildrenCount] = null; - } else if (index >= 0 && index < count) { - System.arraycopy(children, index + 1, children, index, count - index - 1); - children[--mChildrenCount] = null; - } else { - throw new IndexOutOfBoundsException(); - } - } - - // This method also sets the children's mParent to null - private void removeFromArray(int start, int count) { - final View[] children = mChildren; - final int childrenCount = mChildrenCount; - - start = Math.max(0, start); - final int end = Math.min(childrenCount, start + count); - - if (start == end) { - return; - } - - if (end == childrenCount) { - for (int i = start; i < end; i++) { - children[i].mParent = null; - children[i] = null; - } - } else { - for (int i = start; i < end; i++) { - children[i].mParent = null; - } - - // Since we're looping above, we might as well do the copy, but is arraycopy() - // faster than the extra 2 bounds checks we would do in the loop? - System.arraycopy(children, end, children, start, childrenCount - end); - - for (int i = childrenCount - (end - start); i < childrenCount; i++) { - children[i] = null; - } - } - - mChildrenCount -= (end - start); - } - - private void bindLayoutAnimation(View child) { - Animation a = mLayoutAnimationController.getAnimationForView(child); - child.setAnimation(a); - } - - /** - * Subclasses should override this method to set layout animation - * parameters on the supplied child. - * - * @param child the child to associate with animation parameters - * @param params the child's layout parameters which hold the animation - * parameters - * @param index the index of the child in the view group - * @param count the number of children in the view group - */ - protected void attachLayoutAnimationParameters(View child, - LayoutParams params, int index, int count) { - LayoutAnimationController.AnimationParameters animationParams = - params.layoutAnimationParameters; - if (animationParams == null) { - animationParams = new LayoutAnimationController.AnimationParameters(); - params.layoutAnimationParameters = animationParams; - } - - animationParams.count = count; - animationParams.index = index; - } - - /** - * {@inheritDoc} - */ - public void removeView(View view) { - removeViewInternal(view); - requestLayout(); - invalidate(); - } - - /** - * Removes a view during layout. This is useful if in your onLayout() method, - * you need to remove more views. - * - * @param view the view to remove from the group - */ - public void removeViewInLayout(View view) { - removeViewInternal(view); - } - - /** - * Removes a range of views during layout. This is useful if in your onLayout() method, - * you need to remove more views. - * - * @param start the index of the first view to remove from the group - * @param count the number of views to remove from the group - */ - public void removeViewsInLayout(int start, int count) { - removeViewsInternal(start, count); - } - - /** - * Removes the view at the specified position in the group. - * - * @param index the position in the group of the view to remove - */ - public void removeViewAt(int index) { - removeViewInternal(index, getChildAt(index)); - requestLayout(); - invalidate(); - } - - /** - * Removes the specified range of views from the group. - * - * @param start the first position in the group of the range of views to remove - * @param count the number of views to remove - */ - public void removeViews(int start, int count) { - removeViewsInternal(start, count); - requestLayout(); - invalidate(); - } - - private void removeViewInternal(View view) { - final int index = indexOfChild(view); - if (index >= 0) { - removeViewInternal(index, view); - } - } - - private void removeViewInternal(int index, View view) { - boolean clearChildFocus = false; - if (view == mFocused) { - view.clearFocusForRemoval(); - clearChildFocus = true; - } - - if (view.getAnimation() != null) { - addDisappearingView(view); - } else if (view.mAttachInfo != null) { - view.dispatchDetachedFromWindow(); - } - - if (mOnHierarchyChangeListener != null) { - mOnHierarchyChangeListener.onChildViewRemoved(this, view); - } - - needGlobalAttributesUpdate(false); - - removeFromArray(index); - - if (clearChildFocus) { - clearChildFocus(view); - } - } - - private void removeViewsInternal(int start, int count) { - final OnHierarchyChangeListener onHierarchyChangeListener = mOnHierarchyChangeListener; - final boolean notifyListener = onHierarchyChangeListener != null; - final View focused = mFocused; - final boolean detach = mAttachInfo != null; - View clearChildFocus = null; - - final View[] children = mChildren; - final int end = start + count; - - for (int i = start; i < end; i++) { - final View view = children[i]; - - if (view == focused) { - view.clearFocusForRemoval(); - clearChildFocus = view; - } - - if (view.getAnimation() != null) { - addDisappearingView(view); - } else if (detach) { - view.dispatchDetachedFromWindow(); - } - - needGlobalAttributesUpdate(false); - - if (notifyListener) { - onHierarchyChangeListener.onChildViewRemoved(this, view); - } - } - - removeFromArray(start, count); - - if (clearChildFocus != null) { - clearChildFocus(clearChildFocus); - } - } - - /** - * Call this method to remove all child views from the - * ViewGroup. - */ - public void removeAllViews() { - removeAllViewsInLayout(); - requestLayout(); - invalidate(); - } - - /** - * Called by a ViewGroup subclass to remove child views from itself, - * when it must first know its size on screen before it can calculate how many - * child views it will render. An example is a Gallery or a ListView, which - * may "have" 50 children, but actually only render the number of children - * that can currently fit inside the object on screen. Do not call - * this method unless you are extending ViewGroup and understand the - * view measuring and layout pipeline. - */ - public void removeAllViewsInLayout() { - final int count = mChildrenCount; - if (count <= 0) { - return; - } - - final View[] children = mChildren; - mChildrenCount = 0; - - final OnHierarchyChangeListener listener = mOnHierarchyChangeListener; - final boolean notify = listener != null; - final View focused = mFocused; - final boolean detach = mAttachInfo != null; - View clearChildFocus = null; - - needGlobalAttributesUpdate(false); - - for (int i = count - 1; i >= 0; i--) { - final View view = children[i]; - - if (view == focused) { - view.clearFocusForRemoval(); - clearChildFocus = view; - } - - if (view.getAnimation() != null) { - addDisappearingView(view); - } else if (detach) { - view.dispatchDetachedFromWindow(); - } - - if (notify) { - listener.onChildViewRemoved(this, view); - } - - view.mParent = null; - children[i] = null; - } - - if (clearChildFocus != null) { - clearChildFocus(clearChildFocus); - } - } - - /** - * Finishes the removal of a detached view. This method will dispatch the detached from - * window event and notify the hierarchy change listener. - * - * @param child the child to be definitely removed from the view hierarchy - * @param animate if true and the view has an animation, the view is placed in the - * disappearing views list, otherwise, it is detached from the window - * - * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams) - * @see #detachAllViewsFromParent() - * @see #detachViewFromParent(View) - * @see #detachViewFromParent(int) - */ - protected void removeDetachedView(View child, boolean animate) { - if (child == mFocused) { - child.clearFocus(); - } - - if (animate && child.getAnimation() != null) { - addDisappearingView(child); - } else if (child.mAttachInfo != null) { - child.dispatchDetachedFromWindow(); - } - - if (mOnHierarchyChangeListener != null) { - mOnHierarchyChangeListener.onChildViewRemoved(this, child); - } - } - - /** - * Attaches a view to this view group. Attaching a view assigns this group as the parent, - * sets the layout parameters and puts the view in the list of children so it can be retrieved - * by calling {@link #getChildAt(int)}. - * - * This method should be called only for view which were detached from their parent. - * - * @param child the child to attach - * @param index the index at which the child should be attached - * @param params the layout parameters of the child - * - * @see #removeDetachedView(View, boolean) - * @see #detachAllViewsFromParent() - * @see #detachViewFromParent(View) - * @see #detachViewFromParent(int) - */ - protected void attachViewToParent(View child, int index, LayoutParams params) { - child.mLayoutParams = params; - - if (index < 0) { - index = mChildrenCount; - } - - addInArray(child, index); - - child.mParent = this; - child.mPrivateFlags |= DRAWN; - - if (child.hasFocus()) { - requestChildFocus(child, child.findFocus()); - } - } - - /** - * Detaches a view from its parent. Detaching a view should be temporary and followed - * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)} - * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached, - * its parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}. - * - * @param child the child to detach - * - * @see #detachViewFromParent(int) - * @see #detachViewsFromParent(int, int) - * @see #detachAllViewsFromParent() - * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams) - * @see #removeDetachedView(View, boolean) - */ - protected void detachViewFromParent(View child) { - removeFromArray(indexOfChild(child)); - } - - /** - * Detaches a view from its parent. Detaching a view should be temporary and followed - * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)} - * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached, - * its parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}. - * - * @param index the index of the child to detach - * - * @see #detachViewFromParent(View) - * @see #detachAllViewsFromParent() - * @see #detachViewsFromParent(int, int) - * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams) - * @see #removeDetachedView(View, boolean) - */ - protected void detachViewFromParent(int index) { - removeFromArray(index); - } - - /** - * Detaches a range of view from their parent. Detaching a view should be temporary and followed - * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)} - * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached, its - * parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}. - * - * @param start the first index of the childrend range to detach - * @param count the number of children to detach - * - * @see #detachViewFromParent(View) - * @see #detachViewFromParent(int) - * @see #detachAllViewsFromParent() - * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams) - * @see #removeDetachedView(View, boolean) - */ - protected void detachViewsFromParent(int start, int count) { - removeFromArray(start, count); - } - - /** - * Detaches all views from the parent. Detaching a view should be temporary and followed - * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)} - * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached, - * its parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}. - * - * @see #detachViewFromParent(View) - * @see #detachViewFromParent(int) - * @see #detachViewsFromParent(int, int) - * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams) - * @see #removeDetachedView(View, boolean) - */ - protected void detachAllViewsFromParent() { - final int count = mChildrenCount; - if (count <= 0) { - return; - } - - final View[] children = mChildren; - mChildrenCount = 0; - - for (int i = count - 1; i >= 0; i--) { - children[i].mParent = null; - children[i] = null; - } - } - - /** - * Don't call or override this method. It is used for the implementation of - * the view hierarchy. - */ - public final void invalidateChild(View child, final Rect dirty) { - if (ViewDebug.TRACE_HIERARCHY) { - ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE_CHILD); - } - - ViewParent parent = this; - - final AttachInfo attachInfo = mAttachInfo; - if (attachInfo != null) { - final int[] location = attachInfo.mInvalidateChildLocation; - location[CHILD_LEFT_INDEX] = child.mLeft; - location[CHILD_TOP_INDEX] = child.mTop; - - // If the child is drawing an animation, we want to copy this flag onto - // ourselves and the parent to make sure the invalidate request goes - // through - final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION; - - do { - if (drawAnimation && parent instanceof View) { - ((View) parent).mPrivateFlags |= DRAW_ANIMATION; - } - parent = parent.invalidateChildInParent(location, dirty); - } while (parent != null); - } - } - - /** - * Don't call or override this method. It is used for the implementation of - * the view hierarchy. - * - * This implementation returns null if this ViewGroup does not have a parent, - * if this ViewGroup is already fully invalidated or if the dirty rectangle - * does not intersect with this ViewGroup's bounds. - */ - public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) { - if (ViewDebug.TRACE_HIERARCHY) { - ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE_CHILD_IN_PARENT); - } - - if ((mPrivateFlags & DRAWN) == DRAWN) { - if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) != - FLAG_OPTIMIZE_INVALIDATE) { - dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX, - location[CHILD_TOP_INDEX] - mScrollY); - - final int left = mLeft; - final int top = mTop; - - if (dirty.intersect(0, 0, mRight - left, mBottom - top) || - (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) { - mPrivateFlags &= ~DRAWING_CACHE_VALID; - - location[CHILD_LEFT_INDEX] = left; - location[CHILD_TOP_INDEX] = top; - - return mParent; - } - } else { - mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID; - - location[CHILD_LEFT_INDEX] = mLeft; - location[CHILD_TOP_INDEX] = mTop; - - dirty.set(0, 0, mRight - location[CHILD_LEFT_INDEX], - mBottom - location[CHILD_TOP_INDEX]); - - return mParent; - } - } - - return null; - } - - /** - * Offset a rectangle that is in a descendant's coordinate - * space into our coordinate space. - * @param descendant A descendant of this view - * @param rect A rectangle defined in descendant's coordinate space. - */ - public final void offsetDescendantRectToMyCoords(View descendant, Rect rect) { - offsetRectBetweenParentAndChild(descendant, rect, true, false); - } - - /** - * Offset a rectangle that is in our coordinate space into an ancestor's - * coordinate space. - * @param descendant A descendant of this view - * @param rect A rectangle defined in descendant's coordinate space. - */ - public final void offsetRectIntoDescendantCoords(View descendant, Rect rect) { - offsetRectBetweenParentAndChild(descendant, rect, false, false); - } - - /** - * Helper method that offsets a rect either from parent to descendant or - * descendant to parent. - */ - void offsetRectBetweenParentAndChild(View descendant, Rect rect, - boolean offsetFromChildToParent, boolean clipToBounds) { - - // already in the same coord system :) - if (descendant == this) { - return; - } - - ViewParent theParent = descendant.mParent; - - // search and offset up to the parent - while ((theParent != null) - && (theParent instanceof View) - && (theParent != this)) { - - if (offsetFromChildToParent) { - rect.offset(descendant.mLeft - descendant.mScrollX, - descendant.mTop - descendant.mScrollY); - if (clipToBounds) { - View p = (View) theParent; - rect.intersect(0, 0, p.mRight - p.mLeft, p.mBottom - p.mTop); - } - } else { - if (clipToBounds) { - View p = (View) theParent; - rect.intersect(0, 0, p.mRight - p.mLeft, p.mBottom - p.mTop); - } - rect.offset(descendant.mScrollX - descendant.mLeft, - descendant.mScrollY - descendant.mTop); - } - - descendant = (View) theParent; - theParent = descendant.mParent; - } - - // now that we are up to this view, need to offset one more time - // to get into our coordinate space - if (theParent == this) { - if (offsetFromChildToParent) { - rect.offset(descendant.mLeft - descendant.mScrollX, - descendant.mTop - descendant.mScrollY); - } else { - rect.offset(descendant.mScrollX - descendant.mLeft, - descendant.mScrollY - descendant.mTop); - } - } else { - throw new IllegalArgumentException("parameter must be a descendant of this view"); - } - } - - /** - * Offset the vertical location of all children of this view by the specified number of pixels. - * - * @param offset the number of pixels to offset - * - * @hide - */ - public void offsetChildrenTopAndBottom(int offset) { - final int count = mChildrenCount; - final View[] children = mChildren; - - for (int i = 0; i < count; i++) { - final View v = children[i]; - v.mTop += offset; - v.mBottom += offset; - } - } - - /** - * {@inheritDoc} - */ - public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) { - int dx = child.mLeft - mScrollX; - int dy = child.mTop - mScrollY; - if (offset != null) { - offset.x += dx; - offset.y += dy; - } - r.offset(dx, dy); - return r.intersect(0, 0, mRight - mLeft, mBottom - mTop) && - (mParent == null || mParent.getChildVisibleRect(this, r, offset)); - } - - /** - * {@inheritDoc} - */ - @Override - protected abstract void onLayout(boolean changed, - int l, int t, int r, int b); - - /** - * Indicates whether the view group has the ability to animate its children - * after the first layout. - * - * @return true if the children can be animated, false otherwise - */ - protected boolean canAnimate() { - return mLayoutAnimationController != null; - } - - /** - * Runs the layout animation. Calling this method triggers a relayout of - * this view group. - */ - public void startLayoutAnimation() { - if (mLayoutAnimationController != null) { - mGroupFlags |= FLAG_RUN_ANIMATION; - requestLayout(); - } - } - - /** - * Schedules the layout animation to be played after the next layout pass - * of this view group. This can be used to restart the layout animation - * when the content of the view group changes or when the activity is - * paused and resumed. - */ - public void scheduleLayoutAnimation() { - mGroupFlags |= FLAG_RUN_ANIMATION; - } - - /** - * Sets the layout animation controller used to animate the group's - * children after the first layout. - * - * @param controller the animation controller - */ - public void setLayoutAnimation(LayoutAnimationController controller) { - mLayoutAnimationController = controller; - if (mLayoutAnimationController != null) { - mGroupFlags |= FLAG_RUN_ANIMATION; - } - } - - /** - * Returns the layout animation controller used to animate the group's - * children. - * - * @return the current animation controller - */ - public LayoutAnimationController getLayoutAnimation() { - return mLayoutAnimationController; - } - - /** - * Indicates whether the children's drawing cache is used during a layout - * animation. By default, the drawing cache is enabled but this will prevent - * nested layout animations from working. To nest animations, you must disable - * the cache. - * - * @return true if the animation cache is enabled, false otherwise - * - * @see #setAnimationCacheEnabled(boolean) - * @see View#setDrawingCacheEnabled(boolean) - */ - @ViewDebug.ExportedProperty - public boolean isAnimationCacheEnabled() { - return (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE; - } - - /** - * Enables or disables the children's drawing cache during a layout animation. - * By default, the drawing cache is enabled but this will prevent nested - * layout animations from working. To nest animations, you must disable the - * cache. - * - * @param enabled true to enable the animation cache, false otherwise - * - * @see #isAnimationCacheEnabled() - * @see View#setDrawingCacheEnabled(boolean) - */ - public void setAnimationCacheEnabled(boolean enabled) { - setBooleanFlag(FLAG_ANIMATION_CACHE, enabled); - } - - /** - * Indicates whether this ViewGroup will always try to draw its children using their - * drawing cache. By default this property is enabled. - * - * @return true if the animation cache is enabled, false otherwise - * - * @see #setAlwaysDrawnWithCacheEnabled(boolean) - * @see #setChildrenDrawnWithCacheEnabled(boolean) - * @see View#setDrawingCacheEnabled(boolean) - */ - @ViewDebug.ExportedProperty - public boolean isAlwaysDrawnWithCacheEnabled() { - return (mGroupFlags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE; - } - - /** - * Indicates whether this ViewGroup will always try to draw its children using their - * drawing cache. This property can be set to true when the cache rendering is - * slightly different from the children's normal rendering. Renderings can be different, - * for instance, when the cache's quality is set to low. - * - * When this property is disabled, the ViewGroup will use the drawing cache of its - * children only when asked to. It's usually the task of subclasses to tell ViewGroup - * when to start using the drawing cache and when to stop using it. - * - * @param always true to always draw with the drawing cache, false otherwise - * - * @see #isAlwaysDrawnWithCacheEnabled() - * @see #setChildrenDrawnWithCacheEnabled(boolean) - * @see View#setDrawingCacheEnabled(boolean) - * @see View#setDrawingCacheQuality(int) - */ - public void setAlwaysDrawnWithCacheEnabled(boolean always) { - setBooleanFlag(FLAG_ALWAYS_DRAWN_WITH_CACHE, always); - } - - /** - * Indicates whether the ViewGroup is currently drawing its children using - * their drawing cache. - * - * @return true if children should be drawn with their cache, false otherwise - * - * @see #setAlwaysDrawnWithCacheEnabled(boolean) - * @see #setChildrenDrawnWithCacheEnabled(boolean) - */ - @ViewDebug.ExportedProperty - protected boolean isChildrenDrawnWithCacheEnabled() { - return (mGroupFlags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE; - } - - /** - * Tells the ViewGroup to draw its children using their drawing cache. This property - * is ignored when {@link #isAlwaysDrawnWithCacheEnabled()} is true. A child's drawing cache - * will be used only if it has been enabled. - * - * Subclasses should call this method to start and stop using the drawing cache when - * they perform performance sensitive operations, like scrolling or animating. - * - * @param enabled true if children should be drawn with their cache, false otherwise - * - * @see #setAlwaysDrawnWithCacheEnabled(boolean) - * @see #isChildrenDrawnWithCacheEnabled() - */ - protected void setChildrenDrawnWithCacheEnabled(boolean enabled) { - setBooleanFlag(FLAG_CHILDREN_DRAWN_WITH_CACHE, enabled); - } - - private void setBooleanFlag(int flag, boolean value) { - if (value) { - mGroupFlags |= flag; - } else { - mGroupFlags &= ~flag; - } - } - - /** - * Returns an integer indicating what types of drawing caches are kept in memory. - * - * @see #setPersistentDrawingCache(int) - * @see #setAnimationCacheEnabled(boolean) - * - * @return one or a combination of {@link #PERSISTENT_NO_CACHE}, - * {@link #PERSISTENT_ANIMATION_CACHE}, {@link #PERSISTENT_SCROLLING_CACHE} - * and {@link #PERSISTENT_ALL_CACHES} - */ - @ViewDebug.ExportedProperty(mapping = { - @ViewDebug.IntToString(from = PERSISTENT_NO_CACHE, to = "NONE"), - @ViewDebug.IntToString(from = PERSISTENT_ALL_CACHES, to = "ANIMATION"), - @ViewDebug.IntToString(from = PERSISTENT_SCROLLING_CACHE, to = "SCROLLING"), - @ViewDebug.IntToString(from = PERSISTENT_ALL_CACHES, to = "ALL") - }) - public int getPersistentDrawingCache() { - return mPersistentDrawingCache; - } - - /** - * Indicates what types of drawing caches should be kept in memory after - * they have been created. - * - * @see #getPersistentDrawingCache() - * @see #setAnimationCacheEnabled(boolean) - * - * @param drawingCacheToKeep one or a combination of {@link #PERSISTENT_NO_CACHE}, - * {@link #PERSISTENT_ANIMATION_CACHE}, {@link #PERSISTENT_SCROLLING_CACHE} - * and {@link #PERSISTENT_ALL_CACHES} - */ - public void setPersistentDrawingCache(int drawingCacheToKeep) { - mPersistentDrawingCache = drawingCacheToKeep & PERSISTENT_ALL_CACHES; - } - - /** - * Returns a new set of layout parameters based on the supplied attributes set. - * - * @param attrs the attributes to build the layout parameters from - * - * @return an instance of {@link android.view.ViewGroup.LayoutParams} or one - * of its descendants - */ - public LayoutParams generateLayoutParams(AttributeSet attrs) { - return new LayoutParams(getContext(), attrs); - } - - /** - * Returns a safe set of layout parameters based on the supplied layout params. - * When a ViewGroup is passed a View whose layout params do not pass the test of - * {@link #checkLayoutParams(android.view.ViewGroup.LayoutParams)}, this method - * is invoked. This method should return a new set of layout params suitable for - * this ViewGroup, possibly by copying the appropriate attributes from the - * specified set of layout params. - * - * @param p The layout parameters to convert into a suitable set of layout parameters - * for this ViewGroup. - * - * @return an instance of {@link android.view.ViewGroup.LayoutParams} or one - * of its descendants - */ - protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { - return p; - } - - /** - * Returns a set of default layout parameters. These parameters are requested - * when the View passed to {@link #addView(View)} has no layout parameters - * already set. If null is returned, an exception is thrown from addView. - * - * @return a set of default layout parameters or null - */ - protected LayoutParams generateDefaultLayoutParams() { - return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); - } - - /** - * {@inheritDoc} - */ - @Override - protected void debug(int depth) { - super.debug(depth); - String output; - - if (mFocused != null) { - output = debugIndent(depth); - output += "mFocused"; - Log.d(VIEW_LOG_TAG, output); - } - if (mChildrenCount != 0) { - output = debugIndent(depth); - output += "{"; - Log.d(VIEW_LOG_TAG, output); - } - int count = mChildrenCount; - for (int i = 0; i < count; i++) { - View child = mChildren[i]; - child.debug(depth + 1); - } - - if (mChildrenCount != 0) { - output = debugIndent(depth); - output += "}"; - Log.d(VIEW_LOG_TAG, output); - } - } - - /** - * Returns the position in the group of the specified child view. - * - * @param child the view for which to get the position - * @return a positive integer representing the position of the view in the - * group, or -1 if the view does not exist in the group - */ - public int indexOfChild(View child) { - final int count = mChildrenCount; - final View[] children = mChildren; - for (int i = 0; i < count; i++) { - if (children[i] == child) { - return i; - } - } - return -1; - } - - /** - * Returns the number of children in the group. - * - * @return a positive integer representing the number of children in - * the group - */ - public int getChildCount() { - return mChildrenCount; - } - - /** - * Returns the view at the specified position in the group. - * - * @param index the position at which to get the view from - * @return the view at the specified position or null if the position - * does not exist within the group - */ - public View getChildAt(int index) { - try { - return mChildren[index]; - } catch (IndexOutOfBoundsException ex) { - return null; - } - } - - /** - * Ask all of the children of this view to measure themselves, taking into - * account both the MeasureSpec requirements for this view and its padding. - * We skip children that are in the GONE state The heavy lifting is done in - * getChildMeasureSpec. - * - * @param widthMeasureSpec The width requirements for this view - * @param heightMeasureSpec The height requirements for this view - */ - protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) { - final int size = mChildrenCount; - final View[] children = mChildren; - for (int i = 0; i < size; ++i) { - final View child = children[i]; - if ((child.mViewFlags & VISIBILITY_MASK) != GONE) { - measureChild(child, widthMeasureSpec, heightMeasureSpec); - } - } - } - - /** - * Ask one of the children of this view to measure itself, taking into - * account both the MeasureSpec requirements for this view and its padding. - * The heavy lifting is done in getChildMeasureSpec. - * - * @param child The child to measure - * @param parentWidthMeasureSpec The width requirements for this view - * @param parentHeightMeasureSpec The height requirements for this view - */ - protected void measureChild(View child, int parentWidthMeasureSpec, - int parentHeightMeasureSpec) { - final LayoutParams lp = child.getLayoutParams(); - - final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, - mPaddingLeft + mPaddingRight, lp.width); - final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, - mPaddingTop + mPaddingBottom, lp.height); - - child.measure(childWidthMeasureSpec, childHeightMeasureSpec); - } - - /** - * Ask one of the children of this view to measure itself, taking into - * account both the MeasureSpec requirements for this view and its padding - * and margins. The child must have MarginLayoutParams The heavy lifting is - * done in getChildMeasureSpec. - * - * @param child The child to measure - * @param parentWidthMeasureSpec The width requirements for this view - * @param widthUsed Extra space that has been used up by the parent - * horizontally (possibly by other children of the parent) - * @param parentHeightMeasureSpec The height requirements for this view - * @param heightUsed Extra space that has been used up by the parent - * vertically (possibly by other children of the parent) - */ - protected void measureChildWithMargins(View child, - int parentWidthMeasureSpec, int widthUsed, - int parentHeightMeasureSpec, int heightUsed) { - final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); - - final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, - mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin - + widthUsed, lp.width); - final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, - mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin - + heightUsed, lp.height); - - child.measure(childWidthMeasureSpec, childHeightMeasureSpec); - } - - /** - * Does the hard part of measureChildren: figuring out the MeasureSpec to - * pass to a particular child. This method figures out the right MeasureSpec - * for one dimension (height or width) of one child view. - * - * The goal is to combine information from our MeasureSpec with the - * LayoutParams of the child to get the best possible results. For example, - * if the this view knows its size (because its MeasureSpec has a mode of - * EXACTLY), and the child has indicated in its LayoutParams that it wants - * to be the same size as the parent, the parent should ask the child to - * layout given an exact size. - * - * @param spec The requirements for this view - * @param padding The padding of this view for the current dimension and - * margins, if applicable - * @param childDimension How big the child wants to be in the current - * dimension - * @return a MeasureSpec integer for the child - */ - public static int getChildMeasureSpec(int spec, int padding, int childDimension) { - int specMode = MeasureSpec.getMode(spec); - int specSize = MeasureSpec.getSize(spec); - - int size = Math.max(0, specSize - padding); - - int resultSize = 0; - int resultMode = 0; - - switch (specMode) { - // Parent has imposed an exact size on us - case MeasureSpec.EXACTLY: - if (childDimension >= 0) { - resultSize = childDimension; - resultMode = MeasureSpec.EXACTLY; - } else if (childDimension == LayoutParams.FILL_PARENT) { - // Child wants to be our size. So be it. - resultSize = size; - resultMode = MeasureSpec.EXACTLY; - } else if (childDimension == LayoutParams.WRAP_CONTENT) { - // Child wants to determine its own size. It can't be - // bigger than us. - resultSize = size; - resultMode = MeasureSpec.AT_MOST; - } - break; - - // Parent has imposed a maximum size on us - case MeasureSpec.AT_MOST: - if (childDimension >= 0) { - // Child wants a specific size... so be it - resultSize = childDimension; - resultMode = MeasureSpec.EXACTLY; - } else if (childDimension == LayoutParams.FILL_PARENT) { - // Child wants to be our size, but our size is not fixed. - // Constrain child to not be bigger than us. - resultSize = size; - resultMode = MeasureSpec.AT_MOST; - } else if (childDimension == LayoutParams.WRAP_CONTENT) { - // Child wants to determine its own size. It can't be - // bigger than us. - resultSize = size; - resultMode = MeasureSpec.AT_MOST; - } - break; - - // Parent asked to see how big we want to be - case MeasureSpec.UNSPECIFIED: - if (childDimension >= 0) { - // Child wants a specific size... let him have it - resultSize = childDimension; - resultMode = MeasureSpec.EXACTLY; - } else if (childDimension == LayoutParams.FILL_PARENT) { - // Child wants to be our size... find out how big it should - // be - resultSize = 0; - resultMode = MeasureSpec.UNSPECIFIED; - } else if (childDimension == LayoutParams.WRAP_CONTENT) { - // Child wants to determine its own size.... find out how - // big it should be - resultSize = 0; - resultMode = MeasureSpec.UNSPECIFIED; - } - break; - } - return MeasureSpec.makeMeasureSpec(resultSize, resultMode); - } - - - /** - * Removes any pending animations for views that have been removed. Call - * this if you don't want animations for exiting views to stack up. - */ - public void clearDisappearingChildren() { - if (mDisappearingChildren != null) { - mDisappearingChildren.clear(); - } - } - - /** - * Add a view which is removed from mChildren but still needs animation - * - * @param v View to add - */ - private void addDisappearingView(View v) { - ArrayList<View> disappearingChildren = mDisappearingChildren; - - if (disappearingChildren == null) { - disappearingChildren = mDisappearingChildren = new ArrayList<View>(); - } - - disappearingChildren.add(v); - } - - /** - * Cleanup a view when its animation is done. This may mean removing it from - * the list of disappearing views. - * - * @param view The view whose animation has finished - * @param animation The animation, cannot be null - */ - private void finishAnimatingView(final View view, Animation animation) { - final ArrayList<View> disappearingChildren = mDisappearingChildren; - if (disappearingChildren != null) { - if (disappearingChildren.contains(view)) { - disappearingChildren.remove(view); - - if (view.mAttachInfo != null) { - view.dispatchDetachedFromWindow(); - } - - view.clearAnimation(); - mGroupFlags |= FLAG_INVALIDATE_REQUIRED; - } - } - - if (animation != null && !animation.getFillAfter()) { - view.clearAnimation(); - } - - if ((view.mPrivateFlags & ANIMATION_STARTED) == ANIMATION_STARTED) { - view.onAnimationEnd(); - // Should be performed by onAnimationEnd() but this avoid an infinite loop, - // so we'd rather be safe than sorry - view.mPrivateFlags &= ~ANIMATION_STARTED; - // Draw one more frame after the animation is done - mGroupFlags |= FLAG_INVALIDATE_REQUIRED; - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean gatherTransparentRegion(Region region) { - // If no transparent regions requested, we are always opaque. - final boolean meOpaque = (mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) == 0; - if (meOpaque && region == null) { - // The caller doesn't care about the region, so stop now. - return true; - } - super.gatherTransparentRegion(region); - final View[] children = mChildren; - final int count = mChildrenCount; - boolean noneOfTheChildrenAreTransparent = true; - for (int i = 0; i < count; i++) { - final View child = children[i]; - if ((child.mViewFlags & VISIBILITY_MASK) != GONE || child.getAnimation() != null) { - if (!child.gatherTransparentRegion(region)) { - noneOfTheChildrenAreTransparent = false; - } - } - } - return meOpaque || noneOfTheChildrenAreTransparent; - } - - /** - * {@inheritDoc} - */ - public void requestTransparentRegion(View child) { - if (child != null) { - child.mPrivateFlags |= View.REQUEST_TRANSPARENT_REGIONS; - if (mParent != null) { - mParent.requestTransparentRegion(this); - } - } - } - - - @Override - protected boolean fitSystemWindows(Rect insets) { - boolean done = super.fitSystemWindows(insets); - if (!done) { - final int count = mChildrenCount; - final View[] children = mChildren; - for (int i = 0; i < count; i++) { - done = children[i].fitSystemWindows(insets); - if (done) { - break; - } - } - } - return done; - } - - /** - * Returns the animation listener to which layout animation events are - * sent. - * - * @return an {@link android.view.animation.Animation.AnimationListener} - */ - public Animation.AnimationListener getLayoutAnimationListener() { - return mAnimationListener; - } - - @Override - protected void drawableStateChanged() { - super.drawableStateChanged(); - - if ((mGroupFlags & FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE) != 0) { - if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0) { - throw new IllegalStateException("addStateFromChildren cannot be enabled if a" - + " child has duplicateParentState set to true"); - } - - final View[] children = mChildren; - final int count = mChildrenCount; - - for (int i = 0; i < count; i++) { - final View child = children[i]; - if ((child.mViewFlags & DUPLICATE_PARENT_STATE) != 0) { - child.refreshDrawableState(); - } - } - } - } - - @Override - protected int[] onCreateDrawableState(int extraSpace) { - if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) == 0) { - return super.onCreateDrawableState(extraSpace); - } - - int need = 0; - int n = getChildCount(); - for (int i = 0; i < n; i++) { - int[] childState = getChildAt(i).getDrawableState(); - - if (childState != null) { - need += childState.length; - } - } - - int[] state = super.onCreateDrawableState(extraSpace + need); - - for (int i = 0; i < n; i++) { - int[] childState = getChildAt(i).getDrawableState(); - - if (childState != null) { - state = mergeDrawableStates(state, childState); - } - } - - return state; - } - - /** - * Sets whether this ViewGroup's drawable states also include - * its children's drawable states. This is used, for example, to - * make a group appear to be focused when its child EditText or button - * is focused. - */ - public void setAddStatesFromChildren(boolean addsStates) { - if (addsStates) { - mGroupFlags |= FLAG_ADD_STATES_FROM_CHILDREN; - } else { - mGroupFlags &= ~FLAG_ADD_STATES_FROM_CHILDREN; - } - - refreshDrawableState(); - } - - /** - * Returns whether this ViewGroup's drawable states also include - * its children's drawable states. This is used, for example, to - * make a group appear to be focused when its child EditText or button - * is focused. - */ - public boolean addStatesFromChildren() { - return (mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0; - } - - /** - * If {link #addStatesFromChildren} is true, refreshes this group's - * drawable state (to include the states from its children). - */ - public void childDrawableStateChanged(View child) { - if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0) { - refreshDrawableState(); - } - } - - /** - * Specifies the animation listener to which layout animation events must - * be sent. Only - * {@link android.view.animation.Animation.AnimationListener#onAnimationStart(Animation)} - * and - * {@link android.view.animation.Animation.AnimationListener#onAnimationEnd(Animation)} - * are invoked. - * - * @param animationListener the layout animation listener - */ - public void setLayoutAnimationListener(Animation.AnimationListener animationListener) { - mAnimationListener = animationListener; - } - - /** - * LayoutParams are used by views to tell their parents how they want to be - * laid out. See - * {@link android.R.styleable#ViewGroup_Layout ViewGroup Layout Attributes} - * for a list of all child view attributes that this class supports. - * - * <p> - * The base LayoutParams class just describes how big the view wants to be - * for both width and height. For each dimension, it can specify one of: - * <ul> - * <li> an exact number - * <li>FILL_PARENT, which means the view wants to be as big as its parent - * (minus padding) - * <li> WRAP_CONTENT, which means that the view wants to be just big enough - * to enclose its content (plus padding) - * </ul> - * There are subclasses of LayoutParams for different subclasses of - * ViewGroup. For example, AbsoluteLayout has its own subclass of - * LayoutParams which adds an X and Y value. - * - * @attr ref android.R.styleable#ViewGroup_Layout_layout_height - * @attr ref android.R.styleable#ViewGroup_Layout_layout_width - */ - public static class LayoutParams { - /** - * Special value for the height or width requested by a View. - * FILL_PARENT means that the view wants to fill the available space - * within the parent, taking the parent's padding into account. - */ - public static final int FILL_PARENT = -1; - - /** - * Special value for the height or width requested by a View. - * WRAP_CONTENT means that the view wants to be just large enough to fit - * its own internal content, taking its own padding into account. - */ - public static final int WRAP_CONTENT = -2; - - /** - * Information about how wide the view wants to be. Can be an exact - * size, or one of the constants FILL_PARENT or WRAP_CONTENT. - */ - @ViewDebug.ExportedProperty(mapping = { - @ViewDebug.IntToString(from = FILL_PARENT, to = "FILL_PARENT"), - @ViewDebug.IntToString(from = WRAP_CONTENT, to = "WRAP_CONTENT") - }) - public int width; - - /** - * Information about how tall the view wants to be. Can be an exact - * size, or one of the constants FILL_PARENT or WRAP_CONTENT. - */ - @ViewDebug.ExportedProperty(mapping = { - @ViewDebug.IntToString(from = FILL_PARENT, to = "FILL_PARENT"), - @ViewDebug.IntToString(from = WRAP_CONTENT, to = "WRAP_CONTENT") - }) - public int height; - - /** - * Used to animate layouts. - */ - public LayoutAnimationController.AnimationParameters layoutAnimationParameters; - - /** - * Creates a new set of layout parameters. The values are extracted from - * the supplied attributes set and context. The XML attributes mapped - * to this set of layout parameters are: - * - * <ul> - * <li><code>layout_width</code>: the width, either an exact value, - * {@link #WRAP_CONTENT} or {@link #FILL_PARENT}</li> - * <li><code>layout_height</code>: the height, either an exact value, - * {@link #WRAP_CONTENT} or {@link #FILL_PARENT}</li> - * </ul> - * - * @param c the application environment - * @param attrs the set of attributes from which to extract the layout - * parameters' values - */ - public LayoutParams(Context c, AttributeSet attrs) { - TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_Layout); - setBaseAttributes(a, - R.styleable.ViewGroup_Layout_layout_width, - R.styleable.ViewGroup_Layout_layout_height); - a.recycle(); - } - - /** - * Creates a new set of layout parameters with the specified width - * and height. - * - * @param width the width, either {@link #FILL_PARENT}, - * {@link #WRAP_CONTENT} or a fixed size in pixels - * @param height the height, either {@link #FILL_PARENT}, - * {@link #WRAP_CONTENT} or a fixed size in pixels - */ - public LayoutParams(int width, int height) { - this.width = width; - this.height = height; - } - - /** - * Copy constructor. Clones the width and height values of the source. - * - * @param source The layout params to copy from. - */ - public LayoutParams(LayoutParams source) { - this.width = source.width; - this.height = source.height; - } - - /** - * Used internally by MarginLayoutParams. - * @hide - */ - LayoutParams() { - } - - /** - * Extracts the layout parameters from the supplied attributes. - * - * @param a the style attributes to extract the parameters from - * @param widthAttr the identifier of the width attribute - * @param heightAttr the identifier of the height attribute - */ - protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) { - width = a.getLayoutDimension(widthAttr, "layout_width"); - height = a.getLayoutDimension(heightAttr, "layout_height"); - } - - /** - * Returns a String representation of this set of layout parameters. - * - * @param output the String to prepend to the internal representation - * @return a String with the following format: output + - * "ViewGroup.LayoutParams={ width=WIDTH, height=HEIGHT }" - * - * @hide - */ - public String debug(String output) { - return output + "ViewGroup.LayoutParams={ width=" - + sizeToString(width) + ", height=" + sizeToString(height) + " }"; - } - - /** - * Converts the specified size to a readable String. - * - * @param size the size to convert - * @return a String instance representing the supplied size - * - * @hide - */ - protected static String sizeToString(int size) { - if (size == WRAP_CONTENT) { - return "wrap-content"; - } - if (size == FILL_PARENT) { - return "fill-parent"; - } - return String.valueOf(size); - } - } - - /** - * Per-child layout information for layouts that support margins. - * See - * {@link android.R.styleable#ViewGroup_MarginLayout ViewGroup Margin Layout Attributes} - * for a list of all child view attributes that this class supports. - */ - public static class MarginLayoutParams extends ViewGroup.LayoutParams { - /** - * The left margin in pixels of the child. - */ - @ViewDebug.ExportedProperty - public int leftMargin; - - /** - * The top margin in pixels of the child. - */ - @ViewDebug.ExportedProperty - public int topMargin; - - /** - * The right margin in pixels of the child. - */ - @ViewDebug.ExportedProperty - public int rightMargin; - - /** - * The bottom margin in pixels of the child. - */ - @ViewDebug.ExportedProperty - public int bottomMargin; - - /** - * Creates a new set of layout parameters. The values are extracted from - * the supplied attributes set and context. - * - * @param c the application environment - * @param attrs the set of attributes from which to extract the layout - * parameters' values - */ - public MarginLayoutParams(Context c, AttributeSet attrs) { - super(); - - TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_MarginLayout); - setBaseAttributes(a, - R.styleable.ViewGroup_MarginLayout_layout_width, - R.styleable.ViewGroup_MarginLayout_layout_height); - - int margin = a.getDimensionPixelSize( - com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_margin, -1); - if (margin >= 0) { - leftMargin = margin; - topMargin = margin; - rightMargin= margin; - bottomMargin = margin; - } else { - leftMargin = a.getDimensionPixelSize( - R.styleable.ViewGroup_MarginLayout_layout_marginLeft, 0); - topMargin = a.getDimensionPixelSize( - R.styleable.ViewGroup_MarginLayout_layout_marginTop, 0); - rightMargin = a.getDimensionPixelSize( - R.styleable.ViewGroup_MarginLayout_layout_marginRight, 0); - bottomMargin = a.getDimensionPixelSize( - R.styleable.ViewGroup_MarginLayout_layout_marginBottom, 0); - } - - a.recycle(); - } - - /** - * {@inheritDoc} - */ - public MarginLayoutParams(int width, int height) { - super(width, height); - } - - /** - * Copy constructor. Clones the width, height and margin values of the source. - * - * @param source The layout params to copy from. - */ - public MarginLayoutParams(MarginLayoutParams source) { - this.width = source.width; - this.height = source.height; - - this.leftMargin = source.leftMargin; - this.topMargin = source.topMargin; - this.rightMargin = source.rightMargin; - this.bottomMargin = source.bottomMargin; - } - - /** - * {@inheritDoc} - */ - public MarginLayoutParams(LayoutParams source) { - super(source); - } - - /** - * Sets the margins, in pixels. - * - * @param left the left margin size - * @param top the top margin size - * @param right the right margin size - * @param bottom the bottom margin size - * - * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginLeft - * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop - * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginRight - * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom - */ - public void setMargins(int left, int top, int right, int bottom) { - leftMargin = left; - topMargin = top; - rightMargin = right; - bottomMargin = bottom; - } - } -} diff --git a/core/java/android/view/ViewManager.java b/core/java/android/view/ViewManager.java deleted file mode 100644 index 7f318c1..0000000 --- a/core/java/android/view/ViewManager.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -/** Interface to let you add and remove child views to an Activity. To get an instance - * of this class, call {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}. - */ -public interface ViewManager -{ - public void addView(View view, ViewGroup.LayoutParams params); - public void updateViewLayout(View view, ViewGroup.LayoutParams params); - public void removeView(View view); -} diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java deleted file mode 100644 index b456c5d..0000000 --- a/core/java/android/view/ViewParent.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.graphics.Rect; - -/** - * Defines the responsibilities for a class that will be a parent of a View. - * This is the API that a view sees when it wants to interact with its parent. - * - */ -public interface ViewParent { - /** - * Called when something has changed which has invalidated the layout of a - * child of this view parent. This will schedule a layout pass of the view - * tree. - */ - public void requestLayout(); - - /** - * Indicates whether layout was requested on this view parent. - * - * @return true if layout was requested, false otherwise - */ - public boolean isLayoutRequested(); - - /** - * Called when a child wants the view hierarchy to gather and report - * transparent regions to the window compositor. Views that "punch" holes in - * the view hierarchy, such as SurfaceView can use this API to improve - * performance of the system. When no such a view is present in the - * hierarchy, this optimization in unnecessary and might slightly reduce the - * view hierarchy performance. - * - * @param child the view requesting the transparent region computation - * - */ - public void requestTransparentRegion(View child); - - /** - * All or part of a child is dirty and needs to be redrawn. - * - * @param child The child which is dirty - * @param r The area within the child that is invalid - */ - public void invalidateChild(View child, Rect r); - - /** - * All or part of a child is dirty and needs to be redrawn. - * - * The location array is an array of two int values which respectively - * define the left and the top position of the dirty child. - * - * This method must return the parent of this ViewParent if the specified - * rectangle must be invalidated in the parent. If the specified rectangle - * does not require invalidation in the parent or if the parent does not - * exist, this method must return null. - * - * When this method returns a non-null value, the location array must - * have been updated with the left and top coordinates of this ViewParent. - * - * @param location An array of 2 ints containing the left and top - * coordinates of the child to invalidate - * @param r The area within the child that is invalid - * - * @return the parent of this ViewParent or null - */ - public ViewParent invalidateChildInParent(int[] location, Rect r); - - /** - * Returns the parent if it exists, or null. - * - * @return a ViewParent or null if this ViewParent does not have a parent - */ - public ViewParent getParent(); - - /** - * Called when a child of this parent wants focus - * - * @param child The child of this ViewParent that wants focus. This view - * will contain the focused view. It is not necessarily the view that - * actually has focus. - * @param focused The view that is a descendant of child that actually has - * focus - */ - public void requestChildFocus(View child, View focused); - - /** - * Tell view hierarchy that the global view attributes need to be - * re-evaluated. - * - * @param child View whose attributes have changed. - */ - public void recomputeViewAttributes(View child); - - /** - * Called when a child of this parent is giving up focus - * - * @param child The view that is giving up focus - */ - public void clearChildFocus(View child); - - public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset); - - /** - * Find the nearest view in the specified direction that wants to take focus - * - * @param v The view that currently has focus - * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT - */ - public View focusSearch(View v, int direction); - - /** - * Change the z order of the child so it's on top of all other children - * - * @param child - */ - public void bringChildToFront(View child); - - /** - * Tells the parent that a new focusable view has become available. This is - * to handle transitions from the case where there are no focusable views to - * the case where the first focusable view appears. - * - * @param v The view that has become newly focusable - */ - public void focusableViewAvailable(View v); - - /** - * Bring up a context menu for the specified view or its ancestors. - * <p> - * In most cases, a subclass does not need to override this. However, if - * the subclass is added directly to the window manager (for example, - * {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)}) - * then it should override this and show the context menu. - * - * @param originalView The source view where the context menu was first invoked - * @return true if a context menu was displayed - */ - public boolean showContextMenuForChild(View originalView); - - /** - * Have the parent populate the specified context menu if it has anything to - * add (and then recurse on its parent). - * - * @param menu The menu to populate - */ - public void createContextMenu(ContextMenu menu); - - /** - * This method is called on the parent when a child's drawable state - * has changed. - * - * @param child The child whose drawable state has changed. - */ - public void childDrawableStateChanged(View child); - - /** - * Called when a child does not want this parent and its ancestors to - * intercept touch events with - * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}. - * <p> - * This parent should pass this call onto its parents. This parent must obey - * this request for the duration of the touch (that is, only clear the flag - * after this parent has received an up or a cancel. - * - * @param disallowIntercept True if the child does not want the parent to - * intercept touch events. - */ - public void requestDisallowInterceptTouchEvent(boolean disallowIntercept); - - /** - * Called when a child of this group wants a particular rectangle to be - * positioned onto the screen. {@link ViewGroup}s overriding this can trust - * that: - * <ul> - * <li>child will be a direct child of this group</li> - * <li>rectangle will be in the child's coordinates</li> - * </ul> - * - * <p>{@link ViewGroup}s overriding this should uphold the contract:</p> - * <ul> - * <li>nothing will change if the rectangle is already visible</li> - * <li>the view port will be scrolled only just enough to make the - * rectangle visible</li> - * <ul> - * - * @param child The direct child making the request. - * @param rectangle The rectangle in the child's coordinates the child - * wishes to be on the screen. - * @param immediate True to forbid animated or delayed scrolling, - * false otherwise - * @return Whether the group scrolled to handle the operation - */ - public boolean requestChildRectangleOnScreen(View child, Rect rectangle, - boolean immediate); -} diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java deleted file mode 100644 index 3cfaf1b..0000000 --- a/core/java/android/view/ViewRoot.java +++ /dev/null @@ -1,2845 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import com.android.internal.view.IInputMethodCallback; -import com.android.internal.view.IInputMethodSession; - -import android.graphics.Canvas; -import android.graphics.PixelFormat; -import android.graphics.Point; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.graphics.Region; -import android.os.*; -import android.os.Process; -import android.os.SystemProperties; -import android.util.AndroidRuntimeException; -import android.util.Config; -import android.util.Log; -import android.util.EventLog; -import android.util.SparseArray; -import android.util.DisplayMetrics; -import android.view.View.MeasureSpec; -import android.view.inputmethod.InputConnection; -import android.view.inputmethod.InputMethodManager; -import android.widget.Scroller; -import android.content.pm.PackageManager; -import android.content.Context; -import android.app.ActivityManagerNative; -import android.Manifest; -import android.media.AudioManager; - -import java.lang.ref.WeakReference; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; - -import javax.microedition.khronos.egl.*; -import javax.microedition.khronos.opengles.*; -import static javax.microedition.khronos.opengles.GL10.*; - -/** - * The top of a view hierarchy, implementing the needed protocol between View - * and the WindowManager. This is for the most part an internal implementation - * detail of {@link WindowManagerImpl}. - * - * {@hide} - */ -@SuppressWarnings({"EmptyCatchBlock"}) -public final class ViewRoot extends Handler implements ViewParent, - View.AttachInfo.Callbacks { - private static final String TAG = "ViewRoot"; - private static final boolean DBG = false; - @SuppressWarnings({"ConstantConditionalExpression"}) - private static final boolean LOCAL_LOGV = false ? Config.LOGD : Config.LOGV; - /** @noinspection PointlessBooleanExpression*/ - private static final boolean DEBUG_DRAW = false || LOCAL_LOGV; - private static final boolean DEBUG_LAYOUT = false || LOCAL_LOGV; - private static final boolean DEBUG_INPUT_RESIZE = false || LOCAL_LOGV; - private static final boolean DEBUG_ORIENTATION = false || LOCAL_LOGV; - private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV; - private static final boolean DEBUG_IMF = false || LOCAL_LOGV; - private static final boolean WATCH_POINTER = false; - - static final boolean PROFILE_DRAWING = false; - private static final boolean PROFILE_LAYOUT = false; - // profiles real fps (times between draws) and displays the result - private static final boolean SHOW_FPS = false; - // used by SHOW_FPS - private static int sDrawTime; - - /** - * Maximum time we allow the user to roll the trackball enough to generate - * a key event, before resetting the counters. - */ - static final int MAX_TRACKBALL_DELAY = 250; - - static long sInstanceCount = 0; - - static IWindowSession sWindowSession; - - static final Object mStaticInit = new Object(); - static boolean mInitialized = false; - - static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<RunQueue>(); - - long mLastTrackballTime = 0; - final TrackballAxis mTrackballAxisX = new TrackballAxis(); - final TrackballAxis mTrackballAxisY = new TrackballAxis(); - - final int[] mTmpLocation = new int[2]; - - final InputMethodCallback mInputMethodCallback; - final SparseArray<Object> mPendingEvents = new SparseArray<Object>(); - int mPendingEventSeq = 0; - - final Thread mThread; - - final WindowLeaked mLocation; - - final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams(); - - final W mWindow; - - View mView; - View mFocusedView; - View mRealFocusedView; // this is not set to null in touch mode - int mViewVisibility; - boolean mAppVisible = true; - - final Region mTransparentRegion; - final Region mPreviousTransparentRegion; - - int mWidth; - int mHeight; - Rect mDirty; // will be a graphics.Region soon - - final View.AttachInfo mAttachInfo; - - final Rect mTempRect; // used in the transaction to not thrash the heap. - final Rect mVisRect; // used to retrieve visible rect of focused view. - final Point mVisPoint; // used to retrieve global offset of focused view. - - boolean mTraversalScheduled; - boolean mWillDrawSoon; - boolean mLayoutRequested; - boolean mFirst; - boolean mReportNextDraw; - boolean mFullRedrawNeeded; - boolean mNewSurfaceNeeded; - boolean mHasHadWindowFocus; - - boolean mWindowAttributesChanged = false; - - // These can be accessed by any thread, must be protected with a lock. - Surface mSurface; - - boolean mAdded; - boolean mAddedTouchMode; - - /*package*/ int mAddNesting; - - // These are accessed by multiple threads. - final Rect mWinFrame; // frame given by window manager. - - final Rect mPendingVisibleInsets = new Rect(); - final Rect mPendingContentInsets = new Rect(); - final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets - = new ViewTreeObserver.InternalInsetsInfo(); - - boolean mScrollMayChange; - int mSoftInputMode; - View mLastScrolledFocus; - int mScrollY; - int mCurScrollY; - Scroller mScroller; - - EGL10 mEgl; - EGLDisplay mEglDisplay; - EGLContext mEglContext; - EGLSurface mEglSurface; - GL11 mGL; - Canvas mGlCanvas; - boolean mUseGL; - boolean mGlWanted; - - final ViewConfiguration mViewConfiguration; - - /** - * see {@link #playSoundEffect(int)} - */ - AudioManager mAudioManager; - - private final float mDensity; - - public ViewRoot(Context context) { - super(); - - ++sInstanceCount; - - // Initialize the statics when this class is first instantiated. This is - // done here instead of in the static block because Zygote does not - // allow the spawning of threads. - synchronized (mStaticInit) { - if (!mInitialized) { - try { - InputMethodManager imm = InputMethodManager.getInstance(context); - sWindowSession = IWindowManager.Stub.asInterface( - ServiceManager.getService("window")) - .openSession(imm.getClient(), imm.getInputContext()); - mInitialized = true; - } catch (RemoteException e) { - } - } - } - - mThread = Thread.currentThread(); - mLocation = new WindowLeaked(null); - mLocation.fillInStackTrace(); - mWidth = -1; - mHeight = -1; - mDirty = new Rect(); - mTempRect = new Rect(); - mVisRect = new Rect(); - mVisPoint = new Point(); - mWinFrame = new Rect(); - mWindow = new W(this); - mInputMethodCallback = new InputMethodCallback(this); - mViewVisibility = View.GONE; - mTransparentRegion = new Region(); - mPreviousTransparentRegion = new Region(); - mFirst = true; // true for the first time the view is added - mSurface = new Surface(); - mAdded = false; - mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, this); - mViewConfiguration = ViewConfiguration.get(context); - mDensity = context.getResources().getDisplayMetrics().density; - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - --sInstanceCount; - } - - public static long getInstanceCount() { - return sInstanceCount; - } - - // FIXME for perf testing only - private boolean mProfile = false; - - /** - * Call this to profile the next traversal call. - * FIXME for perf testing only. Remove eventually - */ - public void profile() { - mProfile = true; - } - - /** - * Indicates whether we are in touch mode. Calling this method triggers an IPC - * call and should be avoided whenever possible. - * - * @return True, if the device is in touch mode, false otherwise. - * - * @hide - */ - static boolean isInTouchMode() { - if (mInitialized) { - try { - return sWindowSession.getInTouchMode(); - } catch (RemoteException e) { - } - } - return false; - } - - private void initializeGL() { - initializeGLInner(); - int err = mEgl.eglGetError(); - if (err != EGL10.EGL_SUCCESS) { - // give-up on using GL - destroyGL(); - mGlWanted = false; - } - } - - private void initializeGLInner() { - final EGL10 egl = (EGL10) EGLContext.getEGL(); - mEgl = egl; - - /* - * Get to the default display. - */ - final EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - mEglDisplay = eglDisplay; - - /* - * We can now initialize EGL for that display - */ - int[] version = new int[2]; - egl.eglInitialize(eglDisplay, version); - - /* - * Specify a configuration for our opengl session - * and grab the first configuration that matches is - */ - final int[] configSpec = { - EGL10.EGL_RED_SIZE, 5, - EGL10.EGL_GREEN_SIZE, 6, - EGL10.EGL_BLUE_SIZE, 5, - EGL10.EGL_DEPTH_SIZE, 0, - EGL10.EGL_NONE - }; - final EGLConfig[] configs = new EGLConfig[1]; - final int[] num_config = new int[1]; - egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, num_config); - final EGLConfig config = configs[0]; - - /* - * Create an OpenGL ES context. This must be done only once, an - * OpenGL context is a somewhat heavy object. - */ - final EGLContext context = egl.eglCreateContext(eglDisplay, config, - EGL10.EGL_NO_CONTEXT, null); - mEglContext = context; - - /* - * Create an EGL surface we can render into. - */ - final EGLSurface surface = egl.eglCreateWindowSurface(eglDisplay, config, mHolder, null); - mEglSurface = surface; - - /* - * Before we can issue GL commands, we need to make sure - * the context is current and bound to a surface. - */ - egl.eglMakeCurrent(eglDisplay, surface, surface, context); - - /* - * Get to the appropriate GL interface. - * This is simply done by casting the GL context to either - * GL10 or GL11. - */ - final GL11 gl = (GL11) context.getGL(); - mGL = gl; - mGlCanvas = new Canvas(gl); - mUseGL = true; - } - - private void destroyGL() { - // inform skia that the context is gone - nativeAbandonGlCaches(); - - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); - mEgl.eglDestroyContext(mEglDisplay, mEglContext); - mEgl.eglDestroySurface(mEglDisplay, mEglSurface); - mEgl.eglTerminate(mEglDisplay); - mEglContext = null; - mEglSurface = null; - mEglDisplay = null; - mEgl = null; - mGlCanvas = null; - mGL = null; - mUseGL = false; - } - - private void checkEglErrors() { - if (mUseGL) { - int err = mEgl.eglGetError(); - if (err != EGL10.EGL_SUCCESS) { - // something bad has happened revert to - // normal rendering. - destroyGL(); - if (err != EGL11.EGL_CONTEXT_LOST) { - // we'll try again if it was context lost - mGlWanted = false; - } - } - } - } - - /** - * We have one child - */ - public void setView(View view, WindowManager.LayoutParams attrs, - View panelParentView) { - synchronized (this) { - if (mView == null) { - mWindowAttributes.copyFrom(attrs); - mSoftInputMode = attrs.softInputMode; - mWindowAttributesChanged = true; - mView = view; - mAttachInfo.mRootView = view; - if (panelParentView != null) { - mAttachInfo.mPanelParentWindowToken - = panelParentView.getApplicationWindowToken(); - } - mAdded = true; - int res; /* = WindowManagerImpl.ADD_OKAY; */ - - // Schedule the first layout -before- adding to the window - // manager, to make sure we do the relayout before receiving - // any other events from the system. - requestLayout(); - - try { - res = sWindowSession.add(mWindow, attrs, - getHostVisibility(), mAttachInfo.mContentInsets); - } catch (RemoteException e) { - mAdded = false; - mView = null; - mAttachInfo.mRootView = null; - unscheduleTraversals(); - throw new RuntimeException("Adding window failed", e); - } - mPendingContentInsets.set(mAttachInfo.mContentInsets); - mPendingVisibleInsets.set(0, 0, 0, 0); - if (Config.LOGV) Log.v("ViewRoot", "Added window " + mWindow); - if (res < WindowManagerImpl.ADD_OKAY) { - mView = null; - mAttachInfo.mRootView = null; - mAdded = false; - unscheduleTraversals(); - switch (res) { - case WindowManagerImpl.ADD_BAD_APP_TOKEN: - case WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN: - throw new WindowManagerImpl.BadTokenException( - "Unable to add window -- token " + attrs.token - + " is not valid; is your activity running?"); - case WindowManagerImpl.ADD_NOT_APP_TOKEN: - throw new WindowManagerImpl.BadTokenException( - "Unable to add window -- token " + attrs.token - + " is not for an application"); - case WindowManagerImpl.ADD_APP_EXITING: - throw new WindowManagerImpl.BadTokenException( - "Unable to add window -- app for token " + attrs.token - + " is exiting"); - case WindowManagerImpl.ADD_DUPLICATE_ADD: - throw new WindowManagerImpl.BadTokenException( - "Unable to add window -- window " + mWindow - + " has already been added"); - case WindowManagerImpl.ADD_STARTING_NOT_NEEDED: - // Silently ignore -- we would have just removed it - // right away, anyway. - return; - case WindowManagerImpl.ADD_MULTIPLE_SINGLETON: - throw new WindowManagerImpl.BadTokenException( - "Unable to add window " + mWindow + - " -- another window of this type already exists"); - case WindowManagerImpl.ADD_PERMISSION_DENIED: - throw new WindowManagerImpl.BadTokenException( - "Unable to add window " + mWindow + - " -- permission denied for this window type"); - } - throw new RuntimeException( - "Unable to add window -- unknown error code " + res); - } - view.assignParent(this); - mAddedTouchMode = (res&WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE) != 0; - mAppVisible = (res&WindowManagerImpl.ADD_FLAG_APP_VISIBLE) != 0; - } - } - } - - public View getView() { - return mView; - } - - final WindowLeaked getLocation() { - return mLocation; - } - - void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) { - synchronized (this) { - mWindowAttributes.copyFrom(attrs); - if (newView) { - mSoftInputMode = attrs.softInputMode; - requestLayout(); - } - mWindowAttributesChanged = true; - scheduleTraversals(); - } - } - - void handleAppVisibility(boolean visible) { - if (mAppVisible != visible) { - mAppVisible = visible; - scheduleTraversals(); - } - } - - void handleGetNewSurface() { - mNewSurfaceNeeded = true; - mFullRedrawNeeded = true; - scheduleTraversals(); - } - - /** - * {@inheritDoc} - */ - public void requestLayout() { - checkThread(); - mLayoutRequested = true; - scheduleTraversals(); - } - - /** - * {@inheritDoc} - */ - public boolean isLayoutRequested() { - return mLayoutRequested; - } - - public void invalidateChild(View child, Rect dirty) { - checkThread(); - if (LOCAL_LOGV) Log.v(TAG, "Invalidate child: " + dirty); - if (mCurScrollY != 0) { - mTempRect.set(dirty); - mTempRect.offset(0, -mCurScrollY); - dirty = mTempRect; - } - mDirty.union(dirty); - if (!mWillDrawSoon) { - scheduleTraversals(); - } - } - - public ViewParent getParent() { - return null; - } - - public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) { - invalidateChild(null, dirty); - return null; - } - - public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) { - if (child != mView) { - throw new RuntimeException("child is not mine, honest!"); - } - // Note: don't apply scroll offset, because we want to know its - // visibility in the virtual canvas being given to the view hierarchy. - return r.intersect(0, 0, mWidth, mHeight); - } - - public void bringChildToFront(View child) { - } - - public void scheduleTraversals() { - if (!mTraversalScheduled) { - mTraversalScheduled = true; - sendEmptyMessage(DO_TRAVERSAL); - } - } - - public void unscheduleTraversals() { - if (mTraversalScheduled) { - mTraversalScheduled = false; - removeMessages(DO_TRAVERSAL); - } - } - - int getHostVisibility() { - return mAppVisible ? mView.getVisibility() : View.GONE; - } - - private void performTraversals() { - // cache mView since it is used so much below... - final View host = mView; - - if (DBG) { - System.out.println("======================================"); - System.out.println("performTraversals"); - host.debug(); - } - - if (host == null || !mAdded) - return; - - mTraversalScheduled = false; - mWillDrawSoon = true; - boolean windowResizesToFitContent = false; - boolean fullRedrawNeeded = mFullRedrawNeeded; - boolean newSurface = false; - WindowManager.LayoutParams lp = mWindowAttributes; - - int desiredWindowWidth; - int desiredWindowHeight; - int childWidthMeasureSpec; - int childHeightMeasureSpec; - - final View.AttachInfo attachInfo = mAttachInfo; - - final int viewVisibility = getHostVisibility(); - boolean viewVisibilityChanged = mViewVisibility != viewVisibility - || mNewSurfaceNeeded; - - WindowManager.LayoutParams params = null; - if (mWindowAttributesChanged) { - mWindowAttributesChanged = false; - params = lp; - } - - if (mFirst) { - fullRedrawNeeded = true; - mLayoutRequested = true; - - Display d = new Display(0); - desiredWindowWidth = d.getWidth(); - desiredWindowHeight = d.getHeight(); - - // For the very first time, tell the view hierarchy that it - // is attached to the window. Note that at this point the surface - // object is not initialized to its backing store, but soon it - // will be (assuming the window is visible). - attachInfo.mSurface = mSurface; - attachInfo.mHasWindowFocus = false; - attachInfo.mWindowVisibility = viewVisibility; - attachInfo.mRecomputeGlobalAttributes = false; - attachInfo.mKeepScreenOn = false; - viewVisibilityChanged = false; - host.dispatchAttachedToWindow(attachInfo, 0); - getRunQueue().executeActions(attachInfo.mHandler); - //Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn); - } else { - desiredWindowWidth = mWinFrame.width(); - desiredWindowHeight = mWinFrame.height(); - if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) { - if (DEBUG_ORIENTATION) Log.v("ViewRoot", - "View " + host + " resized to: " + mWinFrame); - fullRedrawNeeded = true; - mLayoutRequested = true; - windowResizesToFitContent = true; - } - } - - if (viewVisibilityChanged) { - attachInfo.mWindowVisibility = viewVisibility; - host.dispatchWindowVisibilityChanged(viewVisibility); - if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) { - if (mUseGL) { - destroyGL(); - } - } - if (viewVisibility == View.GONE) { - // After making a window gone, we will count it as being - // shown for the first time the next time it gets focus. - mHasHadWindowFocus = false; - } - } - - boolean insetsChanged = false; - - if (mLayoutRequested) { - if (mFirst) { - host.fitSystemWindows(mAttachInfo.mContentInsets); - // make sure touch mode code executes by setting cached value - // to opposite of the added touch mode. - mAttachInfo.mInTouchMode = !mAddedTouchMode; - ensureTouchModeLocally(mAddedTouchMode); - } else { - if (!mAttachInfo.mContentInsets.equals(mPendingContentInsets)) { - mAttachInfo.mContentInsets.set(mPendingContentInsets); - host.fitSystemWindows(mAttachInfo.mContentInsets); - insetsChanged = true; - if (DEBUG_LAYOUT) Log.v(TAG, "Content insets changing to: " - + mAttachInfo.mContentInsets); - } - if (!mAttachInfo.mVisibleInsets.equals(mPendingVisibleInsets)) { - mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets); - if (DEBUG_LAYOUT) Log.v(TAG, "Visible insets changing to: " - + mAttachInfo.mVisibleInsets); - } - if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT - || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) { - windowResizesToFitContent = true; - - Display d = new Display(0); - desiredWindowWidth = d.getWidth(); - desiredWindowHeight = d.getHeight(); - } - } - - childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width); - childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height); - - // Ask host how big it wants to be - if (DEBUG_ORIENTATION || DEBUG_LAYOUT) Log.v("ViewRoot", - "Measuring " + host + " in display " + desiredWindowWidth - + "x" + desiredWindowHeight + "..."); - host.measure(childWidthMeasureSpec, childHeightMeasureSpec); - - if (DBG) { - System.out.println("======================================"); - System.out.println("performTraversals -- after measure"); - host.debug(); - } - } - - if (attachInfo.mRecomputeGlobalAttributes) { - //Log.i(TAG, "Computing screen on!"); - attachInfo.mRecomputeGlobalAttributes = false; - boolean oldVal = attachInfo.mKeepScreenOn; - attachInfo.mKeepScreenOn = false; - host.dispatchCollectViewAttributes(0); - if (attachInfo.mKeepScreenOn != oldVal) { - params = lp; - //Log.i(TAG, "Keep screen on changed: " + attachInfo.mKeepScreenOn); - } - } - - if (mFirst || attachInfo.mViewVisibilityChanged) { - attachInfo.mViewVisibilityChanged = false; - int resizeMode = mSoftInputMode & - WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; - // If we are in auto resize mode, then we need to determine - // what mode to use now. - if (resizeMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) { - final int N = attachInfo.mScrollContainers.size(); - for (int i=0; i<N; i++) { - if (attachInfo.mScrollContainers.get(i).isShown()) { - resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; - } - } - if (resizeMode == 0) { - resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN; - } - if ((lp.softInputMode & - WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) != resizeMode) { - lp.softInputMode = (lp.softInputMode & - ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) | - resizeMode; - params = lp; - } - } - } - - if (params != null && (host.mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) != 0) { - if (!PixelFormat.formatHasAlpha(params.format)) { - params.format = PixelFormat.TRANSLUCENT; - } - } - - boolean windowShouldResize = mLayoutRequested && windowResizesToFitContent - && (mWidth != host.mMeasuredWidth || mHeight != host.mMeasuredHeight); - - final boolean computesInternalInsets = - attachInfo.mTreeObserver.hasComputeInternalInsetsListeners(); - boolean insetsPending = false; - int relayoutResult = 0; - if (mFirst || windowShouldResize || insetsChanged - || viewVisibilityChanged || params != null) { - - if (viewVisibility == View.VISIBLE) { - // If this window is giving internal insets to the window - // manager, and it is being added or changing its visibility, - // then we want to first give the window manager "fake" - // insets to cause it to effectively ignore the content of - // the window during layout. This avoids it briefly causing - // other windows to resize/move based on the raw frame of the - // window, waiting until we can finish laying out this window - // and get back to the window manager with the ultimately - // computed insets. - insetsPending = computesInternalInsets - && (mFirst || viewVisibilityChanged); - - if (mWindowAttributes.memoryType == WindowManager.LayoutParams.MEMORY_TYPE_GPU) { - if (params == null) { - params = mWindowAttributes; - } - mGlWanted = true; - } - } - - final Rect frame = mWinFrame; - boolean initialized = false; - boolean contentInsetsChanged = false; - boolean visibleInsetsChanged = false; - try { - boolean hadSurface = mSurface.isValid(); - int fl = 0; - if (params != null) { - fl = params.flags; - if (attachInfo.mKeepScreenOn) { - params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; - } - } - relayoutResult = sWindowSession.relayout( - mWindow, params, host.mMeasuredWidth, host.mMeasuredHeight, - viewVisibility, insetsPending, frame, - mPendingContentInsets, mPendingVisibleInsets, mSurface); - if (params != null) { - params.flags = fl; - } - - if (DEBUG_LAYOUT) Log.v(TAG, "relayout: frame=" + frame.toShortString() - + " content=" + mPendingContentInsets.toShortString() - + " visible=" + mPendingVisibleInsets.toShortString() - + " surface=" + mSurface); - - contentInsetsChanged = !mPendingContentInsets.equals( - mAttachInfo.mContentInsets); - visibleInsetsChanged = !mPendingVisibleInsets.equals( - mAttachInfo.mVisibleInsets); - if (contentInsetsChanged) { - mAttachInfo.mContentInsets.set(mPendingContentInsets); - host.fitSystemWindows(mAttachInfo.mContentInsets); - if (DEBUG_LAYOUT) Log.v(TAG, "Content insets changing to: " - + mAttachInfo.mContentInsets); - } - if (visibleInsetsChanged) { - mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets); - if (DEBUG_LAYOUT) Log.v(TAG, "Visible insets changing to: " - + mAttachInfo.mVisibleInsets); - } - - if (!hadSurface) { - if (mSurface.isValid()) { - // If we are creating a new surface, then we need to - // completely redraw it. Also, when we get to the - // point of drawing it we will hold off and schedule - // a new traversal instead. This is so we can tell the - // window manager about all of the windows being displayed - // before actually drawing them, so it can display then - // all at once. - newSurface = true; - fullRedrawNeeded = true; - - if (mGlWanted && !mUseGL) { - initializeGL(); - initialized = mGlCanvas != null; - } - } - } else if (!mSurface.isValid()) { - // If the surface has been removed, then reset the scroll - // positions. - mLastScrolledFocus = null; - mScrollY = mCurScrollY = 0; - if (mScroller != null) { - mScroller.abortAnimation(); - } - } - } catch (RemoteException e) { - } - if (DEBUG_ORIENTATION) Log.v( - "ViewRoot", "Relayout returned: frame=" + mWinFrame + ", surface=" + mSurface); - - attachInfo.mWindowLeft = frame.left; - attachInfo.mWindowTop = frame.top; - - // !!FIXME!! This next section handles the case where we did not get the - // window size we asked for. We should avoid this by getting a maximum size from - // the window session beforehand. - mWidth = frame.width(); - mHeight = frame.height(); - - if (initialized) { - mGlCanvas.setViewport(mWidth, mHeight); - } - - boolean focusChangedDueToTouchMode = ensureTouchModeLocally( - (relayoutResult&WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE) != 0); - if (focusChangedDueToTouchMode || mWidth != host.mMeasuredWidth - || mHeight != host.mMeasuredHeight || contentInsetsChanged) { - childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width); - childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height); - - if (DEBUG_LAYOUT) Log.v(TAG, "Ooops, something changed! mWidth=" - + mWidth + " measuredWidth=" + host.mMeasuredWidth - + " mHeight=" + mHeight - + " measuredHeight" + host.mMeasuredHeight - + " coveredInsetsChanged=" + contentInsetsChanged); - - // Ask host how big it wants to be - host.measure(childWidthMeasureSpec, childHeightMeasureSpec); - - // Implementation of weights from WindowManager.LayoutParams - // We just grow the dimensions as needed and re-measure if - // needs be - int width = host.mMeasuredWidth; - int height = host.mMeasuredHeight; - boolean measureAgain = false; - - if (lp.horizontalWeight > 0.0f) { - width += (int) ((mWidth - width) * lp.horizontalWeight); - childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, - MeasureSpec.EXACTLY); - measureAgain = true; - } - if (lp.verticalWeight > 0.0f) { - height += (int) ((mHeight - height) * lp.verticalWeight); - childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, - MeasureSpec.EXACTLY); - measureAgain = true; - } - - if (measureAgain) { - if (DEBUG_LAYOUT) Log.v(TAG, - "And hey let's measure once more: width=" + width - + " height=" + height); - host.measure(childWidthMeasureSpec, childHeightMeasureSpec); - } - - mLayoutRequested = true; - } - } - - final boolean didLayout = mLayoutRequested; - boolean triggerGlobalLayoutListener = didLayout - || attachInfo.mRecomputeGlobalAttributes; - if (didLayout) { - mLayoutRequested = false; - mScrollMayChange = true; - if (DEBUG_ORIENTATION || DEBUG_LAYOUT) Log.v( - "ViewRoot", "Laying out " + host + " to (" + - host.mMeasuredWidth + ", " + host.mMeasuredHeight + ")"); - long startTime; - if (PROFILE_LAYOUT) { - startTime = SystemClock.elapsedRealtime(); - } - - host.layout(0, 0, host.mMeasuredWidth, host.mMeasuredHeight); - - if (PROFILE_LAYOUT) { - EventLog.writeEvent(60001, SystemClock.elapsedRealtime() - startTime); - } - - // By this point all views have been sized and positionned - // We can compute the transparent area - - if ((host.mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) != 0) { - // start out transparent - // TODO: AVOID THAT CALL BY CACHING THE RESULT? - host.getLocationInWindow(mTmpLocation); - mTransparentRegion.set(mTmpLocation[0], mTmpLocation[1], - mTmpLocation[0] + host.mRight - host.mLeft, - mTmpLocation[1] + host.mBottom - host.mTop); - - host.gatherTransparentRegion(mTransparentRegion); - if (!mTransparentRegion.equals(mPreviousTransparentRegion)) { - mPreviousTransparentRegion.set(mTransparentRegion); - // reconfigure window manager - try { - sWindowSession.setTransparentRegion(mWindow, mTransparentRegion); - } catch (RemoteException e) { - } - } - } - - - if (DBG) { - System.out.println("======================================"); - System.out.println("performTraversals -- after setFrame"); - host.debug(); - } - } - - if (triggerGlobalLayoutListener) { - attachInfo.mRecomputeGlobalAttributes = false; - attachInfo.mTreeObserver.dispatchOnGlobalLayout(); - } - - if (computesInternalInsets) { - ViewTreeObserver.InternalInsetsInfo insets = attachInfo.mGivenInternalInsets; - final Rect givenContent = attachInfo.mGivenInternalInsets.contentInsets; - final Rect givenVisible = attachInfo.mGivenInternalInsets.visibleInsets; - givenContent.left = givenContent.top = givenContent.right - = givenContent.bottom = givenVisible.left = givenVisible.top - = givenVisible.right = givenVisible.bottom = 0; - attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets); - if (insetsPending || !mLastGivenInsets.equals(insets)) { - mLastGivenInsets.set(insets); - try { - sWindowSession.setInsets(mWindow, insets.mTouchableInsets, - insets.contentInsets, insets.visibleInsets); - } catch (RemoteException e) { - } - } - } - - if (mFirst) { - // handle first focus request - if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: mView.hasFocus()=" - + mView.hasFocus()); - if (mView != null) { - if (!mView.hasFocus()) { - mView.requestFocus(View.FOCUS_FORWARD); - mFocusedView = mRealFocusedView = mView.findFocus(); - if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: requested focused view=" - + mFocusedView); - } else { - mRealFocusedView = mView.findFocus(); - if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: existing focused view=" - + mRealFocusedView); - } - } - } - - mFirst = false; - mWillDrawSoon = false; - mNewSurfaceNeeded = false; - mViewVisibility = viewVisibility; - - boolean cancelDraw = attachInfo.mTreeObserver.dispatchOnPreDraw(); - - if (!cancelDraw && !newSurface) { - mFullRedrawNeeded = false; - draw(fullRedrawNeeded); - - if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0 - || mReportNextDraw) { - if (LOCAL_LOGV) { - Log.v("ViewRoot", "FINISHED DRAWING: " + mWindowAttributes.getTitle()); - } - mReportNextDraw = false; - try { - sWindowSession.finishDrawing(mWindow); - } catch (RemoteException e) { - } - } - } else { - // We were supposed to report when we are done drawing. Since we canceled the - // draw, remember it here. - if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) { - mReportNextDraw = true; - } - if (fullRedrawNeeded) { - mFullRedrawNeeded = true; - } - // Try again - scheduleTraversals(); - } - } - - public void requestTransparentRegion(View child) { - // the test below should not fail unless someone is messing with us - checkThread(); - if (mView == child) { - mView.mPrivateFlags |= View.REQUEST_TRANSPARENT_REGIONS; - // Need to make sure we re-evaluate the window attributes next - // time around, to ensure the window has the correct format. - mWindowAttributesChanged = true; - } - } - - /** - * Figures out the measure spec for the root view in a window based on it's - * layout params. - * - * @param windowSize - * The available width or height of the window - * - * @param rootDimension - * The layout params for one dimension (width or height) of the - * window. - * - * @return The measure spec to use to measure the root view. - */ - private int getRootMeasureSpec(int windowSize, int rootDimension) { - int measureSpec; - switch (rootDimension) { - - case ViewGroup.LayoutParams.FILL_PARENT: - // Window can't resize. Force root view to be windowSize. - measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY); - break; - case ViewGroup.LayoutParams.WRAP_CONTENT: - // Window can resize. Set max size for root view. - measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST); - break; - default: - // Window wants to be an exact size. Force root view to be that size. - measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY); - break; - } - return measureSpec; - } - - private void draw(boolean fullRedrawNeeded) { - Surface surface = mSurface; - if (surface == null || !surface.isValid()) { - return; - } - - scrollToRectOrFocus(null, false); - - if (mAttachInfo.mViewScrollChanged) { - mAttachInfo.mViewScrollChanged = false; - mAttachInfo.mTreeObserver.dispatchOnScrollChanged(); - } - - int yoff; - final boolean scrolling = mScroller != null - && mScroller.computeScrollOffset(); - if (scrolling) { - yoff = mScroller.getCurrY(); - } else { - yoff = mScrollY; - } - if (mCurScrollY != yoff) { - mCurScrollY = yoff; - fullRedrawNeeded = true; - } - - Rect dirty = mDirty; - if (mUseGL) { - if (!dirty.isEmpty()) { - Canvas canvas = mGlCanvas; - if (mGL!=null && canvas != null) { - mGL.glDisable(GL_SCISSOR_TEST); - mGL.glClearColor(0, 0, 0, 0); - mGL.glClear(GL_COLOR_BUFFER_BIT); - mGL.glEnable(GL_SCISSOR_TEST); - - mAttachInfo.mDrawingTime = SystemClock.uptimeMillis(); - canvas.translate(0, -yoff); - mView.mPrivateFlags |= View.DRAWN; - mView.draw(canvas); - canvas.translate(0, yoff); - - mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); - checkEglErrors(); - - if (SHOW_FPS) { - int now = (int)SystemClock.elapsedRealtime(); - if (sDrawTime != 0) { - nativeShowFPS(canvas, now - sDrawTime); - } - sDrawTime = now; - } - } - } - if (scrolling) { - mFullRedrawNeeded = true; - scheduleTraversals(); - } - return; - } - - if (fullRedrawNeeded) - dirty.union(0, 0, mWidth, mHeight); - - if (DEBUG_ORIENTATION || DEBUG_DRAW) { - Log.v("ViewRoot", "Draw " + mView + "/" - + mWindowAttributes.getTitle() - + ": dirty={" + dirty.left + "," + dirty.top - + "," + dirty.right + "," + dirty.bottom + "} surface=" - + surface + " surface.isValid()=" + surface.isValid()); - } - - Canvas canvas; - try { - canvas = surface.lockCanvas(dirty); - // TODO: Do this in native - canvas.setDensityScale(mDensity); - } catch (Surface.OutOfResourcesException e) { - Log.e("ViewRoot", "OutOfResourcesException locking surface", e); - // TODO: we should ask the window manager to do something! - // for now we just do nothing - return; - } - - try { - if (!dirty.isEmpty()) { - long startTime; - - if (DEBUG_ORIENTATION || DEBUG_DRAW) { - Log.v("ViewRoot", "Surface " + surface + " drawing to bitmap w=" - + canvas.getWidth() + ", h=" + canvas.getHeight()); - //canvas.drawARGB(255, 255, 0, 0); - } - - if (PROFILE_DRAWING) { - startTime = SystemClock.elapsedRealtime(); - } - - // If this bitmap's format includes an alpha channel, we - // need to clear it before drawing so that the child will - // properly re-composite its drawing on a transparent - // background. This automatically respects the clip/dirty region - if (!canvas.isOpaque()) { - canvas.drawColor(0xff0000ff, PorterDuff.Mode.CLEAR); - } else if (yoff != 0) { - // If we are applying an offset, we need to clear the area - // where the offset doesn't appear to avoid having garbage - // left in the blank areas. - canvas.drawColor(0, PorterDuff.Mode.CLEAR); - } - - dirty.setEmpty(); - mAttachInfo.mDrawingTime = SystemClock.uptimeMillis(); - canvas.translate(0, -yoff); - mView.mPrivateFlags |= View.DRAWN; - mView.draw(canvas); - canvas.translate(0, yoff); - - if (SHOW_FPS) { - int now = (int)SystemClock.elapsedRealtime(); - if (sDrawTime != 0) { - nativeShowFPS(canvas, now - sDrawTime); - } - sDrawTime = now; - } - - if (PROFILE_DRAWING) { - EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime); - } - } - - } finally { - surface.unlockCanvasAndPost(canvas); - } - - if (LOCAL_LOGV) { - Log.v("ViewRoot", "Surface " + surface + " unlockCanvasAndPost"); - } - - if (scrolling) { - mFullRedrawNeeded = true; - scheduleTraversals(); - } - } - - boolean scrollToRectOrFocus(Rect rectangle, boolean immediate) { - final View.AttachInfo attachInfo = mAttachInfo; - final Rect ci = attachInfo.mContentInsets; - final Rect vi = attachInfo.mVisibleInsets; - int scrollY = 0; - boolean handled = false; - - if (vi.left > ci.left || vi.top > ci.top - || vi.right > ci.right || vi.bottom > ci.bottom) { - // We'll assume that we aren't going to change the scroll - // offset, since we want to avoid that unless it is actually - // going to make the focus visible... otherwise we scroll - // all over the place. - scrollY = mScrollY; - // We can be called for two different situations: during a draw, - // to update the scroll position if the focus has changed (in which - // case 'rectangle' is null), or in response to a - // requestChildRectangleOnScreen() call (in which case 'rectangle' - // is non-null and we just want to scroll to whatever that - // rectangle is). - View focus = mRealFocusedView; - if (focus != mLastScrolledFocus) { - // If the focus has changed, then ignore any requests to scroll - // to a rectangle; first we want to make sure the entire focus - // view is visible. - rectangle = null; - } - if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Eval scroll: focus=" + focus - + " rectangle=" + rectangle + " ci=" + ci - + " vi=" + vi); - if (focus == mLastScrolledFocus && !mScrollMayChange - && rectangle == null) { - // Optimization: if the focus hasn't changed since last - // time, and no layout has happened, then just leave things - // as they are. - if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Keeping scroll y=" - + mScrollY + " vi=" + vi.toShortString()); - } else if (focus != null) { - // We need to determine if the currently focused view is - // within the visible part of the window and, if not, apply - // a pan so it can be seen. - mLastScrolledFocus = focus; - mScrollMayChange = false; - if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Need to scroll?"); - // Try to find the rectangle from the focus view. - if (focus.getGlobalVisibleRect(mVisRect, null)) { - if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Root w=" - + mView.getWidth() + " h=" + mView.getHeight() - + " ci=" + ci.toShortString() - + " vi=" + vi.toShortString()); - if (rectangle == null) { - focus.getFocusedRect(mTempRect); - if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Focus " + focus - + ": focusRect=" + mTempRect.toShortString()); - ((ViewGroup) mView).offsetDescendantRectToMyCoords( - focus, mTempRect); - if (DEBUG_INPUT_RESIZE) Log.v(TAG, - "Focus in window: focusRect=" - + mTempRect.toShortString() - + " visRect=" + mVisRect.toShortString()); - } else { - mTempRect.set(rectangle); - if (DEBUG_INPUT_RESIZE) Log.v(TAG, - "Request scroll to rect: " - + mTempRect.toShortString() - + " visRect=" + mVisRect.toShortString()); - } - if (mTempRect.intersect(mVisRect)) { - if (DEBUG_INPUT_RESIZE) Log.v(TAG, - "Focus window visible rect: " - + mTempRect.toShortString()); - if (mTempRect.height() > - (mView.getHeight()-vi.top-vi.bottom)) { - // If the focus simply is not going to fit, then - // best is probably just to leave things as-is. - if (DEBUG_INPUT_RESIZE) Log.v(TAG, - "Too tall; leaving scrollY=" + scrollY); - } else if ((mTempRect.top-scrollY) < vi.top) { - scrollY -= vi.top - (mTempRect.top-scrollY); - if (DEBUG_INPUT_RESIZE) Log.v(TAG, - "Top covered; scrollY=" + scrollY); - } else if ((mTempRect.bottom-scrollY) - > (mView.getHeight()-vi.bottom)) { - scrollY += (mTempRect.bottom-scrollY) - - (mView.getHeight()-vi.bottom); - if (DEBUG_INPUT_RESIZE) Log.v(TAG, - "Bottom covered; scrollY=" + scrollY); - } - handled = true; - } - } - } - } - - if (scrollY != mScrollY) { - if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Pan scroll changed: old=" - + mScrollY + " , new=" + scrollY); - if (!immediate) { - if (mScroller == null) { - mScroller = new Scroller(mView.getContext()); - } - mScroller.startScroll(0, mScrollY, 0, scrollY-mScrollY); - } else if (mScroller != null) { - mScroller.abortAnimation(); - } - mScrollY = scrollY; - } - - return handled; - } - - public void requestChildFocus(View child, View focused) { - checkThread(); - if (mFocusedView != focused) { - mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mFocusedView, focused); - scheduleTraversals(); - } - mFocusedView = mRealFocusedView = focused; - if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Request child focus: focus now " - + mFocusedView); - } - - public void clearChildFocus(View child) { - checkThread(); - - View oldFocus = mFocusedView; - - if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Clearing child focus"); - mFocusedView = mRealFocusedView = null; - if (mView != null && !mView.hasFocus()) { - // If a view gets the focus, the listener will be invoked from requestChildFocus() - if (!mView.requestFocus(View.FOCUS_FORWARD)) { - mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null); - } - } else if (oldFocus != null) { - mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null); - } - } - - - public void focusableViewAvailable(View v) { - checkThread(); - - if (mView != null && !mView.hasFocus()) { - v.requestFocus(); - } else { - // the one case where will transfer focus away from the current one - // is if the current view is a view group that prefers to give focus - // to its children first AND the view is a descendant of it. - mFocusedView = mView.findFocus(); - boolean descendantsHaveDibsOnFocus = - (mFocusedView instanceof ViewGroup) && - (((ViewGroup) mFocusedView).getDescendantFocusability() == - ViewGroup.FOCUS_AFTER_DESCENDANTS); - if (descendantsHaveDibsOnFocus && isViewDescendantOf(v, mFocusedView)) { - // If a view gets the focus, the listener will be invoked from requestChildFocus() - v.requestFocus(); - } - } - } - - public void recomputeViewAttributes(View child) { - checkThread(); - if (mView == child) { - mAttachInfo.mRecomputeGlobalAttributes = true; - if (!mWillDrawSoon) { - scheduleTraversals(); - } - } - } - - void dispatchDetachedFromWindow() { - if (Config.LOGV) Log.v("ViewRoot", "Detaching in " + this + " of " + mSurface); - - if (mView != null) { - mView.dispatchDetachedFromWindow(); - } - - mView = null; - mAttachInfo.mRootView = null; - - if (mUseGL) { - destroyGL(); - } - - try { - sWindowSession.remove(mWindow); - } catch (RemoteException e) { - } - } - - /** - * Return true if child is an ancestor of parent, (or equal to the parent). - */ - private static boolean isViewDescendantOf(View child, View parent) { - if (child == parent) { - return true; - } - - final ViewParent theParent = child.getParent(); - return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent); - } - - - public final static int DO_TRAVERSAL = 1000; - public final static int DIE = 1001; - public final static int RESIZED = 1002; - public final static int RESIZED_REPORT = 1003; - public final static int WINDOW_FOCUS_CHANGED = 1004; - public final static int DISPATCH_KEY = 1005; - public final static int DISPATCH_POINTER = 1006; - public final static int DISPATCH_TRACKBALL = 1007; - public final static int DISPATCH_APP_VISIBILITY = 1008; - public final static int DISPATCH_GET_NEW_SURFACE = 1009; - public final static int FINISHED_EVENT = 1010; - public final static int DISPATCH_KEY_FROM_IME = 1011; - public final static int FINISH_INPUT_CONNECTION = 1012; - public final static int CHECK_FOCUS = 1013; - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case View.AttachInfo.INVALIDATE_MSG: - ((View) msg.obj).invalidate(); - break; - case View.AttachInfo.INVALIDATE_RECT_MSG: - final View.AttachInfo.InvalidateInfo info = (View.AttachInfo.InvalidateInfo) msg.obj; - info.target.invalidate(info.left, info.top, info.right, info.bottom); - info.release(); - break; - case DO_TRAVERSAL: - if (mProfile) { - Debug.startMethodTracing("ViewRoot"); - } - - performTraversals(); - - if (mProfile) { - Debug.stopMethodTracing(); - mProfile = false; - } - break; - case FINISHED_EVENT: - handleFinishedEvent(msg.arg1, msg.arg2 != 0); - break; - case DISPATCH_KEY: - if (LOCAL_LOGV) Log.v( - "ViewRoot", "Dispatching key " - + msg.obj + " to " + mView); - deliverKeyEvent((KeyEvent)msg.obj, true); - break; - case DISPATCH_POINTER: - MotionEvent event = (MotionEvent)msg.obj; - - boolean didFinish; - if (event == null) { - try { - event = sWindowSession.getPendingPointerMove(mWindow); - } catch (RemoteException e) { - } - didFinish = true; - } else { - didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE; - } - - try { - boolean handled; - if (mView != null && mAdded && event != null) { - - // enter touch mode on the down - boolean isDown = event.getAction() == MotionEvent.ACTION_DOWN; - if (isDown) { - ensureTouchMode(true); - } - if(Config.LOGV) { - captureMotionLog("captureDispatchPointer", event); - } - event.offsetLocation(0, mCurScrollY); - handled = mView.dispatchTouchEvent(event); - if (!handled && isDown) { - int edgeSlop = mViewConfiguration.getScaledEdgeSlop(); - - final int edgeFlags = event.getEdgeFlags(); - int direction = View.FOCUS_UP; - int x = (int)event.getX(); - int y = (int)event.getY(); - final int[] deltas = new int[2]; - - if ((edgeFlags & MotionEvent.EDGE_TOP) != 0) { - direction = View.FOCUS_DOWN; - if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) { - deltas[0] = edgeSlop; - x += edgeSlop; - } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) { - deltas[0] = -edgeSlop; - x -= edgeSlop; - } - } else if ((edgeFlags & MotionEvent.EDGE_BOTTOM) != 0) { - direction = View.FOCUS_UP; - if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) { - deltas[0] = edgeSlop; - x += edgeSlop; - } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) { - deltas[0] = -edgeSlop; - x -= edgeSlop; - } - } else if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) { - direction = View.FOCUS_RIGHT; - } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) { - direction = View.FOCUS_LEFT; - } - - if (edgeFlags != 0 && mView instanceof ViewGroup) { - View nearest = FocusFinder.getInstance().findNearestTouchable( - ((ViewGroup) mView), x, y, direction, deltas); - if (nearest != null) { - event.offsetLocation(deltas[0], deltas[1]); - event.setEdgeFlags(0); - mView.dispatchTouchEvent(event); - } - } - } - } - } finally { - if (!didFinish) { - try { - sWindowSession.finishKey(mWindow); - } catch (RemoteException e) { - } - } - if (event != null) { - event.recycle(); - } - if (LOCAL_LOGV || WATCH_POINTER) Log.i(TAG, "Done dispatching!"); - // Let the exception fall through -- the looper will catch - // it and take care of the bad app for us. - } - break; - case DISPATCH_TRACKBALL: - deliverTrackballEvent((MotionEvent)msg.obj); - break; - case DISPATCH_APP_VISIBILITY: - handleAppVisibility(msg.arg1 != 0); - break; - case DISPATCH_GET_NEW_SURFACE: - handleGetNewSurface(); - break; - case RESIZED: - Rect coveredInsets = ((Rect[])msg.obj)[0]; - Rect visibleInsets = ((Rect[])msg.obj)[1]; - if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2 - && mPendingContentInsets.equals(coveredInsets) - && mPendingVisibleInsets.equals(visibleInsets)) { - break; - } - // fall through... - case RESIZED_REPORT: - if (mAdded) { - mWinFrame.left = 0; - mWinFrame.right = msg.arg1; - mWinFrame.top = 0; - mWinFrame.bottom = msg.arg2; - mPendingContentInsets.set(((Rect[])msg.obj)[0]); - mPendingVisibleInsets.set(((Rect[])msg.obj)[1]); - if (msg.what == RESIZED_REPORT) { - mReportNextDraw = true; - } - requestLayout(); - } - break; - case WINDOW_FOCUS_CHANGED: { - if (mAdded) { - boolean hasWindowFocus = msg.arg1 != 0; - mAttachInfo.mHasWindowFocus = hasWindowFocus; - if (hasWindowFocus) { - boolean inTouchMode = msg.arg2 != 0; - ensureTouchModeLocally(inTouchMode); - - if (mGlWanted) { - checkEglErrors(); - // we lost the gl context, so recreate it. - if (mGlWanted && !mUseGL) { - initializeGL(); - if (mGlCanvas != null) { - mGlCanvas.setViewport(mWidth, mHeight); - } - } - } - } - - InputMethodManager imm = InputMethodManager.peekInstance(); - if (mView != null) { - if (hasWindowFocus && imm != null) { - imm.startGettingWindowFocus(); - } - mView.dispatchWindowFocusChanged(hasWindowFocus); - } - - // Note: must be done after the focus change callbacks, - // so all of the view state is set up correctly. - if (hasWindowFocus) { - if (imm != null) { - imm.onWindowFocus(mView, mView.findFocus(), - mWindowAttributes.softInputMode, - !mHasHadWindowFocus, mWindowAttributes.flags); - } - // Clear the forward bit. We can just do this directly, since - // the window manager doesn't care about it. - mWindowAttributes.softInputMode &= - ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION; - ((WindowManager.LayoutParams)mView.getLayoutParams()) - .softInputMode &= - ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION; - mHasHadWindowFocus = true; - } - } - } break; - case DIE: - dispatchDetachedFromWindow(); - break; - case DISPATCH_KEY_FROM_IME: - if (LOCAL_LOGV) Log.v( - "ViewRoot", "Dispatching key " - + msg.obj + " from IME to " + mView); - deliverKeyEventToViewHierarchy((KeyEvent)msg.obj, false); - break; - case FINISH_INPUT_CONNECTION: { - InputMethodManager imm = InputMethodManager.peekInstance(); - if (imm != null) { - imm.reportFinishInputConnection((InputConnection)msg.obj); - } - } break; - case CHECK_FOCUS: { - InputMethodManager imm = InputMethodManager.peekInstance(); - if (imm != null) { - imm.checkFocus((View)msg.obj); - } - } break; - } - } - - /** - * Something in the current window tells us we need to change the touch mode. For - * example, we are not in touch mode, and the user touches the screen. - * - * If the touch mode has changed, tell the window manager, and handle it locally. - * - * @param inTouchMode Whether we want to be in touch mode. - * @return True if the touch mode changed and focus changed was changed as a result - */ - boolean ensureTouchMode(boolean inTouchMode) { - if (DBG) Log.d("touchmode", "ensureTouchMode(" + inTouchMode + "), current " - + "touch mode is " + mAttachInfo.mInTouchMode); - if (mAttachInfo.mInTouchMode == inTouchMode) return false; - - // tell the window manager - try { - sWindowSession.setInTouchMode(inTouchMode); - } catch (RemoteException e) { - throw new RuntimeException(e); - } - - // handle the change - return ensureTouchModeLocally(inTouchMode); - } - - /** - * Ensure that the touch mode for this window is set, and if it is changing, - * take the appropriate action. - * @param inTouchMode Whether we want to be in touch mode. - * @return True if the touch mode changed and focus changed was changed as a result - */ - private boolean ensureTouchModeLocally(boolean inTouchMode) { - if (DBG) Log.d("touchmode", "ensureTouchModeLocally(" + inTouchMode + "), current " - + "touch mode is " + mAttachInfo.mInTouchMode); - - if (mAttachInfo.mInTouchMode == inTouchMode) return false; - - mAttachInfo.mInTouchMode = inTouchMode; - mAttachInfo.mTreeObserver.dispatchOnTouchModeChanged(inTouchMode); - - return (inTouchMode) ? enterTouchMode() : leaveTouchMode(); - } - - private boolean enterTouchMode() { - if (mView != null) { - if (mView.hasFocus()) { - // note: not relying on mFocusedView here because this could - // be when the window is first being added, and mFocused isn't - // set yet. - final View focused = mView.findFocus(); - if (focused != null && !focused.isFocusableInTouchMode()) { - - final ViewGroup ancestorToTakeFocus = - findAncestorToTakeFocusInTouchMode(focused); - if (ancestorToTakeFocus != null) { - // there is an ancestor that wants focus after its descendants that - // is focusable in touch mode.. give it focus - return ancestorToTakeFocus.requestFocus(); - } else { - // nothing appropriate to have focus in touch mode, clear it out - mView.unFocus(); - mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(focused, null); - mFocusedView = null; - return true; - } - } - } - } - return false; - } - - - /** - * Find an ancestor of focused that wants focus after its descendants and is - * focusable in touch mode. - * @param focused The currently focused view. - * @return An appropriate view, or null if no such view exists. - */ - private ViewGroup findAncestorToTakeFocusInTouchMode(View focused) { - ViewParent parent = focused.getParent(); - while (parent instanceof ViewGroup) { - final ViewGroup vgParent = (ViewGroup) parent; - if (vgParent.getDescendantFocusability() == ViewGroup.FOCUS_AFTER_DESCENDANTS - && vgParent.isFocusableInTouchMode()) { - return vgParent; - } - if (vgParent.isRootNamespace()) { - return null; - } else { - parent = vgParent.getParent(); - } - } - return null; - } - - private boolean leaveTouchMode() { - if (mView != null) { - if (mView.hasFocus()) { - // i learned the hard way to not trust mFocusedView :) - mFocusedView = mView.findFocus(); - if (!(mFocusedView instanceof ViewGroup)) { - // some view has focus, let it keep it - return false; - } else if (((ViewGroup)mFocusedView).getDescendantFocusability() != - ViewGroup.FOCUS_AFTER_DESCENDANTS) { - // some view group has focus, and doesn't prefer its children - // over itself for focus, so let them keep it. - return false; - } - } - - // find the best view to give focus to in this brave new non-touch-mode - // world - final View focused = focusSearch(null, View.FOCUS_DOWN); - if (focused != null) { - return focused.requestFocus(View.FOCUS_DOWN); - } - } - return false; - } - - - private void deliverTrackballEvent(MotionEvent event) { - boolean didFinish; - if (event == null) { - try { - event = sWindowSession.getPendingTrackballMove(mWindow); - } catch (RemoteException e) { - } - didFinish = true; - } else { - didFinish = false; - } - - if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event); - - boolean handled = false; - try { - if (event == null) { - handled = true; - } else if (mView != null && mAdded) { - handled = mView.dispatchTrackballEvent(event); - if (!handled) { - // we could do something here, like changing the focus - // or something? - } - } - } finally { - if (handled) { - if (!didFinish) { - try { - sWindowSession.finishKey(mWindow); - } catch (RemoteException e) { - } - } - if (event != null) { - event.recycle(); - } - // If we reach this, we delivered a trackball event to mView and - // mView consumed it. Because we will not translate the trackball - // event into a key event, touch mode will not exit, so we exit - // touch mode here. - ensureTouchMode(false); - //noinspection ReturnInsideFinallyBlock - return; - } - // Let the exception fall through -- the looper will catch - // it and take care of the bad app for us. - } - - final TrackballAxis x = mTrackballAxisX; - final TrackballAxis y = mTrackballAxisY; - - long curTime = SystemClock.uptimeMillis(); - if ((mLastTrackballTime+MAX_TRACKBALL_DELAY) < curTime) { - // It has been too long since the last movement, - // so restart at the beginning. - x.reset(0); - y.reset(0); - mLastTrackballTime = curTime; - } - - try { - final int action = event.getAction(); - final int metastate = event.getMetaState(); - switch (action) { - case MotionEvent.ACTION_DOWN: - x.reset(2); - y.reset(2); - deliverKeyEvent(new KeyEvent(curTime, curTime, - KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, - 0, metastate), false); - break; - case MotionEvent.ACTION_UP: - x.reset(2); - y.reset(2); - deliverKeyEvent(new KeyEvent(curTime, curTime, - KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, - 0, metastate), false); - break; - } - - if (DEBUG_TRACKBALL) Log.v(TAG, "TB X=" + x.position + " step=" - + x.step + " dir=" + x.dir + " acc=" + x.acceleration - + " move=" + event.getX() - + " / Y=" + y.position + " step=" - + y.step + " dir=" + y.dir + " acc=" + y.acceleration - + " move=" + event.getY()); - final float xOff = x.collect(event.getX(), event.getEventTime(), "X"); - final float yOff = y.collect(event.getY(), event.getEventTime(), "Y"); - - // Generate DPAD events based on the trackball movement. - // We pick the axis that has moved the most as the direction of - // the DPAD. When we generate DPAD events for one axis, then the - // other axis is reset -- we don't want to perform DPAD jumps due - // to slight movements in the trackball when making major movements - // along the other axis. - int keycode = 0; - int movement = 0; - float accel = 1; - if (xOff > yOff) { - movement = x.generate((2/event.getXPrecision())); - if (movement != 0) { - keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_RIGHT - : KeyEvent.KEYCODE_DPAD_LEFT; - accel = x.acceleration; - y.reset(2); - } - } else if (yOff > 0) { - movement = y.generate((2/event.getYPrecision())); - if (movement != 0) { - keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_DOWN - : KeyEvent.KEYCODE_DPAD_UP; - accel = y.acceleration; - x.reset(2); - } - } - - if (keycode != 0) { - if (movement < 0) movement = -movement; - int accelMovement = (int)(movement * accel); - if (DEBUG_TRACKBALL) Log.v(TAG, "Move: movement=" + movement - + " accelMovement=" + accelMovement - + " accel=" + accel); - if (accelMovement > movement) { - if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: " - + keycode); - movement--; - deliverKeyEvent(new KeyEvent(curTime, curTime, - KeyEvent.ACTION_MULTIPLE, keycode, - accelMovement-movement, metastate), false); - } - while (movement > 0) { - if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: " - + keycode); - movement--; - curTime = SystemClock.uptimeMillis(); - deliverKeyEvent(new KeyEvent(curTime, curTime, - KeyEvent.ACTION_DOWN, keycode, 0, event.getMetaState()), false); - deliverKeyEvent(new KeyEvent(curTime, curTime, - KeyEvent.ACTION_UP, keycode, 0, metastate), false); - } - mLastTrackballTime = curTime; - } - } finally { - if (!didFinish) { - try { - sWindowSession.finishKey(mWindow); - } catch (RemoteException e) { - } - if (event != null) { - event.recycle(); - } - } - // Let the exception fall through -- the looper will catch - // it and take care of the bad app for us. - } - } - - /** - * @param keyCode The key code - * @return True if the key is directional. - */ - static boolean isDirectional(int keyCode) { - switch (keyCode) { - case KeyEvent.KEYCODE_DPAD_LEFT: - case KeyEvent.KEYCODE_DPAD_RIGHT: - case KeyEvent.KEYCODE_DPAD_UP: - case KeyEvent.KEYCODE_DPAD_DOWN: - return true; - } - return false; - } - - /** - * Returns true if this key is a keyboard key. - * @param keyEvent The key event. - * @return whether this key is a keyboard key. - */ - private static boolean isKeyboardKey(KeyEvent keyEvent) { - final int convertedKey = keyEvent.getUnicodeChar(); - return convertedKey > 0; - } - - - - /** - * See if the key event means we should leave touch mode (and leave touch - * mode if so). - * @param event The key event. - * @return Whether this key event should be consumed (meaning the act of - * leaving touch mode alone is considered the event). - */ - private boolean checkForLeavingTouchModeAndConsume(KeyEvent event) { - if (event.getAction() != KeyEvent.ACTION_DOWN) { - return false; - } - - // only relevant if we are in touch mode - if (!mAttachInfo.mInTouchMode) { - return false; - } - - // if something like an edit text has focus and the user is typing, - // leave touch mode - // - // note: the condition of not being a keyboard key is kind of a hacky - // approximation of whether we think the focused view will want the - // key; if we knew for sure whether the focused view would consume - // the event, that would be better. - if (isKeyboardKey(event) && mView != null && mView.hasFocus()) { - mFocusedView = mView.findFocus(); - if ((mFocusedView instanceof ViewGroup) - && ((ViewGroup) mFocusedView).getDescendantFocusability() == - ViewGroup.FOCUS_AFTER_DESCENDANTS) { - // something has focus, but is holding it weakly as a container - return false; - } - if (ensureTouchMode(false)) { - throw new IllegalStateException("should not have changed focus " - + "when leaving touch mode while a view has focus."); - } - return false; - } - - if (isDirectional(event.getKeyCode())) { - // no view has focus, so we leave touch mode (and find something - // to give focus to). the event is consumed if we were able to - // find something to give focus to. - return ensureTouchMode(false); - } - return false; - } - - /** - * log motion events - */ - private static void captureMotionLog(String subTag, MotionEvent ev) { - //check dynamic switch - if (ev == null || - SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_EVENT, 0) == 0) { - return; - } - - StringBuilder sb = new StringBuilder(subTag + ": "); - sb.append(ev.getDownTime()).append(','); - sb.append(ev.getEventTime()).append(','); - sb.append(ev.getAction()).append(','); - sb.append(ev.getX()).append(','); - sb.append(ev.getY()).append(','); - sb.append(ev.getPressure()).append(','); - sb.append(ev.getSize()).append(','); - sb.append(ev.getMetaState()).append(','); - sb.append(ev.getXPrecision()).append(','); - sb.append(ev.getYPrecision()).append(','); - sb.append(ev.getDeviceId()).append(','); - sb.append(ev.getEdgeFlags()); - Log.d(TAG, sb.toString()); - } - /** - * log motion events - */ - private static void captureKeyLog(String subTag, KeyEvent ev) { - //check dynamic switch - if (ev == null || - SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_EVENT, 0) == 0) { - return; - } - StringBuilder sb = new StringBuilder(subTag + ": "); - sb.append(ev.getDownTime()).append(','); - sb.append(ev.getEventTime()).append(','); - sb.append(ev.getAction()).append(','); - sb.append(ev.getKeyCode()).append(','); - sb.append(ev.getRepeatCount()).append(','); - sb.append(ev.getMetaState()).append(','); - sb.append(ev.getDeviceId()).append(','); - sb.append(ev.getScanCode()); - Log.d(TAG, sb.toString()); - } - - int enqueuePendingEvent(Object event, boolean sendDone) { - int seq = mPendingEventSeq+1; - if (seq < 0) seq = 0; - mPendingEventSeq = seq; - mPendingEvents.put(seq, event); - return sendDone ? seq : -seq; - } - - Object retrievePendingEvent(int seq) { - if (seq < 0) seq = -seq; - Object event = mPendingEvents.get(seq); - if (event != null) { - mPendingEvents.remove(seq); - } - return event; - } - - private void deliverKeyEvent(KeyEvent event, boolean sendDone) { - // If mView is null, we just consume the key event because it doesn't - // make sense to do anything else with it. - boolean handled = mView != null - ? mView.dispatchKeyEventPreIme(event) : true; - if (handled) { - if (sendDone) { - if (LOCAL_LOGV) Log.v( - "ViewRoot", "Telling window manager key is finished"); - try { - sWindowSession.finishKey(mWindow); - } catch (RemoteException e) { - } - } - return; - } - // If it is possible for this window to interact with the input - // method window, then we want to first dispatch our key events - // to the input method. - if (WindowManager.LayoutParams.mayUseInputMethod( - mWindowAttributes.flags)) { - InputMethodManager imm = InputMethodManager.peekInstance(); - if (imm != null && mView != null) { - int seq = enqueuePendingEvent(event, sendDone); - if (DEBUG_IMF) Log.v(TAG, "Sending key event to IME: seq=" - + seq + " event=" + event); - imm.dispatchKeyEvent(mView.getContext(), seq, event, - mInputMethodCallback); - return; - } - } - deliverKeyEventToViewHierarchy(event, sendDone); - } - - void handleFinishedEvent(int seq, boolean handled) { - final KeyEvent event = (KeyEvent)retrievePendingEvent(seq); - if (DEBUG_IMF) Log.v(TAG, "IME finished event: seq=" + seq - + " handled=" + handled + " event=" + event); - if (event != null) { - final boolean sendDone = seq >= 0; - if (!handled) { - deliverKeyEventToViewHierarchy(event, sendDone); - return; - } else if (sendDone) { - if (LOCAL_LOGV) Log.v( - "ViewRoot", "Telling window manager key is finished"); - try { - sWindowSession.finishKey(mWindow); - } catch (RemoteException e) { - } - } - } - } - - private void deliverKeyEventToViewHierarchy(KeyEvent event, boolean sendDone) { - try { - if (mView != null && mAdded) { - final int action = event.getAction(); - boolean isDown = (action == KeyEvent.ACTION_DOWN); - - if (checkForLeavingTouchModeAndConsume(event)) { - return; - } - - if (Config.LOGV) { - captureKeyLog("captureDispatchKeyEvent", event); - } - boolean keyHandled = mView.dispatchKeyEvent(event); - - if (!keyHandled && isDown) { - int direction = 0; - switch (event.getKeyCode()) { - case KeyEvent.KEYCODE_DPAD_LEFT: - direction = View.FOCUS_LEFT; - break; - case KeyEvent.KEYCODE_DPAD_RIGHT: - direction = View.FOCUS_RIGHT; - break; - case KeyEvent.KEYCODE_DPAD_UP: - direction = View.FOCUS_UP; - break; - case KeyEvent.KEYCODE_DPAD_DOWN: - direction = View.FOCUS_DOWN; - break; - } - - if (direction != 0) { - - View focused = mView != null ? mView.findFocus() : null; - if (focused != null) { - View v = focused.focusSearch(direction); - boolean focusPassed = false; - if (v != null && v != focused) { - // do the math the get the interesting rect - // of previous focused into the coord system of - // newly focused view - focused.getFocusedRect(mTempRect); - ((ViewGroup) mView).offsetDescendantRectToMyCoords(focused, mTempRect); - ((ViewGroup) mView).offsetRectIntoDescendantCoords(v, mTempRect); - focusPassed = v.requestFocus(direction, mTempRect); - } - - if (!focusPassed) { - mView.dispatchUnhandledMove(focused, direction); - } else { - playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); - } - } - } - } - } - - } finally { - if (sendDone) { - if (LOCAL_LOGV) Log.v( - "ViewRoot", "Telling window manager key is finished"); - try { - sWindowSession.finishKey(mWindow); - } catch (RemoteException e) { - } - } - // Let the exception fall through -- the looper will catch - // it and take care of the bad app for us. - } - } - - private AudioManager getAudioManager() { - if (mView == null) { - throw new IllegalStateException("getAudioManager called when there is no mView"); - } - if (mAudioManager == null) { - mAudioManager = (AudioManager) mView.getContext().getSystemService(Context.AUDIO_SERVICE); - } - return mAudioManager; - } - - /** - * {@inheritDoc} - */ - public void playSoundEffect(int effectId) { - checkThread(); - - final AudioManager audioManager = getAudioManager(); - - switch (effectId) { - case SoundEffectConstants.CLICK: - audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK); - return; - case SoundEffectConstants.NAVIGATION_DOWN: - audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN); - return; - case SoundEffectConstants.NAVIGATION_LEFT: - audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT); - return; - case SoundEffectConstants.NAVIGATION_RIGHT: - audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT); - return; - case SoundEffectConstants.NAVIGATION_UP: - audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP); - return; - default: - throw new IllegalArgumentException("unknown effect id " + effectId + - " not defined in " + SoundEffectConstants.class.getCanonicalName()); - } - } - - /** - * {@inheritDoc} - */ - public boolean performHapticFeedback(int effectId, boolean always) { - try { - return sWindowSession.performHapticFeedback(mWindow, effectId, always); - } catch (RemoteException e) { - return false; - } - } - - /** - * {@inheritDoc} - */ - public View focusSearch(View focused, int direction) { - checkThread(); - if (!(mView instanceof ViewGroup)) { - return null; - } - return FocusFinder.getInstance().findNextFocus((ViewGroup) mView, focused, direction); - } - - public void debug() { - mView.debug(); - } - - public void die(boolean immediate) { - checkThread(); - if (Config.LOGV) Log.v("ViewRoot", "DIE in " + this + " of " + mSurface); - synchronized (this) { - if (mAdded && !mFirst) { - int viewVisibility = mView.getVisibility(); - boolean viewVisibilityChanged = mViewVisibility != viewVisibility; - if (mWindowAttributesChanged || viewVisibilityChanged) { - // If layout params have been changed, first give them - // to the window manager to make sure it has the correct - // animation info. - try { - if ((sWindowSession.relayout( - mWindow, mWindowAttributes, - mView.mMeasuredWidth, mView.mMeasuredHeight, - viewVisibility, false, mWinFrame, mPendingContentInsets, - mPendingVisibleInsets, mSurface) - &WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) { - sWindowSession.finishDrawing(mWindow); - } - } catch (RemoteException e) { - } - } - - mSurface = null; - } - if (mAdded) { - mAdded = false; - if (immediate) { - dispatchDetachedFromWindow(); - } else if (mView != null) { - sendEmptyMessage(DIE); - } - } - } - } - - public void dispatchFinishedEvent(int seq, boolean handled) { - Message msg = obtainMessage(FINISHED_EVENT); - msg.arg1 = seq; - msg.arg2 = handled ? 1 : 0; - sendMessage(msg); - } - - public void dispatchResized(int w, int h, Rect coveredInsets, - Rect visibleInsets, boolean reportDraw) { - if (DEBUG_LAYOUT) Log.v(TAG, "Resizing " + this + ": w=" + w - + " h=" + h + " coveredInsets=" + coveredInsets.toShortString() - + " visibleInsets=" + visibleInsets.toShortString() - + " reportDraw=" + reportDraw); - Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED); - msg.arg1 = w; - msg.arg2 = h; - msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) }; - sendMessage(msg); - } - - public void dispatchKey(KeyEvent event) { - if (event.getAction() == KeyEvent.ACTION_DOWN) { - //noinspection ConstantConditions - if (false && event.getKeyCode() == KeyEvent.KEYCODE_CAMERA) { - if (Config.LOGD) Log.d("keydisp", - "==================================================="); - if (Config.LOGD) Log.d("keydisp", "Focused view Hierarchy is:"); - debug(); - - if (Config.LOGD) Log.d("keydisp", - "==================================================="); - } - } - - Message msg = obtainMessage(DISPATCH_KEY); - msg.obj = event; - - if (LOCAL_LOGV) Log.v( - "ViewRoot", "sending key " + event + " to " + mView); - - sendMessageAtTime(msg, event.getEventTime()); - } - - public void dispatchPointer(MotionEvent event, long eventTime) { - Message msg = obtainMessage(DISPATCH_POINTER); - msg.obj = event; - sendMessageAtTime(msg, eventTime); - } - - public void dispatchTrackball(MotionEvent event, long eventTime) { - Message msg = obtainMessage(DISPATCH_TRACKBALL); - msg.obj = event; - sendMessageAtTime(msg, eventTime); - } - - public void dispatchAppVisibility(boolean visible) { - Message msg = obtainMessage(DISPATCH_APP_VISIBILITY); - msg.arg1 = visible ? 1 : 0; - sendMessage(msg); - } - - public void dispatchGetNewSurface() { - Message msg = obtainMessage(DISPATCH_GET_NEW_SURFACE); - sendMessage(msg); - } - - public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) { - Message msg = Message.obtain(); - msg.what = WINDOW_FOCUS_CHANGED; - msg.arg1 = hasFocus ? 1 : 0; - msg.arg2 = inTouchMode ? 1 : 0; - sendMessage(msg); - } - - public boolean showContextMenuForChild(View originalView) { - return false; - } - - public void createContextMenu(ContextMenu menu) { - } - - public void childDrawableStateChanged(View child) { - } - - protected Rect getWindowFrame() { - return mWinFrame; - } - - void checkThread() { - if (mThread != Thread.currentThread()) { - throw new CalledFromWrongThreadException( - "Only the original thread that created a view hierarchy can touch its views."); - } - } - - public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { - // ViewRoot never intercepts touch event, so this can be a no-op - } - - public boolean requestChildRectangleOnScreen(View child, Rect rectangle, - boolean immediate) { - return scrollToRectOrFocus(rectangle, immediate); - } - - static class InputMethodCallback extends IInputMethodCallback.Stub { - private WeakReference<ViewRoot> mViewRoot; - - public InputMethodCallback(ViewRoot viewRoot) { - mViewRoot = new WeakReference<ViewRoot>(viewRoot); - } - - public void finishedEvent(int seq, boolean handled) { - final ViewRoot viewRoot = mViewRoot.get(); - if (viewRoot != null) { - viewRoot.dispatchFinishedEvent(seq, handled); - } - } - - public void sessionCreated(IInputMethodSession session) throws RemoteException { - // Stub -- not for use in the client. - } - } - - static class W extends IWindow.Stub { - private WeakReference<ViewRoot> mViewRoot; - - public W(ViewRoot viewRoot) { - mViewRoot = new WeakReference<ViewRoot>(viewRoot); - } - - public void resized(int w, int h, Rect coveredInsets, - Rect visibleInsets, boolean reportDraw) { - final ViewRoot viewRoot = mViewRoot.get(); - if (viewRoot != null) { - viewRoot.dispatchResized(w, h, coveredInsets, - visibleInsets, reportDraw); - } - } - - public void dispatchKey(KeyEvent event) { - final ViewRoot viewRoot = mViewRoot.get(); - if (viewRoot != null) { - viewRoot.dispatchKey(event); - } - } - - public void dispatchPointer(MotionEvent event, long eventTime) { - final ViewRoot viewRoot = mViewRoot.get(); - if (viewRoot != null) { - viewRoot.dispatchPointer(event, eventTime); - } - } - - public void dispatchTrackball(MotionEvent event, long eventTime) { - final ViewRoot viewRoot = mViewRoot.get(); - if (viewRoot != null) { - viewRoot.dispatchTrackball(event, eventTime); - } - } - - public void dispatchAppVisibility(boolean visible) { - final ViewRoot viewRoot = mViewRoot.get(); - if (viewRoot != null) { - viewRoot.dispatchAppVisibility(visible); - } - } - - public void dispatchGetNewSurface() { - final ViewRoot viewRoot = mViewRoot.get(); - if (viewRoot != null) { - viewRoot.dispatchGetNewSurface(); - } - } - - public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) { - final ViewRoot viewRoot = mViewRoot.get(); - if (viewRoot != null) { - viewRoot.windowFocusChanged(hasFocus, inTouchMode); - } - } - - private static int checkCallingPermission(String permission) { - if (!Process.supportsProcesses()) { - return PackageManager.PERMISSION_GRANTED; - } - - try { - return ActivityManagerNative.getDefault().checkPermission( - permission, Binder.getCallingPid(), Binder.getCallingUid()); - } catch (RemoteException e) { - return PackageManager.PERMISSION_DENIED; - } - } - - public void executeCommand(String command, String parameters, ParcelFileDescriptor out) { - final ViewRoot viewRoot = mViewRoot.get(); - if (viewRoot != null) { - final View view = viewRoot.mView; - if (view != null) { - if (checkCallingPermission(Manifest.permission.DUMP) != - PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Insufficient permissions to invoke" - + " executeCommand() from pid=" + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - } - - OutputStream clientStream = null; - try { - clientStream = new ParcelFileDescriptor.AutoCloseOutputStream(out); - ViewDebug.dispatchCommand(view, command, parameters, clientStream); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (clientStream != null) { - try { - clientStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - } - } - } - - /** - * Maintains state information for a single trackball axis, generating - * discrete (DPAD) movements based on raw trackball motion. - */ - static final class TrackballAxis { - /** - * The maximum amount of acceleration we will apply. - */ - static final float MAX_ACCELERATION = 20; - - /** - * The maximum amount of time (in milliseconds) between events in order - * for us to consider the user to be doing fast trackball movements, - * and thus apply an acceleration. - */ - static final long FAST_MOVE_TIME = 150; - - /** - * Scaling factor to the time (in milliseconds) between events to how - * much to multiple/divide the current acceleration. When movement - * is < FAST_MOVE_TIME this multiplies the acceleration; when > - * FAST_MOVE_TIME it divides it. - */ - static final float ACCEL_MOVE_SCALING_FACTOR = (1.0f/40); - - float position; - float absPosition; - float acceleration = 1; - long lastMoveTime = 0; - int step; - int dir; - int nonAccelMovement; - - void reset(int _step) { - position = 0; - acceleration = 1; - lastMoveTime = 0; - step = _step; - dir = 0; - } - - /** - * Add trackball movement into the state. If the direction of movement - * has been reversed, the state is reset before adding the - * movement (so that you don't have to compensate for any previously - * collected movement before see the result of the movement in the - * new direction). - * - * @return Returns the absolute value of the amount of movement - * collected so far. - */ - float collect(float off, long time, String axis) { - long normTime; - if (off > 0) { - normTime = (long)(off * FAST_MOVE_TIME); - if (dir < 0) { - if (DEBUG_TRACKBALL) Log.v(TAG, axis + " reversed to positive!"); - position = 0; - step = 0; - acceleration = 1; - lastMoveTime = 0; - } - dir = 1; - } else if (off < 0) { - normTime = (long)((-off) * FAST_MOVE_TIME); - if (dir > 0) { - if (DEBUG_TRACKBALL) Log.v(TAG, axis + " reversed to negative!"); - position = 0; - step = 0; - acceleration = 1; - lastMoveTime = 0; - } - dir = -1; - } else { - normTime = 0; - } - - // The number of milliseconds between each movement that is - // considered "normal" and will not result in any acceleration - // or deceleration, scaled by the offset we have here. - if (normTime > 0) { - long delta = time - lastMoveTime; - lastMoveTime = time; - float acc = acceleration; - if (delta < normTime) { - // The user is scrolling rapidly, so increase acceleration. - float scale = (normTime-delta) * ACCEL_MOVE_SCALING_FACTOR; - if (scale > 1) acc *= scale; - if (DEBUG_TRACKBALL) Log.v(TAG, axis + " accelerate: off=" - + off + " normTime=" + normTime + " delta=" + delta - + " scale=" + scale + " acc=" + acc); - acceleration = acc < MAX_ACCELERATION ? acc : MAX_ACCELERATION; - } else { - // The user is scrolling slowly, so decrease acceleration. - float scale = (delta-normTime) * ACCEL_MOVE_SCALING_FACTOR; - if (scale > 1) acc /= scale; - if (DEBUG_TRACKBALL) Log.v(TAG, axis + " deccelerate: off=" - + off + " normTime=" + normTime + " delta=" + delta - + " scale=" + scale + " acc=" + acc); - acceleration = acc > 1 ? acc : 1; - } - } - position += off; - return (absPosition = Math.abs(position)); - } - - /** - * Generate the number of discrete movement events appropriate for - * the currently collected trackball movement. - * - * @param precision The minimum movement required to generate the - * first discrete movement. - * - * @return Returns the number of discrete movements, either positive - * or negative, or 0 if there is not enough trackball movement yet - * for a discrete movement. - */ - int generate(float precision) { - int movement = 0; - nonAccelMovement = 0; - do { - final int dir = position >= 0 ? 1 : -1; - switch (step) { - // If we are going to execute the first step, then we want - // to do this as soon as possible instead of waiting for - // a full movement, in order to make things look responsive. - case 0: - if (absPosition < precision) { - return movement; - } - movement += dir; - nonAccelMovement += dir; - step = 1; - break; - // If we have generated the first movement, then we need - // to wait for the second complete trackball motion before - // generating the second discrete movement. - case 1: - if (absPosition < 2) { - return movement; - } - movement += dir; - nonAccelMovement += dir; - position += dir > 0 ? -2 : 2; - absPosition = Math.abs(position); - step = 2; - break; - // After the first two, we generate discrete movements - // consistently with the trackball, applying an acceleration - // if the trackball is moving quickly. This is a simple - // acceleration on top of what we already compute based - // on how quickly the wheel is being turned, to apply - // a longer increasing acceleration to continuous movement - // in one direction. - default: - if (absPosition < 1) { - return movement; - } - movement += dir; - position += dir >= 0 ? -1 : 1; - absPosition = Math.abs(position); - float acc = acceleration; - acc *= 1.1f; - acceleration = acc < MAX_ACCELERATION ? acc : acceleration; - break; - } - } while (true); - } - } - - public static final class CalledFromWrongThreadException extends AndroidRuntimeException { - public CalledFromWrongThreadException(String msg) { - super(msg); - } - } - - private SurfaceHolder mHolder = new SurfaceHolder() { - // we only need a SurfaceHolder for opengl. it would be nice - // to implement everything else though, especially the callback - // support (opengl doesn't make use of it right now, but eventually - // will). - public Surface getSurface() { - return mSurface; - } - - public boolean isCreating() { - return false; - } - - public void addCallback(Callback callback) { - } - - public void removeCallback(Callback callback) { - } - - public void setFixedSize(int width, int height) { - } - - public void setSizeFromLayout() { - } - - public void setFormat(int format) { - } - - public void setType(int type) { - } - - public void setKeepScreenOn(boolean screenOn) { - } - - public Canvas lockCanvas() { - return null; - } - - public Canvas lockCanvas(Rect dirty) { - return null; - } - - public void unlockCanvasAndPost(Canvas canvas) { - } - public Rect getSurfaceFrame() { - return null; - } - }; - - static RunQueue getRunQueue() { - RunQueue rq = sRunQueues.get(); - if (rq != null) { - return rq; - } - rq = new RunQueue(); - sRunQueues.set(rq); - return rq; - } - - /** - * @hide - */ - static final class RunQueue { - private final ArrayList<HandlerAction> mActions = new ArrayList<HandlerAction>(); - - void post(Runnable action) { - postDelayed(action, 0); - } - - void postDelayed(Runnable action, long delayMillis) { - HandlerAction handlerAction = new HandlerAction(); - handlerAction.action = action; - handlerAction.delay = delayMillis; - - synchronized (mActions) { - mActions.add(handlerAction); - } - } - - void removeCallbacks(Runnable action) { - final HandlerAction handlerAction = new HandlerAction(); - handlerAction.action = action; - - synchronized (mActions) { - final ArrayList<HandlerAction> actions = mActions; - - while (actions.remove(handlerAction)) { - // Keep going - } - } - } - - void executeActions(Handler handler) { - synchronized (mActions) { - final ArrayList<HandlerAction> actions = mActions; - final int count = actions.size(); - - for (int i = 0; i < count; i++) { - final HandlerAction handlerAction = actions.get(i); - handler.postDelayed(handlerAction.action, handlerAction.delay); - } - - mActions.clear(); - } - } - - private static class HandlerAction { - Runnable action; - long delay; - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - HandlerAction that = (HandlerAction) o; - - return !(action != null ? !action.equals(that.action) : that.action != null); - - } - - @Override - public int hashCode() { - int result = action != null ? action.hashCode() : 0; - result = 31 * result + (int) (delay ^ (delay >>> 32)); - return result; - } - } - } - - private static native void nativeShowFPS(Canvas canvas, int durationMillis); - - // inform skia to just abandon its texture cache IDs - // doesn't call glDeleteTextures - private static native void nativeAbandonGlCaches(); -} diff --git a/core/java/android/view/ViewStub.java b/core/java/android/view/ViewStub.java deleted file mode 100644 index e159de4..0000000 --- a/core/java/android/view/ViewStub.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2008 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.view; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.util.AttributeSet; - -import com.android.internal.R; - -/** - * A ViewStub is an invisible, zero-sized View that can be used to lazily inflate - * layout resources at runtime. - * - * When a ViewStub is made visible, or when {@link #inflate()} is invoked, the layout resource - * is inflated. The ViewStub then replaces itself in its parent with the inflated View or Views. - * Therefore, the ViewStub exists in the view hierarchy until {@link #setVisibility(int)} or - * {@link #inflate()} is invoked. - * - * The inflated View is added to the ViewStub's parent with the ViewStub's layout - * parameters. Similarly, you can define/override the inflate View's id by using the - * ViewStub's inflatedId property. For instance: - * - * <pre> - * <ViewStub android:id="@+id/stub" - * android:inflatedId="@+id/subTree" - * android:layout="@layout/mySubTree" - * android:layout_width="120dip" - * android:layout_height="40dip" /> - * </pre> - * - * The ViewStub thus defined can be found using the id "stub." After inflation of - * the layout resource "mySubTree," the ViewStub is removed from its parent. The - * View created by inflating the layout resource "mySubTree" can be found using the - * id "subTree," specified by the inflatedId property. The inflated View is finally - * assigned a width of 120dip and a height of 40dip. - * - * The preferred way to perform the inflation of the layout resource is the following: - * - * <pre> - * ViewStub stub = (ViewStub) findViewById(R.id.stub); - * View inflated = stub.inflate(); - * </pre> - * - * When {@link #inflate()} is invoked, the ViewStub is replaced by the inflated View - * and the inflated View is returned. This lets applications get a reference to the - * inflated View without executing an extra findViewById(). - * - * @attr ref android.R.styleable#ViewStub_inflatedId - * @attr ref android.R.styleable#ViewStub_layout - */ -public final class ViewStub extends View { - private int mLayoutResource = 0; - private int mInflatedId; - - private OnInflateListener mInflateListener; - - public ViewStub(Context context) { - initialize(context); - } - - /** - * Creates a new ViewStub with the specified layout resource. - * - * @param context The application's environment. - * @param layoutResource The reference to a layout resource that will be inflated. - */ - public ViewStub(Context context, int layoutResource) { - mLayoutResource = layoutResource; - initialize(context); - } - - public ViewStub(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public ViewStub(Context context, AttributeSet attrs, int defStyle) { - TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ViewStub, - defStyle, 0); - - mInflatedId = a.getResourceId(R.styleable.ViewStub_inflatedId, NO_ID); - mLayoutResource = a.getResourceId(R.styleable.ViewStub_layout, 0); - - a.recycle(); - - a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View, defStyle, 0); - mID = a.getResourceId(R.styleable.View_id, NO_ID); - a.recycle(); - - initialize(context); - } - - private void initialize(Context context) { - mContext = context; - setVisibility(GONE); - setWillNotDraw(true); - } - - /** - * Returns the id taken by the inflated view. If the inflated id is - * {@link View#NO_ID}, the inflated view keeps its original id. - * - * @return A positive integer used to identify the inflated view or - * {@link #NO_ID} if the inflated view should keep its id. - * - * @see #setInflatedId(int) - * @attr ref android.R.styleable#ViewStub_inflatedId - */ - public int getInflatedId() { - return mInflatedId; - } - - /** - * Defines the id taken by the inflated view. If the inflated id is - * {@link View#NO_ID}, the inflated view keeps its original id. - * - * @param inflatedId A positive integer used to identify the inflated view or - * {@link #NO_ID} if the inflated view should keep its id. - * - * @see #getInflatedId() - * @attr ref android.R.styleable#ViewStub_inflatedId - */ - public void setInflatedId(int inflatedId) { - mInflatedId = inflatedId; - } - - /** - * Returns the layout resource that will be used by {@link #setVisibility(int)} or - * {@link #inflate()} to replace this StubbedView - * in its parent by another view. - * - * @return The layout resource identifier used to inflate the new View. - * - * @see #setLayoutResource(int) - * @see #setVisibility(int) - * @see #inflate() - * @attr ref android.R.styleable#ViewStub_layout - */ - public int getLayoutResource() { - return mLayoutResource; - } - - /** - * Specifies the layout resource to inflate when this StubbedView becomes visible or invisible - * or when {@link #inflate()} is invoked. The View created by inflating the layout resource is - * used to replace this StubbedView in its parent. - * - * @param layoutResource A valid layout resource identifier (different from 0.) - * - * @see #getLayoutResource() - * @see #setVisibility(int) - * @see #inflate() - * @attr ref android.R.styleable#ViewStub_layout - */ - public void setLayoutResource(int layoutResource) { - mLayoutResource = layoutResource; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(0, 0); - } - - @Override - public void draw(Canvas canvas) { - } - - @Override - protected void dispatchDraw(Canvas canvas) { - } - - /** - * When visibility is set to {@link #VISIBLE} or {@link #INVISIBLE}, - * {@link #inflate()} is invoked and this StubbedView is replaced in its parent - * by the inflated layout resource. - * - * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. - * - * @see #inflate() - */ - @Override - public void setVisibility(int visibility) { - super.setVisibility(visibility); - - if (visibility == VISIBLE || visibility == INVISIBLE) { - inflate(); - } - } - - /** - * Inflates the layout resource identified by {@link #getLayoutResource()} - * and replaces this StubbedView in its parent by the inflated layout resource. - * - * @return The inflated layout resource. - * - */ - public View inflate() { - final ViewParent viewParent = getParent(); - - if (viewParent != null && viewParent instanceof ViewGroup) { - if (mLayoutResource != 0) { - final ViewGroup parent = (ViewGroup) viewParent; - final LayoutInflater factory = LayoutInflater.from(mContext); - final View view = factory.inflate(mLayoutResource, parent, - false); - - if (mInflatedId != NO_ID) { - view.setId(mInflatedId); - } - - final int index = parent.indexOfChild(this); - parent.removeViewInLayout(this); - - final ViewGroup.LayoutParams layoutParams = getLayoutParams(); - if (layoutParams != null) { - parent.addView(view, index, layoutParams); - } else { - parent.addView(view, index); - } - - if (mInflateListener != null) { - mInflateListener.onInflate(this, view); - } - - return view; - } else { - throw new IllegalArgumentException("ViewStub must have a valid layoutResource"); - } - } else { - throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent"); - } - } - - /** - * Specifies the inflate listener to be notified after this ViewStub successfully - * inflated its layout resource. - * - * @param inflateListener The OnInflateListener to notify of successful inflation. - * - * @see android.view.ViewStub.OnInflateListener - */ - public void setOnInflateListener(OnInflateListener inflateListener) { - mInflateListener = inflateListener; - } - - /** - * Listener used to receive a notification after a ViewStub has successfully - * inflated its layout resource. - * - * @see android.view.ViewStub#setOnInflateListener(android.view.ViewStub.OnInflateListener) - */ - public static interface OnInflateListener { - /** - * Invoked after a ViewStub successfully inflated its layout resource. - * This method is invoked after the inflated view was added to the - * hierarchy but before the layout pass. - * - * @param stub The ViewStub that initiated the inflation. - * @param inflated The inflated View. - */ - void onInflate(ViewStub stub, View inflated); - } -} diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java deleted file mode 100644 index 47b52e4..0000000 --- a/core/java/android/view/ViewTreeObserver.java +++ /dev/null @@ -1,613 +0,0 @@ -/* - * Copyright (C) 2008 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.view; - -import android.graphics.Rect; - -import java.util.ArrayList; - -/** - * A view tree observer is used to register listeners that can be notified of global - * changes in the view tree. Such global events include, but are not limited to, - * layout of the whole tree, beginning of the drawing pass, touch mode change.... - * - * A ViewTreeObserver should never be instantiated by applications as it is provided - * by the views hierarchy. Refer to {@link android.view.View#getViewTreeObserver()} - * for more information. - */ -public final class ViewTreeObserver { - private ArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners; - private ArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners; - private ArrayList<OnPreDrawListener> mOnPreDrawListeners; - private ArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners; - private ArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners; - private ArrayList<OnScrollChangedListener> mOnScrollChangedListeners; - - private boolean mAlive = true; - - /** - * Interface definition for a callback to be invoked when the focus state within - * the view tree changes. - */ - public interface OnGlobalFocusChangeListener { - /** - * Callback method to be invoked when the focus changes in the view tree. When - * the view tree transitions from touch mode to non-touch mode, oldFocus is null. - * When the view tree transitions from non-touch mode to touch mode, newFocus is - * null. When focus changes in non-touch mode (without transition from or to - * touch mode) either oldFocus or newFocus can be null. - * - * @param oldFocus The previously focused view, if any. - * @param newFocus The newly focused View, if any. - */ - public void onGlobalFocusChanged(View oldFocus, View newFocus); - } - - /** - * Interface definition for a callback to be invoked when the global layout state - * or the visibility of views within the view tree changes. - */ - public interface OnGlobalLayoutListener { - /** - * Callback method to be invoked when the global layout state or the visibility of views - * within the view tree changes - */ - public void onGlobalLayout(); - } - - /** - * Interface definition for a callback to be invoked when the view tree is about to be drawn. - */ - public interface OnPreDrawListener { - /** - * Callback method to be invoked when the view tree is about to be drawn. At this point, all - * views in the tree have been measured and given a frame. Clients can use this to adjust - * their scroll bounds or even to request a new layout before drawing occurs. - * - * @return Return true to proceed with the current drawing pass, or false to cancel. - * - * @see android.view.View#onMeasure - * @see android.view.View#onLayout - * @see android.view.View#onDraw - */ - public boolean onPreDraw(); - } - - /** - * Interface definition for a callback to be invoked when the touch mode changes. - */ - public interface OnTouchModeChangeListener { - /** - * Callback method to be invoked when the touch mode changes. - * - * @param isInTouchMode True if the view hierarchy is now in touch mode, false otherwise. - */ - public void onTouchModeChanged(boolean isInTouchMode); - } - - /** - * Interface definition for a callback to be invoked when - * something in the view tree has been scrolled. - * - * @hide pending API council approval - */ - public interface OnScrollChangedListener { - /** - * Callback method to be invoked when something in the view tree - * has been scrolled. - */ - public void onScrollChanged(); - } - - /** - * Parameters used with OnComputeInternalInsetsListener. - * {@hide pending API Council approval} - */ - public final static class InternalInsetsInfo { - /** - * Offsets from the frame of the window at which the content of - * windows behind it should be placed. - */ - public final Rect contentInsets = new Rect(); - - /** - * Offsets from the fram of the window at which windows behind it - * are visible. - */ - public final Rect visibleInsets = new Rect(); - - /** - * Option for {@link #setTouchableInsets(int)}: the entire window frame - * can be touched. - */ - public static final int TOUCHABLE_INSETS_FRAME = 0; - - /** - * Option for {@link #setTouchableInsets(int)}: the area inside of - * the content insets can be touched. - */ - public static final int TOUCHABLE_INSETS_CONTENT = 1; - - /** - * Option for {@link #setTouchableInsets(int)}: the area inside of - * the visible insets can be touched. - */ - public static final int TOUCHABLE_INSETS_VISIBLE = 2; - - /** - * Set which parts of the window can be touched: either - * {@link #TOUCHABLE_INSETS_FRAME}, {@link #TOUCHABLE_INSETS_CONTENT}, - * or {@link #TOUCHABLE_INSETS_VISIBLE}. - */ - public void setTouchableInsets(int val) { - mTouchableInsets = val; - } - - public int getTouchableInsets() { - return mTouchableInsets; - } - - int mTouchableInsets; - - void reset() { - final Rect givenContent = contentInsets; - final Rect givenVisible = visibleInsets; - givenContent.left = givenContent.top = givenContent.right - = givenContent.bottom = givenVisible.left = givenVisible.top - = givenVisible.right = givenVisible.bottom = 0; - mTouchableInsets = TOUCHABLE_INSETS_FRAME; - } - - @Override public boolean equals(Object o) { - try { - if (o == null) { - return false; - } - InternalInsetsInfo other = (InternalInsetsInfo)o; - if (!contentInsets.equals(other.contentInsets)) { - return false; - } - if (!visibleInsets.equals(other.visibleInsets)) { - return false; - } - return mTouchableInsets == other.mTouchableInsets; - } catch (ClassCastException e) { - return false; - } - } - - void set(InternalInsetsInfo other) { - contentInsets.set(other.contentInsets); - visibleInsets.set(other.visibleInsets); - mTouchableInsets = other.mTouchableInsets; - } - } - - /** - * Interface definition for a callback to be invoked when layout has - * completed and the client can compute its interior insets. - * {@hide pending API Council approval} - */ - public interface OnComputeInternalInsetsListener { - /** - * Callback method to be invoked when layout has completed and the - * client can compute its interior insets. - * - * @param inoutInfo Should be filled in by the implementation with - * the information about the insets of the window. This is called - * with whatever values the previous OnComputeInternalInsetsListener - * returned, if there are multiple such listeners in the window. - */ - public void onComputeInternalInsets(InternalInsetsInfo inoutInfo); - } - - /** - * Creates a new ViewTreeObserver. This constructor should not be called - */ - ViewTreeObserver() { - } - - /** - * Merges all the listeners registered on the specified observer with the listeners - * registered on this object. After this method is invoked, the specified observer - * will return false in {@link #isAlive()} and should not be used anymore. - * - * @param observer The ViewTreeObserver whose listeners must be added to this observer - */ - void merge(ViewTreeObserver observer) { - if (observer.mOnGlobalFocusListeners != null) { - if (mOnGlobalFocusListeners != null) { - mOnGlobalFocusListeners.addAll(observer.mOnGlobalFocusListeners); - } else { - mOnGlobalFocusListeners = observer.mOnGlobalFocusListeners; - } - } - - if (observer.mOnGlobalLayoutListeners != null) { - if (mOnGlobalLayoutListeners != null) { - mOnGlobalLayoutListeners.addAll(observer.mOnGlobalLayoutListeners); - } else { - mOnGlobalLayoutListeners = observer.mOnGlobalLayoutListeners; - } - } - - if (observer.mOnPreDrawListeners != null) { - if (mOnPreDrawListeners != null) { - mOnPreDrawListeners.addAll(observer.mOnPreDrawListeners); - } else { - mOnPreDrawListeners = observer.mOnPreDrawListeners; - } - } - - if (observer.mOnTouchModeChangeListeners != null) { - if (mOnTouchModeChangeListeners != null) { - mOnTouchModeChangeListeners.addAll(observer.mOnTouchModeChangeListeners); - } else { - mOnTouchModeChangeListeners = observer.mOnTouchModeChangeListeners; - } - } - - if (observer.mOnComputeInternalInsetsListeners != null) { - if (mOnComputeInternalInsetsListeners != null) { - mOnComputeInternalInsetsListeners.addAll(observer.mOnComputeInternalInsetsListeners); - } else { - mOnComputeInternalInsetsListeners = observer.mOnComputeInternalInsetsListeners; - } - } - - observer.kill(); - } - - /** - * Register a callback to be invoked when the focus state within the view tree changes. - * - * @param listener The callback to add - * - * @throws IllegalStateException If {@link #isAlive()} returns false - */ - public void addOnGlobalFocusChangeListener(OnGlobalFocusChangeListener listener) { - checkIsAlive(); - - if (mOnGlobalFocusListeners == null) { - mOnGlobalFocusListeners = new ArrayList<OnGlobalFocusChangeListener>(); - } - - mOnGlobalFocusListeners.add(listener); - } - - /** - * Remove a previously installed focus change callback. - * - * @param victim The callback to remove - * - * @throws IllegalStateException If {@link #isAlive()} returns false - * - * @see #addOnGlobalFocusChangeListener(OnGlobalFocusChangeListener) - */ - public void removeOnGlobalFocusChangeListener(OnGlobalFocusChangeListener victim) { - checkIsAlive(); - if (mOnGlobalFocusListeners == null) { - return; - } - mOnGlobalFocusListeners.remove(victim); - } - - /** - * Register a callback to be invoked when the global layout state or the visibility of views - * within the view tree changes - * - * @param listener The callback to add - * - * @throws IllegalStateException If {@link #isAlive()} returns false - */ - public void addOnGlobalLayoutListener(OnGlobalLayoutListener listener) { - checkIsAlive(); - - if (mOnGlobalLayoutListeners == null) { - mOnGlobalLayoutListeners = new ArrayList<OnGlobalLayoutListener>(); - } - - mOnGlobalLayoutListeners.add(listener); - } - - /** - * Remove a previously installed global layout callback - * - * @param victim The callback to remove - * - * @throws IllegalStateException If {@link #isAlive()} returns false - * - * @see #addOnGlobalLayoutListener(OnGlobalLayoutListener) - */ - public void removeGlobalOnLayoutListener(OnGlobalLayoutListener victim) { - checkIsAlive(); - if (mOnGlobalLayoutListeners == null) { - return; - } - mOnGlobalLayoutListeners.remove(victim); - } - - /** - * Register a callback to be invoked when the view tree is about to be drawn - * - * @param listener The callback to add - * - * @throws IllegalStateException If {@link #isAlive()} returns false - */ - public void addOnPreDrawListener(OnPreDrawListener listener) { - checkIsAlive(); - - if (mOnPreDrawListeners == null) { - mOnPreDrawListeners = new ArrayList<OnPreDrawListener>(); - } - - mOnPreDrawListeners.add(listener); - } - - /** - * Remove a previously installed pre-draw callback - * - * @param victim The callback to remove - * - * @throws IllegalStateException If {@link #isAlive()} returns false - * - * @see #addOnPreDrawListener(OnPreDrawListener) - */ - public void removeOnPreDrawListener(OnPreDrawListener victim) { - checkIsAlive(); - if (mOnPreDrawListeners == null) { - return; - } - mOnPreDrawListeners.remove(victim); - } - - /** - * Register a callback to be invoked when a view has been scrolled. - * - * @param listener The callback to add - * - * @throws IllegalStateException If {@link #isAlive()} returns false - * - * @hide pending API council approval - */ - public void addOnScrollChangedListener(OnScrollChangedListener listener) { - checkIsAlive(); - - if (mOnScrollChangedListeners == null) { - mOnScrollChangedListeners = new ArrayList<OnScrollChangedListener>(); - } - - mOnScrollChangedListeners.add(listener); - } - - /** - * Remove a previously installed scroll-changed callback - * - * @param victim The callback to remove - * - * @throws IllegalStateException If {@link #isAlive()} returns false - * - * @see #addOnScrollChangedListener(OnScrollChangedListener) - * - * @hide pending API council approval - */ - public void removeOnScrollChangedListener(OnScrollChangedListener victim) { - checkIsAlive(); - if (mOnScrollChangedListeners == null) { - return; - } - mOnScrollChangedListeners.remove(victim); - } - - /** - * Register a callback to be invoked when the invoked when the touch mode changes. - * - * @param listener The callback to add - * - * @throws IllegalStateException If {@link #isAlive()} returns false - */ - public void addOnTouchModeChangeListener(OnTouchModeChangeListener listener) { - checkIsAlive(); - - if (mOnTouchModeChangeListeners == null) { - mOnTouchModeChangeListeners = new ArrayList<OnTouchModeChangeListener>(); - } - - mOnTouchModeChangeListeners.add(listener); - } - - /** - * Remove a previously installed touch mode change callback - * - * @param victim The callback to remove - * - * @throws IllegalStateException If {@link #isAlive()} returns false - * - * @see #addOnTouchModeChangeListener(OnTouchModeChangeListener) - */ - public void removeOnTouchModeChangeListener(OnTouchModeChangeListener victim) { - checkIsAlive(); - if (mOnTouchModeChangeListeners == null) { - return; - } - mOnTouchModeChangeListeners.remove(victim); - } - - /** - * Register a callback to be invoked when the invoked when it is time to - * compute the window's internal insets. - * - * @param listener The callback to add - * - * @throws IllegalStateException If {@link #isAlive()} returns false - * {@hide pending API Council approval} - */ - public void addOnComputeInternalInsetsListener(OnComputeInternalInsetsListener listener) { - checkIsAlive(); - - if (mOnComputeInternalInsetsListeners == null) { - mOnComputeInternalInsetsListeners = new ArrayList<OnComputeInternalInsetsListener>(); - } - - mOnComputeInternalInsetsListeners.add(listener); - } - - /** - * Remove a previously installed internal insets computation callback - * - * @param victim The callback to remove - * - * @throws IllegalStateException If {@link #isAlive()} returns false - * - * @see #addOnComputeInternalInsetsListener(OnComputeInternalInsetsListener) - * {@hide pending API Council approval} - */ - public void removeOnComputeInternalInsetsListener(OnComputeInternalInsetsListener victim) { - checkIsAlive(); - if (mOnComputeInternalInsetsListeners == null) { - return; - } - mOnComputeInternalInsetsListeners.remove(victim); - } - - private void checkIsAlive() { - if (!mAlive) { - throw new IllegalStateException("This ViewTreeObserver is not alive, call " - + "getViewTreeObserver() again"); - } - } - - /** - * Indicates whether this ViewTreeObserver is alive. When an observer is not alive, - * any call to a method (except this one) will throw an exception. - * - * If an application keeps a long-lived reference to this ViewTreeObserver, it should - * always check for the result of this method before calling any other method. - * - * @return True if this object is alive and be used, false otherwise. - */ - public boolean isAlive() { - return mAlive; - } - - /** - * Marks this ViewTreeObserver as not alive. After invoking this method, invoking - * any other method but {@link #isAlive()} and {@link #kill()} will throw an Exception. - * - * @hide - */ - private void kill() { - mAlive = false; - } - - /** - * Notifies registered listeners that focus has changed. - */ - final void dispatchOnGlobalFocusChange(View oldFocus, View newFocus) { - final ArrayList<OnGlobalFocusChangeListener> globaFocusListeners = mOnGlobalFocusListeners; - if (globaFocusListeners != null) { - final int count = globaFocusListeners.size(); - for (int i = count - 1; i >= 0; i--) { - globaFocusListeners.get(i).onGlobalFocusChanged(oldFocus, newFocus); - } - } - } - - /** - * Notifies registered listeners that a global layout happened. This can be called - * manually if you are forcing a layout on a View or a hierarchy of Views that are - * not attached to a Window or in the GONE state. - */ - public final void dispatchOnGlobalLayout() { - final ArrayList<OnGlobalLayoutListener> globaLayoutListeners = mOnGlobalLayoutListeners; - if (globaLayoutListeners != null) { - final int count = globaLayoutListeners.size(); - for (int i = count - 1; i >= 0; i--) { - globaLayoutListeners.get(i).onGlobalLayout(); - } - } - } - - /** - * Notifies registered listeners that the drawing pass is about to start. If a - * listener returns true, then the drawing pass is canceled and rescheduled. This can - * be called manually if you are forcing the drawing on a View or a hierarchy of Views - * that are not attached to a Window or in the GONE state. - * - * @return True if the current draw should be canceled and resceduled, false otherwise. - */ - public final boolean dispatchOnPreDraw() { - boolean cancelDraw = false; - final ArrayList<OnPreDrawListener> preDrawListeners = mOnPreDrawListeners; - if (preDrawListeners != null) { - final int count = preDrawListeners.size(); - for (int i = count - 1; i >= 0; i--) { - cancelDraw |= !preDrawListeners.get(i).onPreDraw(); - } - } - return cancelDraw; - } - - /** - * Notifies registered listeners that the touch mode has changed. - * - * @param inTouchMode True if the touch mode is now enabled, false otherwise. - */ - final void dispatchOnTouchModeChanged(boolean inTouchMode) { - final ArrayList<OnTouchModeChangeListener> touchModeListeners = mOnTouchModeChangeListeners; - if (touchModeListeners != null) { - final int count = touchModeListeners.size(); - for (int i = count - 1; i >= 0; i--) { - touchModeListeners.get(i).onTouchModeChanged(inTouchMode); - } - } - } - - /** - * Notifies registered listeners that something has scrolled. - */ - final void dispatchOnScrollChanged() { - final ArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners; - - if (listeners != null) { - for (OnScrollChangedListener scl : mOnScrollChangedListeners) { - scl.onScrollChanged(); - } - } - } - - /** - * Returns whether there are listeners for computing internal insets. - */ - final boolean hasComputeInternalInsetsListeners() { - final ArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners; - return (listeners != null && listeners.size() > 0); - } - - /** - * Calls all listeners to compute the current insets. - */ - final void dispatchOnComputeInternalInsets(InternalInsetsInfo inoutInfo) { - final ArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners; - if (listeners != null) { - final int count = listeners.size(); - for (int i = count - 1; i >= 0; i--) { - listeners.get(i).onComputeInternalInsets(inoutInfo); - } - } - } -} diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java deleted file mode 100644 index a573983..0000000 --- a/core/java/android/view/VolumePanel.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright (C) 2007 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.view; - -import android.bluetooth.HeadsetBase; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.media.AudioManager; -import android.media.AudioService; -import android.media.AudioSystem; -import android.media.ToneGenerator; -import android.os.Handler; -import android.os.Message; -import android.os.Vibrator; -import android.util.Config; -import android.util.Log; -import android.widget.ImageView; -import android.widget.ProgressBar; -import android.widget.TextView; -import android.widget.Toast; - -/** - * Handle the volume up and down keys. - * - * This code really should be moved elsewhere. - * - * @hide - */ -public class VolumePanel extends Handler -{ - private static final String TAG = "VolumePanel"; - private static boolean LOGD = false || Config.LOGD; - - /** - * The delay before playing a sound. This small period exists so the user - * can press another key (non-volume keys, too) to have it NOT be audible. - * <p> - * PhoneWindow will implement this part. - */ - public static final int PLAY_SOUND_DELAY = 300; - - /** - * The delay before vibrating. This small period exists so if the user is - * moving to silent mode, it will not emit a short vibrate (it normally - * would since vibrate is between normal mode and silent mode using hardware - * keys). - */ - public static final int VIBRATE_DELAY = 300; - - private static final int VIBRATE_DURATION = 300; - private static final int BEEP_DURATION = 150; - private static final int MAX_VOLUME = 100; - private static final int FREE_DELAY = 10000; - - private static final int MSG_VOLUME_CHANGED = 0; - private static final int MSG_FREE_RESOURCES = 1; - private static final int MSG_PLAY_SOUND = 2; - private static final int MSG_STOP_SOUNDS = 3; - private static final int MSG_VIBRATE = 4; - - private static final int RINGTONE_VOLUME_TEXT = com.android.internal.R.string.volume_ringtone; - private static final int MUSIC_VOLUME_TEXT = com.android.internal.R.string.volume_music; - private static final int INCALL_VOLUME_TEXT = com.android.internal.R.string.volume_call; - private static final int ALARM_VOLUME_TEXT = com.android.internal.R.string.volume_alarm; - private static final int UNKNOWN_VOLUME_TEXT = com.android.internal.R.string.volume_unknown; - private static final int NOTIFICATION_VOLUME_TEXT = - com.android.internal.R.string.volume_notification; - private static final int BLUETOOTH_INCALL_VOLUME_TEXT = - com.android.internal.R.string.volume_bluetooth_call; - - protected Context mContext; - private AudioManager mAudioManager; - protected AudioService mAudioService; - - private final Toast mToast; - private final View mView; - private final TextView mMessage; - private final TextView mAdditionalMessage; - private final ImageView mSmallStreamIcon; - private final ImageView mLargeStreamIcon; - private final ProgressBar mLevel; - - // Synchronize when accessing this - private ToneGenerator mToneGenerators[]; - private Vibrator mVibrator; - - public VolumePanel(Context context, AudioService volumeService) { - mContext = context; - mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - mAudioService = volumeService; - mToast = new Toast(context); - - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View view = mView = inflater.inflate(com.android.internal.R.layout.volume_adjust, null); - mMessage = (TextView) view.findViewById(com.android.internal.R.id.message); - mAdditionalMessage = - (TextView) view.findViewById(com.android.internal.R.id.additional_message); - mSmallStreamIcon = (ImageView) view.findViewById(com.android.internal.R.id.other_stream_icon); - mLargeStreamIcon = (ImageView) view.findViewById(com.android.internal.R.id.ringer_stream_icon); - mLevel = (ProgressBar) view.findViewById(com.android.internal.R.id.level); - - mToneGenerators = new ToneGenerator[AudioSystem.getNumStreamTypes()]; - mVibrator = new Vibrator(); - } - - public void postVolumeChanged(int streamType, int flags) { - if (hasMessages(MSG_VOLUME_CHANGED)) return; - removeMessages(MSG_FREE_RESOURCES); - obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget(); - } - - /** - * Override this if you have other work to do when the volume changes (for - * example, vibrating, playing a sound, etc.). Make sure to call through to - * the superclass implementation. - */ - protected void onVolumeChanged(int streamType, int flags) { - - if (LOGD) Log.d(TAG, "onVolumeChanged(streamType: " + streamType + ", flags: " + flags + ")"); - - if ((flags & AudioManager.FLAG_SHOW_UI) != 0) { - onShowVolumeChanged(streamType, flags); - } - - if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0) { - removeMessages(MSG_PLAY_SOUND); - sendMessageDelayed(obtainMessage(MSG_PLAY_SOUND, streamType, flags), PLAY_SOUND_DELAY); - } - - if ((flags & AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE) != 0) { - removeMessages(MSG_PLAY_SOUND); - removeMessages(MSG_VIBRATE); - onStopSounds(); - } - - removeMessages(MSG_FREE_RESOURCES); - sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY); - } - - protected void onShowVolumeChanged(int streamType, int flags) { - int index = mAudioService.getStreamVolume(streamType); - int message = UNKNOWN_VOLUME_TEXT; - int additionalMessage = 0; - - if (LOGD) { - Log.d(TAG, "onShowVolumeChanged(streamType: " + streamType - + ", flags: " + flags + "), index: " + index); - } - - // get max volume for progress bar - int max = mAudioService.getStreamMaxVolume(streamType); - - switch (streamType) { - - case AudioManager.STREAM_RING: { - message = RINGTONE_VOLUME_TEXT; - setRingerIcon(index); - break; - } - - case AudioManager.STREAM_MUSIC: { - message = MUSIC_VOLUME_TEXT; - if (mAudioManager.isBluetoothA2dpOn()) { - additionalMessage = - com.android.internal.R.string.volume_music_hint_playing_through_bluetooth; - setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_ad2p); - } else { - setSmallIcon(index); - } - break; - } - - case AudioManager.STREAM_VOICE_CALL: { - /* - * For in-call voice call volume, there is no inaudible volume. - * Rescale the UI control so the progress bar doesn't go all - * the way to zero and don't show the mute icon. - */ - index++; - max++; - message = INCALL_VOLUME_TEXT; - setSmallIcon(index); - break; - } - - case AudioManager.STREAM_ALARM: { - message = ALARM_VOLUME_TEXT; - setSmallIcon(index); - break; - } - - case AudioManager.STREAM_NOTIFICATION: { - message = NOTIFICATION_VOLUME_TEXT; - setSmallIcon(index); - break; - } - - case AudioManager.STREAM_BLUETOOTH_SCO: { - /* - * For in-call voice call volume, there is no inaudible volume. - * Rescale the UI control so the progress bar doesn't go all - * the way to zero and don't show the mute icon. - */ - index++; - max++; - message = BLUETOOTH_INCALL_VOLUME_TEXT; - setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_in_call); - break; - } - } - - String messageString = Resources.getSystem().getString(message); - if (!mMessage.getText().equals(messageString)) { - mMessage.setText(messageString); - } - - if (additionalMessage == 0) { - mAdditionalMessage.setVisibility(View.GONE); - } else { - mAdditionalMessage.setVisibility(View.VISIBLE); - mAdditionalMessage.setText(Resources.getSystem().getString(additionalMessage)); - } - - if (max != mLevel.getMax()) { - mLevel.setMax(max); - } - mLevel.setProgress(index); - - mToast.setView(mView); - mToast.setDuration(Toast.LENGTH_SHORT); - mToast.setGravity(Gravity.TOP, 0, 0); - mToast.show(); - - // Do a little vibrate if applicable (only when going into vibrate mode) - if ((flags & AudioManager.FLAG_VIBRATE) != 0 && - mAudioService.isStreamAffectedByRingerMode(streamType) && - mAudioService.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE && - mAudioService.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)) { - sendMessageDelayed(obtainMessage(MSG_VIBRATE), VIBRATE_DELAY); - } - - } - - protected void onPlaySound(int streamType, int flags) { - - if (hasMessages(MSG_STOP_SOUNDS)) { - removeMessages(MSG_STOP_SOUNDS); - // Force stop right now - onStopSounds(); - } - - synchronized (this) { - ToneGenerator toneGen = getOrCreateToneGenerator(streamType); - toneGen.startTone(ToneGenerator.TONE_PROP_BEEP); - } - - sendMessageDelayed(obtainMessage(MSG_STOP_SOUNDS), BEEP_DURATION); - } - - protected void onStopSounds() { - - synchronized (this) { - int numStreamTypes = AudioSystem.getNumStreamTypes(); - for (int i = numStreamTypes - 1; i >= 0; i--) { - ToneGenerator toneGen = mToneGenerators[i]; - if (toneGen != null) { - toneGen.stopTone(); - } - } - } - } - - protected void onVibrate() { - - // Make sure we ended up in vibrate ringer mode - if (mAudioService.getRingerMode() != AudioManager.RINGER_MODE_VIBRATE) { - return; - } - - mVibrator.vibrate(VIBRATE_DURATION); - } - - /** - * Lock on this VolumePanel instance as long as you use the returned ToneGenerator. - */ - private ToneGenerator getOrCreateToneGenerator(int streamType) { - synchronized (this) { - if (mToneGenerators[streamType] == null) { - return mToneGenerators[streamType] = new ToneGenerator(streamType, MAX_VOLUME); - } else { - return mToneGenerators[streamType]; - } - } - } - - /** - * Makes the small icon visible, and hides the large icon. - * - * @param index The volume index, where 0 means muted. - */ - private void setSmallIcon(int index) { - mLargeStreamIcon.setVisibility(View.GONE); - mSmallStreamIcon.setVisibility(View.VISIBLE); - - mSmallStreamIcon.setImageResource(index == 0 - ? com.android.internal.R.drawable.ic_volume_off_small - : com.android.internal.R.drawable.ic_volume_small); - } - - /** - * Makes the large image view visible with the given icon. - * - * @param resId The icon to display. - */ - private void setLargeIcon(int resId) { - mSmallStreamIcon.setVisibility(View.GONE); - mLargeStreamIcon.setVisibility(View.VISIBLE); - mLargeStreamIcon.setImageResource(resId); - } - - /** - * Makes the ringer icon visible with an icon that is chosen - * based on the current ringer mode. - * - * @param index - */ - private void setRingerIcon(int index) { - mSmallStreamIcon.setVisibility(View.GONE); - mLargeStreamIcon.setVisibility(View.VISIBLE); - - int ringerMode = mAudioService.getRingerMode(); - int icon; - - if (LOGD) Log.d(TAG, "setRingerIcon(index: " + index+ "), ringerMode: " + ringerMode); - - if (ringerMode == AudioManager.RINGER_MODE_SILENT) { - icon = com.android.internal.R.drawable.ic_volume_off; - } else if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) { - icon = com.android.internal.R.drawable.ic_vibrate; - } else { - icon = com.android.internal.R.drawable.ic_volume; - } - mLargeStreamIcon.setImageResource(icon); - } - - protected void onFreeResources() { - // We'll keep the views, just ditch the cached drawable and hence - // bitmaps - mSmallStreamIcon.setImageDrawable(null); - mLargeStreamIcon.setImageDrawable(null); - - synchronized (this) { - for (int i = mToneGenerators.length - 1; i >= 0; i--) { - if (mToneGenerators[i] != null) { - mToneGenerators[i].release(); - } - mToneGenerators[i] = null; - } - } - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - - case MSG_VOLUME_CHANGED: { - onVolumeChanged(msg.arg1, msg.arg2); - break; - } - - case MSG_FREE_RESOURCES: { - onFreeResources(); - break; - } - - case MSG_STOP_SOUNDS: { - onStopSounds(); - break; - } - - case MSG_PLAY_SOUND: { - onPlaySound(msg.arg1, msg.arg2); - break; - } - - case MSG_VIBRATE: { - onVibrate(); - break; - } - - } - } - -} diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java deleted file mode 100644 index 428de67..0000000 --- a/core/java/android/view/Window.java +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.TypedArray; -import android.graphics.PixelFormat; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Bundle; -import android.os.IBinder; -import android.util.Log; - -/** - * Abstract base class for a top-level window look and behavior policy. An - * instance of this class should be used as the top-level view added to the - * window manager. It provides standard UI policies such as a background, title - * area, default key processing, etc. - * - * <p>The only existing implementation of this abstract class is - * android.policy.PhoneWindow, which you should instantiate when needing a - * Window. Eventually that class will be refactored and a factory method - * added for creating Window instances without knowing about a particular - * implementation. - */ -public abstract class Window { - /** Flag for the "options panel" feature. This is enabled by default. */ - public static final int FEATURE_OPTIONS_PANEL = 0; - /** Flag for the "no title" feature, turning off the title at the top - * of the screen. */ - public static final int FEATURE_NO_TITLE = 1; - /** Flag for the progress indicator feature */ - public static final int FEATURE_PROGRESS = 2; - /** Flag for having an icon on the left side of the title bar */ - public static final int FEATURE_LEFT_ICON = 3; - /** Flag for having an icon on the right side of the title bar */ - public static final int FEATURE_RIGHT_ICON = 4; - /** Flag for indeterminate progress */ - public static final int FEATURE_INDETERMINATE_PROGRESS = 5; - /** Flag for the context menu. This is enabled by default. */ - public static final int FEATURE_CONTEXT_MENU = 6; - /** Flag for custom title. You cannot combine this feature with other title features. */ - public static final int FEATURE_CUSTOM_TITLE = 7; - /* Flag for asking for an OpenGL enabled window. - All 2D graphics will be handled by OpenGL ES. - Private for now, until it is better tested (not shipping in 1.0) - */ - private static final int FEATURE_OPENGL = 8; - /** Flag for setting the progress bar's visibility to VISIBLE */ - public static final int PROGRESS_VISIBILITY_ON = -1; - /** Flag for setting the progress bar's visibility to GONE */ - public static final int PROGRESS_VISIBILITY_OFF = -2; - /** Flag for setting the progress bar's indeterminate mode on */ - public static final int PROGRESS_INDETERMINATE_ON = -3; - /** Flag for setting the progress bar's indeterminate mode off */ - public static final int PROGRESS_INDETERMINATE_OFF = -4; - /** Starting value for the (primary) progress */ - public static final int PROGRESS_START = 0; - /** Ending value for the (primary) progress */ - public static final int PROGRESS_END = 10000; - /** Lowest possible value for the secondary progress */ - public static final int PROGRESS_SECONDARY_START = 20000; - /** Highest possible value for the secondary progress */ - public static final int PROGRESS_SECONDARY_END = 30000; - - /** The default features enabled */ - @SuppressWarnings({"PointlessBitwiseExpression"}) - protected static final int DEFAULT_FEATURES = (1 << FEATURE_OPTIONS_PANEL) | - (1 << FEATURE_CONTEXT_MENU); - - /** - * The ID that the main layout in the XML layout file should have. - */ - public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content; - - private final Context mContext; - - private TypedArray mWindowStyle; - private Callback mCallback; - private WindowManager mWindowManager; - private IBinder mAppToken; - private String mAppName; - private Window mContainer; - private Window mActiveChild; - private boolean mIsActive = false; - private boolean mHasChildren = false; - private int mForcedWindowFlags = 0; - - private int mFeatures = DEFAULT_FEATURES; - private int mLocalFeatures = DEFAULT_FEATURES; - - private boolean mHaveWindowFormat = false; - private int mDefaultWindowFormat = PixelFormat.OPAQUE; - - private boolean mHasSoftInputMode = false; - - // The current window attributes. - private final WindowManager.LayoutParams mWindowAttributes = - new WindowManager.LayoutParams(); - - /** - * API from a Window back to its caller. This allows the client to - * intercept key dispatching, panels and menus, etc. - */ - public interface Callback { - /** - * Called to process key events. At the very least your - * implementation must call - * {@link android.view.Window#superDispatchKeyEvent} to do the - * standard key processing. - * - * @param event The key event. - * - * @return boolean Return true if this event was consumed. - */ - public boolean dispatchKeyEvent(KeyEvent event); - - /** - * Called to process touch screen events. At the very least your - * implementation must call - * {@link android.view.Window#superDispatchTouchEvent} to do the - * standard touch screen processing. - * - * @param event The touch screen event. - * - * @return boolean Return true if this event was consumed. - */ - public boolean dispatchTouchEvent(MotionEvent event); - - /** - * Called to process trackball events. At the very least your - * implementation must call - * {@link android.view.Window#superDispatchTrackballEvent} to do the - * standard trackball processing. - * - * @param event The trackball event. - * - * @return boolean Return true if this event was consumed. - */ - public boolean dispatchTrackballEvent(MotionEvent event); - - /** - * Instantiate the view to display in the panel for 'featureId'. - * You can return null, in which case the default content (typically - * a menu) will be created for you. - * - * @param featureId Which panel is being created. - * - * @return view The top-level view to place in the panel. - * - * @see #onPreparePanel - */ - public View onCreatePanelView(int featureId); - - /** - * Initialize the contents of the menu for panel 'featureId'. This is - * called if onCreatePanelView() returns null, giving you a standard - * menu in which you can place your items. It is only called once for - * the panel, the first time it is shown. - * - * <p>You can safely hold on to <var>menu</var> (and any items created - * from it), making modifications to it as desired, until the next - * time onCreatePanelMenu() is called for this feature. - * - * @param featureId The panel being created. - * @param menu The menu inside the panel. - * - * @return boolean You must return true for the panel to be displayed; - * if you return false it will not be shown. - */ - public boolean onCreatePanelMenu(int featureId, Menu menu); - - /** - * Prepare a panel to be displayed. This is called right before the - * panel window is shown, every time it is shown. - * - * @param featureId The panel that is being displayed. - * @param view The View that was returned by onCreatePanelView(). - * @param menu If onCreatePanelView() returned null, this is the Menu - * being displayed in the panel. - * - * @return boolean You must return true for the panel to be displayed; - * if you return false it will not be shown. - * - * @see #onCreatePanelView - */ - public boolean onPreparePanel(int featureId, View view, Menu menu); - - /** - * Called when a panel's menu is opened by the user. This may also be - * called when the menu is changing from one type to another (for - * example, from the icon menu to the expanded menu). - * - * @param featureId The panel that the menu is in. - * @param menu The menu that is opened. - * @return Return true to allow the menu to open, or false to prevent - * the menu from opening. - */ - public boolean onMenuOpened(int featureId, Menu menu); - - /** - * Called when a panel's menu item has been selected by the user. - * - * @param featureId The panel that the menu is in. - * @param item The menu item that was selected. - * - * @return boolean Return true to finish processing of selection, or - * false to perform the normal menu handling (calling its - * Runnable or sending a Message to its target Handler). - */ - public boolean onMenuItemSelected(int featureId, MenuItem item); - - /** - * This is called whenever the current window attributes change. - * - - */ - public void onWindowAttributesChanged(WindowManager.LayoutParams attrs); - - /** - * This hook is called whenever the content view of the screen changes - * (due to a call to - * {@link Window#setContentView(View, android.view.ViewGroup.LayoutParams) - * Window.setContentView} or - * {@link Window#addContentView(View, android.view.ViewGroup.LayoutParams) - * Window.addContentView}). - */ - public void onContentChanged(); - - /** - * This hook is called whenever the window focus changes. - * - * @param hasFocus Whether the window now has focus. - */ - public void onWindowFocusChanged(boolean hasFocus); - - /** - * Called when a panel is being closed. If another logical subsequent - * panel is being opened (and this panel is being closed to make room for the subsequent - * panel), this method will NOT be called. - * - * @param featureId The panel that is being displayed. - * @param menu If onCreatePanelView() returned null, this is the Menu - * being displayed in the panel. - */ - public void onPanelClosed(int featureId, Menu menu); - - /** - * Called when the user signals the desire to start a search. - * - * @return true if search launched, false if activity refuses (blocks) - * - * @see android.app.Activity#onSearchRequested() - */ - public boolean onSearchRequested(); - } - - public Window(Context context) { - mContext = context; - } - - /** - * Return the Context this window policy is running in, for retrieving - * resources and other information. - * - * @return Context The Context that was supplied to the constructor. - */ - public final Context getContext() { - return mContext; - } - - /** - * Return the {@link android.R.styleable#Window} attributes from this - * window's theme. - */ - public final TypedArray getWindowStyle() { - synchronized (this) { - if (mWindowStyle == null) { - mWindowStyle = mContext.obtainStyledAttributes( - com.android.internal.R.styleable.Window); - } - return mWindowStyle; - } - } - - /** - * Set the container for this window. If not set, the DecorWindow - * operates as a top-level window; otherwise, it negotiates with the - * container to display itself appropriately. - * - * @param container The desired containing Window. - */ - public void setContainer(Window container) { - mContainer = container; - if (container != null) { - // Embedded screens never have a title. - mFeatures |= 1<<FEATURE_NO_TITLE; - mLocalFeatures |= 1<<FEATURE_NO_TITLE; - container.mHasChildren = true; - } - } - - /** - * Return the container for this Window. - * - * @return Window The containing window, or null if this is a - * top-level window. - */ - public final Window getContainer() { - return mContainer; - } - - public final boolean hasChildren() { - return mHasChildren; - } - - /** - * Set the window manager for use by this Window to, for example, - * display panels. This is <em>not</em> used for displaying the - * Window itself -- that must be done by the client. - * - * @param wm The ViewManager for adding new windows. - */ - public void setWindowManager(WindowManager wm, - IBinder appToken, String appName) { - mAppToken = appToken; - mAppName = appName; - if (wm == null) { - wm = WindowManagerImpl.getDefault(); - } - mWindowManager = new LocalWindowManager(wm); - } - - private class LocalWindowManager implements WindowManager { - LocalWindowManager(WindowManager wm) { - mWindowManager = wm; - } - - public final void addView(View view, ViewGroup.LayoutParams params) { - // Let this throw an exception on a bad params. - WindowManager.LayoutParams wp = (WindowManager.LayoutParams)params; - CharSequence curTitle = wp.getTitle(); - if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && - wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { - if (wp.token == null) { - View decor = peekDecorView(); - if (decor != null) { - wp.token = decor.getWindowToken(); - } - } - if (curTitle == null || curTitle.length() == 0) { - String title; - if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) { - title="Media"; - } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { - title="Panel"; - } else { - title=Integer.toString(wp.type); - } - if (mAppName != null) { - title += ":" + mAppName; - } - wp.setTitle(title); - } - } else { - if (wp.token == null) { - wp.token = mContainer == null ? mAppToken : mContainer.mAppToken; - } - if ((curTitle == null || curTitle.length() == 0) - && mAppName != null) { - wp.setTitle(mAppName); - } - } - if (wp.packageName == null) { - wp.packageName = mContext.getPackageName(); - } - mWindowManager.addView(view, params); - } - - public void updateViewLayout(View view, ViewGroup.LayoutParams params) { - mWindowManager.updateViewLayout(view, params); - } - - public final void removeView(View view) { - mWindowManager.removeView(view); - } - - public final void removeViewImmediate(View view) { - mWindowManager.removeViewImmediate(view); - } - - public Display getDefaultDisplay() { - return mWindowManager.getDefaultDisplay(); - } - - WindowManager mWindowManager; - } - - /** - * Return the window manager allowing this Window to display its own - * windows. - * - * @return WindowManager The ViewManager. - */ - public WindowManager getWindowManager() { - return mWindowManager; - } - - /** - * Set the Callback interface for this window, used to intercept key - * events and other dynamic operations in the window. - * - * @param callback The desired Callback interface. - */ - public void setCallback(Callback callback) { - mCallback = callback; - } - - /** - * Return the current Callback interface for this window. - */ - public final Callback getCallback() { - return mCallback; - } - - /** - * Return whether this window is being displayed with a floating style - * (based on the {@link android.R.attr#windowIsFloating} attribute in - * the style/theme). - * - * @return Returns true if the window is configured to be displayed floating - * on top of whatever is behind it. - */ - public abstract boolean isFloating(); - - /** - * Set the width and height layout parameters of the window. The default - * for both of these is FILL_PARENT; you can change them to WRAP_CONTENT to - * make a window that is not full-screen. - * - * @param width The desired layout width of the window. - * @param height The desired layout height of the window. - */ - public void setLayout(int width, int height) - { - final WindowManager.LayoutParams attrs = getAttributes(); - attrs.width = width; - attrs.height = height; - if (mCallback != null) { - mCallback.onWindowAttributesChanged(attrs); - } - } - - /** - * Set the gravity of the window, as per the Gravity constants. This - * controls how the window manager is positioned in the overall window; it - * is only useful when using WRAP_CONTENT for the layout width or height. - * - * @param gravity The desired gravity constant. - * - * @see Gravity - * @see #setLayout - */ - public void setGravity(int gravity) - { - final WindowManager.LayoutParams attrs = getAttributes(); - attrs.gravity = gravity; - if (mCallback != null) { - mCallback.onWindowAttributesChanged(attrs); - } - } - - /** - * Set the type of the window, as per the WindowManager.LayoutParams - * types. - * - * @param type The new window type (see WindowManager.LayoutParams). - */ - public void setType(int type) { - final WindowManager.LayoutParams attrs = getAttributes(); - attrs.type = type; - if (mCallback != null) { - mCallback.onWindowAttributesChanged(attrs); - } - } - - /** - * Set the format of window, as per the PixelFormat types. This overrides - * the default format that is selected by the Window based on its - * window decorations. - * - * @param format The new window format (see PixelFormat). Use - * PixelFormat.UNKNOWN to allow the Window to select - * the format. - * - * @see PixelFormat - */ - public void setFormat(int format) { - final WindowManager.LayoutParams attrs = getAttributes(); - if (format != PixelFormat.UNKNOWN) { - attrs.format = format; - mHaveWindowFormat = true; - } else { - attrs.format = mDefaultWindowFormat; - mHaveWindowFormat = false; - } - if (mCallback != null) { - mCallback.onWindowAttributesChanged(attrs); - } - } - - /** - * Specify custom animations to use for the window, as per - * {@link WindowManager.LayoutParams#windowAnimations - * WindowManager.LayoutParams.windowAnimations}. Providing anything besides - * 0 here will override the animations the window would - * normally retrieve from its theme. - */ - public void setWindowAnimations(int resId) { - final WindowManager.LayoutParams attrs = getAttributes(); - attrs.windowAnimations = resId; - if (mCallback != null) { - mCallback.onWindowAttributesChanged(attrs); - } - } - - /** - * Specify an explicit soft input mode to use for the window, as per - * {@link WindowManager.LayoutParams#softInputMode - * WindowManager.LayoutParams.softInputMode}. Providing anything besides - * "unspecified" here will override the input mode the window would - * normally retrieve from its theme. - */ - public void setSoftInputMode(int mode) { - final WindowManager.LayoutParams attrs = getAttributes(); - if (mode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) { - attrs.softInputMode = mode; - mHasSoftInputMode = true; - } else { - mHasSoftInputMode = false; - } - if (mCallback != null) { - mCallback.onWindowAttributesChanged(attrs); - } - } - - /** - * Convenience function to set the flag bits as specified in flags, as - * per {@link #setFlags}. - * @param flags The flag bits to be set. - * @see #setFlags - */ - public void addFlags(int flags) { - setFlags(flags, flags); - } - - /** - * Convenience function to clear the flag bits as specified in flags, as - * per {@link #setFlags}. - * @param flags The flag bits to be cleared. - * @see #setFlags - */ - public void clearFlags(int flags) { - setFlags(0, flags); - } - - /** - * Set the flags of the window, as per the - * {@link WindowManager.LayoutParams WindowManager.LayoutParams} - * flags. - * - * <p>Note that some flags must be set before the window decoration is - * created (by the first call to - * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)} or - * {@link #getDecorView()}: - * {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN} and - * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}. These - * will be set for you based on the {@link android.R.attr#windowIsFloating} - * attribute. - * - * @param flags The new window flags (see WindowManager.LayoutParams). - * @param mask Which of the window flag bits to modify. - */ - public void setFlags(int flags, int mask) { - final WindowManager.LayoutParams attrs = getAttributes(); - attrs.flags = (attrs.flags&~mask) | (flags&mask); - mForcedWindowFlags |= mask; - if (mCallback != null) { - mCallback.onWindowAttributesChanged(attrs); - } - } - - /** - * Specify custom window attributes. <strong>PLEASE NOTE:</strong> the - * layout params you give here should generally be from values previously - * retrieved with {@link #getAttributes()}; you probably do not want to - * blindly create and apply your own, since this will blow away any values - * set by the framework that you are not interested in. - * - * @param a The new window attributes, which will completely override any - * current values. - */ - public void setAttributes(WindowManager.LayoutParams a) { - mWindowAttributes.copyFrom(a); - if (mCallback != null) { - mCallback.onWindowAttributesChanged(mWindowAttributes); - } - } - - /** - * Retrieve the current window attributes associated with this panel. - * - * @return WindowManager.LayoutParams Either the existing window - * attributes object, or a freshly created one if there is none. - */ - public final WindowManager.LayoutParams getAttributes() { - return mWindowAttributes; - } - - /** - * Return the window flags that have been explicitly set by the client, - * so will not be modified by {@link #getDecorView}. - */ - protected final int getForcedWindowFlags() { - return mForcedWindowFlags; - } - - /** - * Has the app specified their own soft input mode? - */ - protected final boolean hasSoftInputMode() { - return mHasSoftInputMode; - } - - /** - * Enable extended screen features. This must be called before - * setContentView(). May be called as many times as desired as long as it - * is before setContentView(). If not called, no extended features - * will be available. You can not turn off a feature once it is requested. - * You canot use other title features with {@link #FEATURE_CUSTOM_TITLE}. - * - * @param featureId The desired features, defined as constants by Window. - * @return The features that are now set. - */ - public boolean requestFeature(int featureId) { - final int flag = 1<<featureId; - mFeatures |= flag; - mLocalFeatures |= mContainer != null ? (flag&~mContainer.mFeatures) : flag; - return (mFeatures&flag) != 0; - } - - public final void makeActive() { - if (mContainer != null) { - if (mContainer.mActiveChild != null) { - mContainer.mActiveChild.mIsActive = false; - } - mContainer.mActiveChild = this; - } - mIsActive = true; - onActive(); - } - - public final boolean isActive() - { - return mIsActive; - } - - /** - * Finds a view that was identified by the id attribute from the XML that - * was processed in {@link android.app.Activity#onCreate}. This will - * implicitly call {@link #getDecorView} for you, with all of the - * associated side-effects. - * - * @return The view if found or null otherwise. - */ - public View findViewById(int id) { - return getDecorView().findViewById(id); - } - - /** - * Convenience for - * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)} - * to set the screen content from a layout resource. The resource will be - * inflated, adding all top-level views to the screen. - * - * @param layoutResID Resource ID to be inflated. - * @see #setContentView(View, android.view.ViewGroup.LayoutParams) - */ - public abstract void setContentView(int layoutResID); - - /** - * Convenience for - * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)} - * set the screen content to an explicit view. This view is placed - * directly into the screen's view hierarchy. It can itself be a complex - * view hierarhcy. - * - * @param view The desired content to display. - * @see #setContentView(View, android.view.ViewGroup.LayoutParams) - */ - public abstract void setContentView(View view); - - /** - * Set the screen content to an explicit view. This view is placed - * directly into the screen's view hierarchy. It can itself be a complex - * view hierarchy. - * - * <p>Note that calling this function "locks in" various characteristics - * of the window that can not, from this point forward, be changed: the - * features that have been requested with {@link #requestFeature(int)}, - * and certain window flags as described in {@link #setFlags(int, int)}. - * - * @param view The desired content to display. - * @param params Layout parameters for the view. - */ - public abstract void setContentView(View view, ViewGroup.LayoutParams params); - - /** - * Variation on - * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)} - * to add an additional content view to the screen. Added after any existing - * ones in the screen -- existing views are NOT removed. - * - * @param view The desired content to display. - * @param params Layout parameters for the view. - */ - public abstract void addContentView(View view, ViewGroup.LayoutParams params); - - /** - * Return the view in this Window that currently has focus, or null if - * there are none. Note that this does not look in any containing - * Window. - * - * @return View The current View with focus or null. - */ - public abstract View getCurrentFocus(); - - /** - * Quick access to the {@link LayoutInflater} instance that this Window - * retrieved from its Context. - * - * @return LayoutInflater The shared LayoutInflater. - */ - public abstract LayoutInflater getLayoutInflater(); - - public abstract void setTitle(CharSequence title); - - public abstract void setTitleColor(int textColor); - - public abstract void openPanel(int featureId, KeyEvent event); - - public abstract void closePanel(int featureId); - - public abstract void togglePanel(int featureId, KeyEvent event); - - public abstract boolean performPanelShortcut(int featureId, - int keyCode, - KeyEvent event, - int flags); - public abstract boolean performPanelIdentifierAction(int featureId, - int id, - int flags); - - public abstract void closeAllPanels(); - - public abstract boolean performContextMenuIdentifierAction(int id, int flags); - - /** - * Should be called when the configuration is changed. - * - * @param newConfig The new configuration. - */ - public abstract void onConfigurationChanged(Configuration newConfig); - - /** - * Change the background of this window to a Drawable resource. Setting the - * background to null will make the window be opaque. To make the window - * transparent, you can use an empty drawable (for instance a ColorDrawable - * with the color 0 or the system drawable android:drawable/empty.) - * - * @param resid The resource identifier of a drawable resource which will be - * installed as the new background. - */ - public void setBackgroundDrawableResource(int resid) - { - setBackgroundDrawable(mContext.getResources().getDrawable(resid)); - } - - /** - * Change the background of this window to a custom Drawable. Setting the - * background to null will make the window be opaque. To make the window - * transparent, you can use an empty drawable (for instance a ColorDrawable - * with the color 0 or the system drawable android:drawable/empty.) - * - * @param drawable The new Drawable to use for this window's background. - */ - public abstract void setBackgroundDrawable(Drawable drawable); - - /** - * Set the value for a drawable feature of this window, from a resource - * identifier. You must have called requestFeauture(featureId) before - * calling this function. - * - * @see android.content.res.Resources#getDrawable(int) - * - * @param featureId The desired drawable feature to change, defined as a - * constant by Window. - * @param resId Resource identifier of the desired image. - */ - public abstract void setFeatureDrawableResource(int featureId, int resId); - - /** - * Set the value for a drawable feature of this window, from a URI. You - * must have called requestFeature(featureId) before calling this - * function. - * - * <p>The only URI currently supported is "content:", specifying an image - * in a content provider. - * - * @see android.widget.ImageView#setImageURI - * - * @param featureId The desired drawable feature to change. Features are - * constants defined by Window. - * @param uri The desired URI. - */ - public abstract void setFeatureDrawableUri(int featureId, Uri uri); - - /** - * Set an explicit Drawable value for feature of this window. You must - * have called requestFeature(featureId) before calling this function. - * - * @param featureId The desired drawable feature to change. - * Features are constants defined by Window. - * @param drawable A Drawable object to display. - */ - public abstract void setFeatureDrawable(int featureId, Drawable drawable); - - /** - * Set a custom alpha value for the given drawale feature, controlling how - * much the background is visible through it. - * - * @param featureId The desired drawable feature to change. - * Features are constants defined by Window. - * @param alpha The alpha amount, 0 is completely transparent and 255 is - * completely opaque. - */ - public abstract void setFeatureDrawableAlpha(int featureId, int alpha); - - /** - * Set the integer value for a feature. The range of the value depends on - * the feature being set. For FEATURE_PROGRESSS, it should go from 0 to - * 10000. At 10000 the progress is complete and the indicator hidden. - * - * @param featureId The desired feature to change. - * Features are constants defined by Window. - * @param value The value for the feature. The interpretation of this - * value is feature-specific. - */ - public abstract void setFeatureInt(int featureId, int value); - - /** - * Request that key events come to this activity. Use this if your - * activity has no views with focus, but the activity still wants - * a chance to process key events. - */ - public abstract void takeKeyEvents(boolean get); - - /** - * Used by custom windows, such as Dialog, to pass the key press event - * further down the view hierarchy. Application developers should - * not need to implement or call this. - * - */ - public abstract boolean superDispatchKeyEvent(KeyEvent event); - - /** - * Used by custom windows, such as Dialog, to pass the touch screen event - * further down the view hierarchy. Application developers should - * not need to implement or call this. - * - */ - public abstract boolean superDispatchTouchEvent(MotionEvent event); - - /** - * Used by custom windows, such as Dialog, to pass the trackball event - * further down the view hierarchy. Application developers should - * not need to implement or call this. - * - */ - public abstract boolean superDispatchTrackballEvent(MotionEvent event); - - /** - * Retrieve the top-level window decor view (containing the standard - * window frame/decorations and the client's content inside of that), which - * can be added as a window to the window manager. - * - * <p><em>Note that calling this function for the first time "locks in" - * various window characteristics as described in - * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)}.</em></p> - * - * @return Returns the top-level window decor view. - */ - public abstract View getDecorView(); - - /** - * Retrieve the current decor view, but only if it has already been created; - * otherwise returns null. - * - * @return Returns the top-level window decor or null. - * @see #getDecorView - */ - public abstract View peekDecorView(); - - public abstract Bundle saveHierarchyState(); - - public abstract void restoreHierarchyState(Bundle savedInstanceState); - - protected abstract void onActive(); - - /** - * Return the feature bits that are enabled. This is the set of features - * that were given to requestFeature(), and are being handled by this - * Window itself or its container. That is, it is the set of - * requested features that you can actually use. - * - * <p>To do: add a public version of this API that allows you to check for - * features by their feature ID. - * - * @return int The feature bits. - */ - protected final int getFeatures() - { - return mFeatures; - } - - /** - * Return the feature bits that are being implemented by this Window. - * This is the set of features that were given to requestFeature(), and are - * being handled by only this Window itself, not by its containers. - * - * @return int The feature bits. - */ - protected final int getLocalFeatures() - { - return mLocalFeatures; - } - - /** - * Set the default format of window, as per the PixelFormat types. This - * is the format that will be used unless the client specifies in explicit - * format with setFormat(); - * - * @param format The new window format (see PixelFormat). - * - * @see #setFormat - * @see PixelFormat - */ - protected void setDefaultWindowFormat(int format) { - mDefaultWindowFormat = format; - if (!mHaveWindowFormat) { - final WindowManager.LayoutParams attrs = getAttributes(); - attrs.format = format; - if (mCallback != null) { - mCallback.onWindowAttributesChanged(attrs); - } - } - } - - public abstract void setChildDrawable(int featureId, Drawable drawable); - - public abstract void setChildInt(int featureId, int value); - - /** - * Is a keypress one of the defined shortcut keys for this window. - * @param keyCode the key code from {@link android.view.KeyEvent} to check. - * @param event the {@link android.view.KeyEvent} to use to help check. - */ - public abstract boolean isShortcutKey(int keyCode, KeyEvent event); - - /** - * @see android.app.Activity#setVolumeControlStream(int) - */ - public abstract void setVolumeControlStream(int streamType); - - /** - * @see android.app.Activity#getVolumeControlStream() - */ - public abstract int getVolumeControlStream(); - -} diff --git a/core/java/android/view/WindowManager.aidl b/core/java/android/view/WindowManager.aidl deleted file mode 100755 index 556dc72..0000000 --- a/core/java/android/view/WindowManager.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/* //device/java/android/android/view/WindowManager.aidl -** -** Copyright 2007, 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.view; - -parcelable WindowManager.LayoutParams; - diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java deleted file mode 100644 index b87cc42..0000000 --- a/core/java/android/view/WindowManager.java +++ /dev/null @@ -1,959 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.content.pm.ActivityInfo; -import android.graphics.PixelFormat; -import android.os.IBinder; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; -import android.util.Log; - - -/** - * The interface that apps use to talk to the window manager. - * <p> - * Use <code>Context.getSystemService(Context.WINDOW_SERVICE)</code> to get one of these. - * - * @see android.content.Context#getSystemService - * @see android.content.Context#WINDOW_SERVICE - */ -public interface WindowManager extends ViewManager { - /** - * Exception that is thrown when trying to add view whose - * {@link WindowManager.LayoutParams} {@link WindowManager.LayoutParams#token} - * is invalid. - */ - public static class BadTokenException extends RuntimeException { - public BadTokenException() { - } - - public BadTokenException(String name) { - super(name); - } - } - - /** - * Use this method to get the default Display object. - * - * @return default Display object - */ - public Display getDefaultDisplay(); - - /** - * Special variation of {@link #removeView} that immediately invokes - * the given view hierarchy's {@link View#onDetachedFromWindow() - * View.onDetachedFromWindow()} methods before returning. This is not - * for normal applications; using it correctly requires great care. - * - * @param view The view to be removed. - */ - public void removeViewImmediate(View view); - - public static class LayoutParams extends ViewGroup.LayoutParams - implements Parcelable { - /** - * X position for this window. With the default gravity it is ignored. - * When using {@link Gravity#LEFT} or {@link Gravity#RIGHT} it provides - * an offset from the given edge. - */ - public int x; - - /** - * Y position for this window. With the default gravity it is ignored. - * When using {@link Gravity#TOP} or {@link Gravity#BOTTOM} it provides - * an offset from the given edge. - */ - public int y; - - /** - * Indicates how much of the extra space will be allocated horizontally - * to the view associated with these LayoutParams. Specify 0 if the view - * should not be stretched. Otherwise the extra pixels will be pro-rated - * among all views whose weight is greater than 0. - */ - public float horizontalWeight; - - /** - * Indicates how much of the extra space will be allocated vertically - * to the view associated with these LayoutParams. Specify 0 if the view - * should not be stretched. Otherwise the extra pixels will be pro-rated - * among all views whose weight is greater than 0. - */ - public float verticalWeight; - - /** - * The general type of window. There are three main classes of - * window types: - * <ul> - * <li> <strong>Application windows</strong> (ranging from - * {@link #FIRST_APPLICATION_WINDOW} to - * {@link #LAST_APPLICATION_WINDOW}) are normal top-level application - * windows. For these types of windows, the {@link #token} must be - * set to the token of the activity they are a part of (this will - * normally be done for you if {@link #token} is null). - * <li> <strong>Sub-windows</strong> (ranging from - * {@link #FIRST_SUB_WINDOW} to - * {@link #LAST_SUB_WINDOW}) are associated with another top-level - * window. For these types of windows, the {@link #token} must be - * the token of the window it is attached to. - * <li> <strong>System windows</strong> (ranging from - * {@link #FIRST_SYSTEM_WINDOW} to - * {@link #LAST_SYSTEM_WINDOW}) are special types of windows for - * use by the system for specific purposes. They should not normally - * be used by applications, and a special permission is required - * to use them. - * </ul> - * - * @see #TYPE_BASE_APPLICATION - * @see #TYPE_APPLICATION - * @see #TYPE_APPLICATION_STARTING - * @see #TYPE_APPLICATION_PANEL - * @see #TYPE_APPLICATION_MEDIA - * @see #TYPE_APPLICATION_SUB_PANEL - * @see #TYPE_APPLICATION_ATTACHED_DIALOG - * @see #TYPE_STATUS_BAR - * @see #TYPE_SEARCH_BAR - * @see #TYPE_PHONE - * @see #TYPE_SYSTEM_ALERT - * @see #TYPE_KEYGUARD - * @see #TYPE_TOAST - * @see #TYPE_SYSTEM_OVERLAY - * @see #TYPE_PRIORITY_PHONE - * @see #TYPE_STATUS_BAR_PANEL - * @see #TYPE_SYSTEM_DIALOG - * @see #TYPE_KEYGUARD_DIALOG - * @see #TYPE_SYSTEM_ERROR - * @see #TYPE_INPUT_METHOD - * @see #TYPE_INPUT_METHOD_DIALOG - */ - public int type; - - /** - * Start of window types that represent normal application windows. - */ - public static final int FIRST_APPLICATION_WINDOW = 1; - - /** - * Window type: an application window that serves as the "base" window - * of the overall application; all other application windows will - * appear on top of it. - */ - public static final int TYPE_BASE_APPLICATION = 1; - - /** - * Window type: a normal application window. The {@link #token} must be - * an Activity token identifying who the window belongs to. - */ - public static final int TYPE_APPLICATION = 2; - - /** - * Window type: special application window that is displayed while the - * application is starting. Not for use by applications themselves; - * this is used by the system to display something until the - * application can show its own windows. - */ - public static final int TYPE_APPLICATION_STARTING = 3; - - /** - * End of types of application windows. - */ - public static final int LAST_APPLICATION_WINDOW = 99; - - /** - * Start of types of sub-windows. The {@link #token} of these windows - * must be set to the window they are attached to. These types of - * windows are kept next to their attached window in Z-order, and their - * coordinate space is relative to their attached window. - */ - public static final int FIRST_SUB_WINDOW = 1000; - - /** - * Window type: a panel on top of an application window. These windows - * appear on top of their attached window. - */ - public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW; - - /** - * Window type: window for showing media (e.g. video). These windows - * are displayed behind their attached window. - */ - public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1; - - /** - * Window type: a sub-panel on top of an application window. These - * windows are displayed on top their attached window and any - * {@link #TYPE_APPLICATION_PANEL} panels. - */ - public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2; - - /** Window type: like {@link #TYPE_APPLICATION_PANEL}, but layout - * of the window happens as that of a top-level window, <em>not</em> - * as a child of its container. - */ - public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3; - - /** - * End of types of sub-windows. - */ - public static final int LAST_SUB_WINDOW = 1999; - - /** - * Start of system-specific window types. These are not normally - * created by applications. - */ - public static final int FIRST_SYSTEM_WINDOW = 2000; - - /** - * Window type: the status bar. There can be only one status bar - * window; it is placed at the top of the screen, and all other - * windows are shifted down so they are below it. - */ - public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW; - - /** - * Window type: the search bar. There can be only one search bar - * window; it is placed at the top of the screen. - */ - public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1; - - /** - * Window type: phone. These are non-application windows providing - * user interaction with the phone (in particular incoming calls). - * These windows are normally placed above all applications, but behind - * the status bar. - */ - public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2; - - /** - * Window type: system window, such as low power alert. These windows - * are always on top of application windows. - */ - public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3; - - /** - * Window type: keyguard window. - */ - public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4; - - /** - * Window type: transient notifications. - */ - public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5; - - /** - * Window type: system overlay windows, which need to be displayed - * on top of everything else. These windows must not take input - * focus, or they will interfere with the keyguard. - */ - public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6; - - /** - * Window type: priority phone UI, which needs to be displayed even if - * the keyguard is active. These windows must not take input - * focus, or they will interfere with the keyguard. - */ - public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7; - - /** - * Window type: panel that slides out from the status bar - */ - public static final int TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+8; - - /** - * Window type: panel that slides out from the status bar - */ - public static final int TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8; - - /** - * Window type: dialogs that the keyguard shows - */ - public static final int TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9; - - /** - * Window type: internal system error windows, appear on top of - * everything they can. - */ - public static final int TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10; - - /** - * Window type: internal input methods windows, which appear above - * the normal UI. Application windows may be resized or panned to keep - * the input focus visible while this window is displayed. - */ - public static final int TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11; - - /** - * Window type: internal input methods dialog windows, which appear above - * the current input method window. - */ - public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12; - - /** - * End of types of system windows. - */ - public static final int LAST_SYSTEM_WINDOW = 2999; - - /** - * Specifies what type of memory buffers should be used by this window. - * Default is normal. - * - * @see #MEMORY_TYPE_NORMAL - * @see #MEMORY_TYPE_HARDWARE - * @see #MEMORY_TYPE_GPU - * @see #MEMORY_TYPE_PUSH_BUFFERS - */ - public int memoryType; - - /** Memory type: The window's surface is allocated in main memory. */ - public static final int MEMORY_TYPE_NORMAL = 0; - /** Memory type: The window's surface is configured to be accessible - * by DMA engines and hardware accelerators. */ - public static final int MEMORY_TYPE_HARDWARE = 1; - /** Memory type: The window's surface is configured to be accessible - * by graphics accelerators. */ - public static final int MEMORY_TYPE_GPU = 2; - /** Memory type: The window's surface doesn't own its buffers and - * therefore cannot be locked. Instead the buffers are pushed to - * it through native binder calls. */ - public static final int MEMORY_TYPE_PUSH_BUFFERS = 3; - - /** - * Various behavioral options/flags. Default is none. - * - * @see #FLAG_BLUR_BEHIND - * @see #FLAG_DIM_BEHIND - * @see #FLAG_NOT_FOCUSABLE - * @see #FLAG_NOT_TOUCHABLE - * @see #FLAG_NOT_TOUCH_MODAL - * @see #FLAG_LAYOUT_IN_SCREEN - * @see #FLAG_DITHER - * @see #FLAG_KEEP_SCREEN_ON - * @see #FLAG_FULLSCREEN - * @see #FLAG_FORCE_NOT_FULLSCREEN - * @see #FLAG_IGNORE_CHEEK_PRESSES - */ - public int flags; - - /** Window flag: everything behind this window will be dimmed. - * Use {@link #dimAmount} to control the amount of dim. */ - public static final int FLAG_DIM_BEHIND = 0x00000002; - - /** Window flag: blur everything behind this window. */ - public static final int FLAG_BLUR_BEHIND = 0x00000004; - - /** Window flag: this window won't ever get key input focus, so the - * user can not send key or other button events to it. Those will - * instead go to whatever focusable window is behind it. This flag - * will also enable {@link #FLAG_NOT_TOUCH_MODAL} whether or not that - * is explicitly set. - * - * <p>Setting this flag also implies that the window will not need to - * interact with - * a soft input method, so it will be Z-ordered and positioned - * independently of any active input method (typically this means it - * gets Z-ordered on top of the input method, so it can use the full - * screen for its content and cover the input method if needed. You - * can use {@link #FLAG_ALT_FOCUSABLE_IM} to modify this behavior. */ - public static final int FLAG_NOT_FOCUSABLE = 0x00000008; - - /** Window flag: this window can never receive touch events. */ - public static final int FLAG_NOT_TOUCHABLE = 0x00000010; - - /** Window flag: Even when this window is focusable (its - * {@link #FLAG_NOT_FOCUSABLE is not set), allow any pointer events - * outside of the window to be sent to the windows behind it. Otherwise - * it will consume all pointer events itself, regardless of whether they - * are inside of the window. */ - public static final int FLAG_NOT_TOUCH_MODAL = 0x00000020; - - /** Window flag: When set, if the device is asleep when the touch - * screen is pressed, you will receive this first touch event. Usually - * the first touch event is consumed by the system since the user can - * not see what they are pressing on. - */ - public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040; - - /** Window flag: as long as this window is visible to the user, keep - * the device's screen turned on and bright. */ - public static final int FLAG_KEEP_SCREEN_ON = 0x00000080; - - /** Window flag: place the window within the entire screen, ignoring - * decorations around the border (a.k.a. the status bar). The - * window must correctly position its contents to take the screen - * decoration into account. This flag is normally set for you - * by Window as described in {@link Window#setFlags}. */ - public static final int FLAG_LAYOUT_IN_SCREEN = 0x00000100; - - /** Window flag: allow window to extend outside of the screen. */ - public static final int FLAG_LAYOUT_NO_LIMITS = 0x00000200; - - /** Window flag: Hide all screen decorations (e.g. status bar) while - * this window is displayed. This allows the window to use the entire - * display space for itself -- the status bar will be hidden when - * an app window with this flag set is on the top layer. */ - public static final int FLAG_FULLSCREEN = 0x00000400; - - /** Window flag: Override {@link #FLAG_FULLSCREEN and force the - * screen decorations (such as status bar) to be shown. */ - public static final int FLAG_FORCE_NOT_FULLSCREEN = 0x00000800; - - /** Window flag: turn on dithering when compositing this window to - * the screen. */ - public static final int FLAG_DITHER = 0x00001000; - - /** Window flag: don't allow screen shots while this window is - * displayed. */ - public static final int FLAG_SECURE = 0x00002000; - - /** Window flag: a special mode where the layout parameters are used - * to perform scaling of the surface when it is composited to the - * screen. */ - public static final int FLAG_SCALED = 0x00004000; - - /** Window flag: intended for windows that will often be used when the user is - * holding the screen against their face, it will aggressively filter the event - * stream to prevent unintended presses in this situation that may not be - * desired for a particular window, when such an event stream is detected, the - * application will receive a CANCEL motion event to indicate this so applications - * can handle this accordingly by taking no action on the event - * until the finger is released. */ - public static final int FLAG_IGNORE_CHEEK_PRESSES = 0x00008000; - - /** Window flag: a special option only for use in combination with - * {@link #FLAG_LAYOUT_IN_SCREEN}. When requesting layout in the - * screen your window may appear on top of or behind screen decorations - * such as the status bar. By also including this flag, the window - * manager will report the inset rectangle needed to ensure your - * content is not covered by screen decorations. This flag is normally - * set for you by Window as described in {@link Window#setFlags}.*/ - public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000; - - /** Window flag: invert the state of {@link #FLAG_NOT_FOCUSABLE} with - * respect to how this window interacts with the current method. That - * is, if FLAG_NOT_FOCUSABLE is set and this flag is set, then the - * window will behave as if it needs to interact with the input method - * and thus be placed behind/away from it; if FLAG_NOT_FOCUSABLE is - * not set and this flag is set, then the window will behave as if it - * doesn't need to interact with the input method and can be placed - * to use more space and cover the input method. - */ - public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000; - - /** Window flag: if you have set {@link #FLAG_NOT_TOUCH_MODAL}, you - * can set this flag to receive a single special MotionEvent with - * the action - * {@link MotionEvent#ACTION_OUTSIDE MotionEvent.ACTION_OUTSIDE} for - * touches that occur outside of your window. Note that you will not - * receive the full down/move/up gesture, only the location of the - * first down as an ACTION_OUTSIDE. - */ - public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000; - - /** Window flag: a special option intended for system dialogs. When - * this flag is set, the window will demand focus unconditionally when - * it is created. - * {@hide} */ - public static final int FLAG_SYSTEM_ERROR = 0x40000000; - - /** - * Given a particular set of window manager flags, determine whether - * such a window may be a target for an input method when it has - * focus. In particular, this checks the - * {@link #FLAG_NOT_FOCUSABLE} and {@link #FLAG_ALT_FOCUSABLE_IM} - * flags and returns true if the combination of the two corresponds - * to a window that needs to be behind the input method so that the - * user can type into it. - * - * @param flags The current window manager flags. - * - * @return Returns true if such a window should be behind/interact - * with an input method, false if not. - */ - public static boolean mayUseInputMethod(int flags) { - switch (flags&(FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) { - case 0: - case FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM: - return true; - } - return false; - } - - /** - * Mask for {@link #softInputMode} of the bits that determine the - * desired visibility state of the soft input area for this window. - */ - public static final int SOFT_INPUT_MASK_STATE = 0x0f; - - /** - * Visibility state for {@link #softInputMode}: no state has been specified. - */ - public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0; - - /** - * Visibility state for {@link #softInputMode}: please don't change the state of - * the soft input area. - */ - public static final int SOFT_INPUT_STATE_UNCHANGED = 1; - - /** - * Visibility state for {@link #softInputMode}: please hide any soft input - * area when normally appropriate (when the user is navigating - * forward to your window). - */ - public static final int SOFT_INPUT_STATE_HIDDEN = 2; - - /** - * Visibility state for {@link #softInputMode}: please always hide any - * soft input area when this window receives focus. - */ - public static final int SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3; - - /** - * Visibility state for {@link #softInputMode}: please show the soft - * input area when normally appropriate (when the user is navigating - * forward to your window). - */ - public static final int SOFT_INPUT_STATE_VISIBLE = 4; - - /** - * Visibility state for {@link #softInputMode}: please always make the - * soft input area visible when this window receives input focus. - */ - public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5; - - /** - * Mask for {@link #softInputMode} of the bits that determine the - * way that the window should be adjusted to accommodate the soft - * input window. - */ - public static final int SOFT_INPUT_MASK_ADJUST = 0xf0; - - /** Adjustment option for {@link #softInputMode}: nothing specified. - * The system will try to pick one or - * the other depending on the contents of the window. - */ - public static final int SOFT_INPUT_ADJUST_UNSPECIFIED = 0x00; - - /** Adjustment option for {@link #softInputMode}: set to allow the - * window to be resized when an input - * method is shown, so that its contents are not covered by the input - * method. This can <em>not<em> be combined with - * {@link #SOFT_INPUT_ADJUST_PAN}; if - * neither of these are set, then the system will try to pick one or - * the other depending on the contents of the window. - */ - public static final int SOFT_INPUT_ADJUST_RESIZE = 0x10; - - /** Adjustment option for {@link #softInputMode}: set to have a window - * pan when an input method is - * shown, so it doesn't need to deal with resizing but just panned - * by the framework to ensure the current input focus is visible. This - * can <em>not<em> be combined with {@link #SOFT_INPUT_ADJUST_RESIZE}; if - * neither of these are set, then the system will try to pick one or - * the other depending on the contents of the window. - */ - public static final int SOFT_INPUT_ADJUST_PAN = 0x20; - - /** - * Bit for {@link #softInputMode}: set when the user has navigated - * forward to the window. This is normally set automatically for - * you by the system, though you may want to set it in certain cases - * when you are displaying a window yourself. This flag will always - * be cleared automatically after the window is displayed. - */ - public static final int SOFT_INPUT_IS_FORWARD_NAVIGATION = 0x100; - - /** - * Desired operating mode for any soft input area. May any combination - * of: - * - * <ul> - * <li> One of the visibility states - * {@link #SOFT_INPUT_STATE_UNSPECIFIED}, {@link #SOFT_INPUT_STATE_UNCHANGED}, - * {@link #SOFT_INPUT_STATE_HIDDEN}, {@link #SOFT_INPUT_STATE_ALWAYS_VISIBLE}, or - * {@link #SOFT_INPUT_STATE_VISIBLE}. - * <li> One of the adjustment options - * {@link #SOFT_INPUT_ADJUST_UNSPECIFIED}, - * {@link #SOFT_INPUT_ADJUST_RESIZE}, or - * {@link #SOFT_INPUT_ADJUST_PAN}. - */ - public int softInputMode; - - /** - * Placement of window within the screen as per {@link Gravity} - * - * @see Gravity - */ - public int gravity; - - /** - * The horizontal margin, as a percentage of the container's width, - * between the container and the widget. - */ - public float horizontalMargin; - - /** - * The vertical margin, as a percentage of the container's height, - * between the container and the widget. - */ - public float verticalMargin; - - /** - * The desired bitmap format. May be one of the constants in - * {@link android.graphics.PixelFormat}. Default is OPAQUE. - */ - public int format; - - /** - * A style resource defining the animations to use for this window. - * This must be a system resource; it can not be an application resource - * because the window manager does not have access to applications. - */ - public int windowAnimations; - - /** - * An alpha value to apply to this entire window. - * An alpha of 1.0 means fully opaque and 0.0 means fully transparent - */ - public float alpha = 1.0f; - - /** - * When {@link #FLAG_DIM_BEHIND} is set, this is the amount of dimming - * to apply. Range is from 1.0 for completely opaque to 0.0 for no - * dim. - */ - public float dimAmount = 1.0f; - - /** - * This can be used to override the user's preferred brightness of - * the screen. A value of less than 0, the default, means to use the - * preferred screen brightness. 0 to 1 adjusts the brightness from - * dark to full bright. - */ - public float screenBrightness = -1.0f; - - /** - * Identifier for this window. This will usually be filled in for - * you. - */ - public IBinder token = null; - - /** - * Name of the package owning this window. - */ - public String packageName = null; - - /** - * Specific orientation value for a window. - * May be any of the same values allowed - * for {@link android.content.pm.ActivityInfo#screenOrientation}. - * If not set, a default value of - * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} - * will be used. - */ - public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; - - - public LayoutParams() { - super(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); - type = TYPE_APPLICATION; - format = PixelFormat.OPAQUE; - } - - public LayoutParams(int _type) { - super(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); - type = _type; - format = PixelFormat.OPAQUE; - } - - public LayoutParams(int _type, int _flags) { - super(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); - type = _type; - flags = _flags; - format = PixelFormat.OPAQUE; - } - - public LayoutParams(int _type, int _flags, int _format) { - super(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); - type = _type; - flags = _flags; - format = _format; - } - - public LayoutParams(int w, int h, int _type, int _flags, int _format) { - super(w, h); - type = _type; - flags = _flags; - format = _format; - } - - public LayoutParams(int w, int h, int xpos, int ypos, int _type, - int _flags, int _format) { - super(w, h); - x = xpos; - y = ypos; - type = _type; - flags = _flags; - format = _format; - } - - public final void setTitle(CharSequence title) { - if (null == title) - title = ""; - - mTitle = TextUtils.stringOrSpannedString(title); - } - - public final CharSequence getTitle() { - return mTitle; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel out, int parcelableFlags) { - out.writeInt(width); - out.writeInt(height); - out.writeInt(x); - out.writeInt(y); - out.writeInt(type); - out.writeInt(memoryType); - out.writeInt(flags); - out.writeInt(softInputMode); - out.writeInt(gravity); - out.writeFloat(horizontalMargin); - out.writeFloat(verticalMargin); - out.writeInt(format); - out.writeInt(windowAnimations); - out.writeFloat(alpha); - out.writeFloat(dimAmount); - out.writeFloat(screenBrightness); - out.writeStrongBinder(token); - out.writeString(packageName); - TextUtils.writeToParcel(mTitle, out, parcelableFlags); - out.writeInt(screenOrientation); - } - - public static final Parcelable.Creator<LayoutParams> CREATOR - = new Parcelable.Creator<LayoutParams>() { - public LayoutParams createFromParcel(Parcel in) { - return new LayoutParams(in); - } - - public LayoutParams[] newArray(int size) { - return new LayoutParams[size]; - } - }; - - - public LayoutParams(Parcel in) { - width = in.readInt(); - height = in.readInt(); - x = in.readInt(); - y = in.readInt(); - type = in.readInt(); - memoryType = in.readInt(); - flags = in.readInt(); - softInputMode = in.readInt(); - gravity = in.readInt(); - horizontalMargin = in.readFloat(); - verticalMargin = in.readFloat(); - format = in.readInt(); - windowAnimations = in.readInt(); - alpha = in.readFloat(); - dimAmount = in.readFloat(); - screenBrightness = in.readFloat(); - token = in.readStrongBinder(); - packageName = in.readString(); - mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - screenOrientation = in.readInt(); - } - - public static final int LAYOUT_CHANGED = 1<<0; - public static final int TYPE_CHANGED = 1<<1; - public static final int FLAGS_CHANGED = 1<<2; - public static final int FORMAT_CHANGED = 1<<3; - public static final int ANIMATION_CHANGED = 1<<4; - public static final int DIM_AMOUNT_CHANGED = 1<<5; - public static final int TITLE_CHANGED = 1<<6; - public static final int ALPHA_CHANGED = 1<<7; - public static final int MEMORY_TYPE_CHANGED = 1<<8; - public static final int SOFT_INPUT_MODE_CHANGED = 1<<9; - public static final int SCREEN_ORIENTATION_CHANGED = 1<<10; - public static final int SCREEN_BRIGHTNESS_CHANGED = 1<<11; - - public final int copyFrom(LayoutParams o) { - int changes = 0; - - if (width != o.width) { - width = o.width; - changes |= LAYOUT_CHANGED; - } - if (height != o.height) { - height = o.height; - changes |= LAYOUT_CHANGED; - } - if (x != o.x) { - x = o.x; - changes |= LAYOUT_CHANGED; - } - if (y != o.y) { - y = o.y; - changes |= LAYOUT_CHANGED; - } - if (horizontalWeight != o.horizontalWeight) { - horizontalWeight = o.horizontalWeight; - changes |= LAYOUT_CHANGED; - } - if (verticalWeight != o.verticalWeight) { - verticalWeight = o.verticalWeight; - changes |= LAYOUT_CHANGED; - } - if (horizontalMargin != o.horizontalMargin) { - horizontalMargin = o.horizontalMargin; - changes |= LAYOUT_CHANGED; - } - if (verticalMargin != o.verticalMargin) { - verticalMargin = o.verticalMargin; - changes |= LAYOUT_CHANGED; - } - if (type != o.type) { - type = o.type; - changes |= TYPE_CHANGED; - } - if (memoryType != o.memoryType) { - memoryType = o.memoryType; - changes |= MEMORY_TYPE_CHANGED; - } - if (flags != o.flags) { - flags = o.flags; - changes |= FLAGS_CHANGED; - } - if (softInputMode != o.softInputMode) { - softInputMode = o.softInputMode; - changes |= SOFT_INPUT_MODE_CHANGED; - } - if (gravity != o.gravity) { - gravity = o.gravity; - changes |= LAYOUT_CHANGED; - } - if (horizontalMargin != o.horizontalMargin) { - horizontalMargin = o.horizontalMargin; - changes |= LAYOUT_CHANGED; - } - if (verticalMargin != o.verticalMargin) { - verticalMargin = o.verticalMargin; - changes |= LAYOUT_CHANGED; - } - if (format != o.format) { - format = o.format; - changes |= FORMAT_CHANGED; - } - if (windowAnimations != o.windowAnimations) { - windowAnimations = o.windowAnimations; - changes |= ANIMATION_CHANGED; - } - if (token == null) { - // NOTE: token only copied if the recipient doesn't - // already have one. - token = o.token; - } - if (packageName == null) { - // NOTE: packageName only copied if the recipient doesn't - // already have one. - packageName = o.packageName; - } - if (!mTitle.equals(o.mTitle)) { - mTitle = o.mTitle; - changes |= TITLE_CHANGED; - } - if (alpha != o.alpha) { - alpha = o.alpha; - changes |= ALPHA_CHANGED; - } - if (dimAmount != o.dimAmount) { - dimAmount = o.dimAmount; - changes |= DIM_AMOUNT_CHANGED; - } - if (screenBrightness != o.screenBrightness) { - screenBrightness = o.screenBrightness; - changes |= SCREEN_BRIGHTNESS_CHANGED; - } - - if (screenOrientation != o.screenOrientation) { - screenOrientation = o.screenOrientation; - changes |= SCREEN_ORIENTATION_CHANGED; - } - return changes; - } - - @Override - public String debug(String output) { - output += "Contents of " + this + ":"; - Log.d("Debug", output); - output = super.debug(""); - Log.d("Debug", output); - Log.d("Debug", ""); - Log.d("Debug", "WindowManager.LayoutParams={title=" + mTitle + "}"); - return ""; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(256); - sb.append("WM.LayoutParams{"); - sb.append("("); - sb.append(x); - sb.append(','); - sb.append(y); - sb.append(")("); - sb.append((width==FILL_PARENT?"fill":(width==WRAP_CONTENT?"wrap":width))); - sb.append('x'); - sb.append((height==FILL_PARENT?"fill":(height==WRAP_CONTENT?"wrap":height))); - sb.append(")"); - if (softInputMode != 0) { - sb.append(" sim=#"); - sb.append(Integer.toHexString(softInputMode)); - } - if (gravity != 0) { - sb.append(" gr=#"); - sb.append(Integer.toHexString(gravity)); - } - sb.append(" ty="); - sb.append(type); - sb.append(" fl=#"); - sb.append(Integer.toHexString(flags)); - sb.append(" fmt="); - sb.append(format); - if (windowAnimations != 0) { - sb.append(" wanim=0x"); - sb.append(Integer.toHexString(windowAnimations)); - } - if (screenOrientation != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { - sb.append(" or="); - sb.append(screenOrientation); - } - sb.append('}'); - return sb.toString(); - } - - private CharSequence mTitle = ""; - } -} diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java deleted file mode 100644 index 755d7b8..0000000 --- a/core/java/android/view/WindowManagerImpl.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.graphics.PixelFormat; -import android.os.IBinder; -import android.util.AndroidRuntimeException; -import android.util.Config; -import android.util.Log; -import android.view.WindowManager; -import android.view.inputmethod.InputMethodManager; - -final class WindowLeaked extends AndroidRuntimeException { - public WindowLeaked(String msg) { - super(msg); - } -} - -/** - * Low-level communication with the global system window manager. It implements - * the ViewManager interface, allowing you to add any View subclass as a - * top-level window on the screen. Additional window manager specific layout - * parameters are defined for control over how windows are displayed. - * It also implemens the WindowManager interface, allowing you to control the - * displays attached to the device. - * - * <p>Applications will not normally use WindowManager directly, instead relying - * on the higher-level facilities in {@link android.app.Activity} and - * {@link android.app.Dialog}. - * - * <p>Even for low-level window manager access, it is almost never correct to use - * this class. For example, {@link android.app.Activity#getWindowManager} - * provides a ViewManager for adding windows that are associated with that - * activity -- the window manager will not normally allow you to add arbitrary - * windows that are not associated with an activity. - * - * @hide - */ -public class WindowManagerImpl implements WindowManager { - /** - * The user is navigating with keys (not the touch screen), so - * navigational focus should be shown. - */ - public static final int RELAYOUT_IN_TOUCH_MODE = 0x1; - /** - * This is the first time the window is being drawn, - * so the client must call drawingFinished() when done - */ - public static final int RELAYOUT_FIRST_TIME = 0x2; - - public static final int ADD_FLAG_APP_VISIBLE = 0x2; - public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_IN_TOUCH_MODE; - - public static final int ADD_OKAY = 0; - public static final int ADD_BAD_APP_TOKEN = -1; - public static final int ADD_BAD_SUBWINDOW_TOKEN = -2; - public static final int ADD_NOT_APP_TOKEN = -3; - public static final int ADD_APP_EXITING = -4; - public static final int ADD_DUPLICATE_ADD = -5; - public static final int ADD_STARTING_NOT_NEEDED = -6; - public static final int ADD_MULTIPLE_SINGLETON = -7; - public static final int ADD_PERMISSION_DENIED = -8; - - public static WindowManagerImpl getDefault() - { - return mWindowManager; - } - - public void addView(View view) - { - addView(view, new WindowManager.LayoutParams( - WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.OPAQUE)); - } - - public void addView(View view, ViewGroup.LayoutParams params) - { - addView(view, params, false); - } - - public void addViewNesting(View view, ViewGroup.LayoutParams params) - { - addView(view, params, false); - } - - private void addView(View view, ViewGroup.LayoutParams params, boolean nest) - { - if (Config.LOGV) Log.v("WindowManager", "addView view=" + view); - - if (!(params instanceof WindowManager.LayoutParams)) { - throw new IllegalArgumentException( - "Params must be WindowManager.LayoutParams"); - } - - final WindowManager.LayoutParams wparams - = (WindowManager.LayoutParams)params; - - ViewRoot root; - View panelParentView = null; - - synchronized (this) { - // Here's an odd/questionable case: if someone tries to add a - // view multiple times, then we simply bump up a nesting count - // and they need to remove the view the corresponding number of - // times to have it actually removed from the window manager. - // This is useful specifically for the notification manager, - // which can continually add/remove the same view as a - // notification gets updated. - int index = findViewLocked(view, false); - if (index >= 0) { - if (!nest) { - throw new IllegalStateException("View " + view - + " has already been added to the window manager."); - } - root = mRoots[index]; - root.mAddNesting++; - // Update layout parameters. - view.setLayoutParams(wparams); - root.setLayoutParams(wparams, true); - return; - } - - // If this is a panel window, then find the window it is being - // attached to for future reference. - if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && - wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { - final int count = mViews != null ? mViews.length : 0; - for (int i=0; i<count; i++) { - if (mRoots[i].mWindow.asBinder() == wparams.token) { - panelParentView = mViews[i]; - } - } - } - - root = new ViewRoot(view.getContext()); - root.mAddNesting = 1; - - view.setLayoutParams(wparams); - - if (mViews == null) { - index = 1; - mViews = new View[1]; - mRoots = new ViewRoot[1]; - mParams = new WindowManager.LayoutParams[1]; - } else { - index = mViews.length + 1; - Object[] old = mViews; - mViews = new View[index]; - System.arraycopy(old, 0, mViews, 0, index-1); - old = mRoots; - mRoots = new ViewRoot[index]; - System.arraycopy(old, 0, mRoots, 0, index-1); - old = mParams; - mParams = new WindowManager.LayoutParams[index]; - System.arraycopy(old, 0, mParams, 0, index-1); - } - index--; - - mViews[index] = view; - mRoots[index] = root; - mParams[index] = wparams; - } - - // do this last because it fires off messages to start doing things - root.setView(view, wparams, panelParentView); - } - - public void updateViewLayout(View view, ViewGroup.LayoutParams params) { - if (!(params instanceof WindowManager.LayoutParams)) { - throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); - } - - final WindowManager.LayoutParams wparams - = (WindowManager.LayoutParams)params; - - view.setLayoutParams(wparams); - - synchronized (this) { - int index = findViewLocked(view, true); - ViewRoot root = mRoots[index]; - mParams[index] = wparams; - root.setLayoutParams(wparams, false); - } - } - - public void removeView(View view) { - synchronized (this) { - int index = findViewLocked(view, true); - View curView = removeViewLocked(index); - if (curView == view) { - return; - } - - throw new IllegalStateException("Calling with view " + view - + " but the ViewRoot is attached to " + curView); - } - } - - public void removeViewImmediate(View view) { - synchronized (this) { - int index = findViewLocked(view, true); - ViewRoot root = mRoots[index]; - View curView = root.getView(); - - root.mAddNesting = 0; - root.die(true); - finishRemoveViewLocked(curView, index); - if (curView == view) { - return; - } - - throw new IllegalStateException("Calling with view " + view - + " but the ViewRoot is attached to " + curView); - } - } - - View removeViewLocked(int index) { - ViewRoot root = mRoots[index]; - View view = root.getView(); - - // Don't really remove until we have matched all calls to add(). - root.mAddNesting--; - if (root.mAddNesting > 0) { - return view; - } - - InputMethodManager imm = InputMethodManager.getInstance(view.getContext()); - if (imm != null) { - imm.windowDismissed(mViews[index].getWindowToken()); - } - root.die(false); - finishRemoveViewLocked(view, index); - return view; - } - - void finishRemoveViewLocked(View view, int index) { - final int count = mViews.length; - - // remove it from the list - View[] tmpViews = new View[count-1]; - removeItem(tmpViews, mViews, index); - mViews = tmpViews; - - ViewRoot[] tmpRoots = new ViewRoot[count-1]; - removeItem(tmpRoots, mRoots, index); - mRoots = tmpRoots; - - WindowManager.LayoutParams[] tmpParams - = new WindowManager.LayoutParams[count-1]; - removeItem(tmpParams, mParams, index); - mParams = tmpParams; - - view.assignParent(null); - // func doesn't allow null... does it matter if we clear them? - //view.setLayoutParams(null); - } - - public void closeAll(IBinder token, String who, String what) { - synchronized (this) { - if (mViews == null) - return; - - int count = mViews.length; - //Log.i("foo", "Closing all windows of " + token); - for (int i=0; i<count; i++) { - //Log.i("foo", "@ " + i + " token " + mParams[i].token - // + " view " + mRoots[i].getView()); - if (token == null || mParams[i].token == token) { - ViewRoot root = mRoots[i]; - root.mAddNesting = 1; - - //Log.i("foo", "Force closing " + root); - if (who != null) { - WindowLeaked leak = new WindowLeaked( - what + " " + who + " has leaked window " - + root.getView() + " that was originally added here"); - leak.setStackTrace(root.getLocation().getStackTrace()); - Log.e("WindowManager", leak.getMessage(), leak); - } - - removeViewLocked(i); - i--; - count--; - } - } - } - } - - public WindowManager.LayoutParams getRootViewLayoutParameter(View view) { - ViewParent vp = view.getParent(); - while (vp != null && !(vp instanceof ViewRoot)) { - vp = vp.getParent(); - } - - if (vp == null) return null; - - ViewRoot vr = (ViewRoot)vp; - - int N = mRoots.length; - for (int i = 0; i < N; ++i) { - if (mRoots[i] == vr) { - return mParams[i]; - } - } - - return null; - } - - public void closeAll() { - closeAll(null, null, null); - } - - public Display getDefaultDisplay() { - return new Display(Display.DEFAULT_DISPLAY); - } - - private View[] mViews; - private ViewRoot[] mRoots; - private WindowManager.LayoutParams[] mParams; - - private static void removeItem(Object[] dst, Object[] src, int index) - { - if (dst.length > 0) { - if (index > 0) { - System.arraycopy(src, 0, dst, 0, index); - } - if (index < dst.length) { - System.arraycopy(src, index+1, dst, index, src.length-index-1); - } - } - } - - private int findViewLocked(View view, boolean required) - { - synchronized (this) { - final int count = mViews != null ? mViews.length : 0; - for (int i=0; i<count; i++) { - if (mViews[i] == view) { - return i; - } - } - if (required) { - throw new IllegalArgumentException( - "View not attached to window manager"); - } - return -1; - } - } - - private static WindowManagerImpl mWindowManager = new WindowManagerImpl(); -} diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java deleted file mode 100644 index 0f15b17..0000000 --- a/core/java/android/view/WindowManagerPolicy.java +++ /dev/null @@ -1,796 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view; - -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Rect; -import android.os.IBinder; -import android.os.LocalPowerManager; -import android.view.animation.Animation; - -/** - * This interface supplies all UI-specific behavior of the window manager. An - * instance of it is created by the window manager when it starts up, and allows - * customization of window layering, special window types, key dispatching, and - * layout. - * - * <p>Because this provides deep interaction with the system window manager, - * specific methods on this interface can be called from a variety of contexts - * with various restrictions on what they can do. These are encoded through - * a suffixes at the end of a method encoding the thread the method is called - * from and any locks that are held when it is being called; if no suffix - * is attached to a method, then it is not called with any locks and may be - * called from the main window manager thread or another thread calling into - * the window manager. - * - * <p>The current suffixes are: - * - * <dl> - * <dt> Ti <dd> Called from the input thread. This is the thread that - * collects pending input events and dispatches them to the appropriate window. - * It may block waiting for events to be processed, so that the input stream is - * properly serialized. - * <dt> Tq <dd> Called from the low-level input queue thread. This is the - * thread that reads events out of the raw input devices and places them - * into the global input queue that is read by the <var>Ti</var> thread. - * This thread should not block for a long period of time on anything but the - * key driver. - * <dt> Lw <dd> Called with the main window manager lock held. Because the - * window manager is a very low-level system service, there are few other - * system services you can call with this lock held. It is explicitly okay to - * make calls into the package manager and power manager; it is explicitly not - * okay to make calls into the activity manager. Note that - * {@link android.content.Context#checkPermission(String, int, int)} and - * variations require calling into the activity manager. - * <dt> Li <dd> Called with the input thread lock held. This lock can be - * acquired by the window manager while it holds the window lock, so this is - * even more restrictive than <var>Lw</var>. - * </dl> - * - * @hide - */ -public interface WindowManagerPolicy { - public final static int FLAG_WAKE = 0x00000001; - public final static int FLAG_WAKE_DROPPED = 0x00000002; - public final static int FLAG_SHIFT = 0x00000004; - public final static int FLAG_CAPS_LOCK = 0x00000008; - public final static int FLAG_ALT = 0x00000010; - public final static int FLAG_ALT_GR = 0x00000020; - public final static int FLAG_MENU = 0x00000040; - public final static int FLAG_LAUNCHER = 0x00000080; - - public final static int FLAG_WOKE_HERE = 0x10000000; - public final static int FLAG_BRIGHT_HERE = 0x20000000; - - public final static boolean WATCH_POINTER = false; - - // flags for interceptKeyTq - /** - * Pass this event to the user / app. To be returned from {@link #interceptKeyTq}. - */ - public final static int ACTION_PASS_TO_USER = 0x00000001; - - /** - * This key event should extend the user activity timeout and turn the lights on. - * To be returned from {@link #interceptKeyTq}. Do not return this and - * {@link #ACTION_GO_TO_SLEEP} or {@link #ACTION_PASS_TO_USER}. - */ - public final static int ACTION_POKE_USER_ACTIVITY = 0x00000002; - - /** - * This key event should put the device to sleep (and engage keyguard if necessary) - * To be returned from {@link #interceptKeyTq}. Do not return this and - * {@link #ACTION_POKE_USER_ACTIVITY} or {@link #ACTION_PASS_TO_USER}. - */ - public final static int ACTION_GO_TO_SLEEP = 0x00000004; - - /** - * Interface to the Window Manager state associated with a particular - * window. You can hold on to an instance of this interface from the call - * to prepareAddWindow() until removeWindow(). - */ - public interface WindowState { - /** - * Perform standard frame computation. The result can be obtained with - * getFrame() if so desired. Must be called with the window manager - * lock held. - * - * @param parentFrame The frame of the parent container this window - * is in, used for computing its basic position. - * @param displayFrame The frame of the overall display in which this - * window can appear, used for constraining the overall dimensions - * of the window. - * @param contentFrame The frame within the display in which we would - * like active content to appear. This will cause windows behind to - * be resized to match the given content frame. - * @param visibleFrame The frame within the display that the window - * is actually visible, used for computing its visible insets to be - * given to windows behind. - * This can be used as a hint for scrolling (avoiding resizing) - * the window to make certain that parts of its content - * are visible. - */ - public void computeFrameLw(Rect parentFrame, Rect displayFrame, - Rect contentFrame, Rect visibleFrame); - - /** - * Retrieve the current frame of the window that has been assigned by - * the window manager. Must be called with the window manager lock held. - * - * @return Rect The rectangle holding the window frame. - */ - public Rect getFrameLw(); - - /** - * Retrieve the current frame of the window that is actually shown. - * Must be called with the window manager lock held. - * - * @return Rect The rectangle holding the shown window frame. - */ - public Rect getShownFrameLw(); - - /** - * Retrieve the frame of the display that this window was last - * laid out in. Must be called with the - * window manager lock held. - * - * @return Rect The rectangle holding the display frame. - */ - public Rect getDisplayFrameLw(); - - /** - * Retrieve the frame of the content area that this window was last - * laid out in. This is the area in which the content of the window - * should be placed. It will be smaller than the display frame to - * account for screen decorations such as a status bar or soft - * keyboard. Must be called with the - * window manager lock held. - * - * @return Rect The rectangle holding the content frame. - */ - public Rect getContentFrameLw(); - - /** - * Retrieve the frame of the visible area that this window was last - * laid out in. This is the area of the screen in which the window - * will actually be fully visible. It will be smaller than the - * content frame to account for transient UI elements blocking it - * such as an input method's candidates UI. Must be called with the - * window manager lock held. - * - * @return Rect The rectangle holding the visible frame. - */ - public Rect getVisibleFrameLw(); - - /** - * Returns true if this window is waiting to receive its given - * internal insets from the client app, and so should not impact the - * layout of other windows. - */ - public boolean getGivenInsetsPendingLw(); - - /** - * Retrieve the insets given by this window's client for the content - * area of windows behind it. Must be called with the - * window manager lock held. - * - * @return Rect The left, top, right, and bottom insets, relative - * to the window's frame, of the actual contents. - */ - public Rect getGivenContentInsetsLw(); - - /** - * Retrieve the insets given by this window's client for the visible - * area of windows behind it. Must be called with the - * window manager lock held. - * - * @return Rect The left, top, right, and bottom insets, relative - * to the window's frame, of the actual visible area. - */ - public Rect getGivenVisibleInsetsLw(); - - /** - * Retrieve the current LayoutParams of the window. - * - * @return WindowManager.LayoutParams The window's internal LayoutParams - * instance. - */ - public WindowManager.LayoutParams getAttrs(); - - /** - * Get the layer at which this window's surface will be Z-ordered. - */ - public int getSurfaceLayer(); - - /** - * Return the token for the application (actually activity) that owns - * this window. May return null for system windows. - * - * @return An IApplicationToken identifying the owning activity. - */ - public IApplicationToken getAppToken(); - - /** - * Return true if, at any point, the application token associated with - * this window has actually displayed any windows. This is most useful - * with the "starting up" window to determine if any windows were - * displayed when it is closed. - * - * @return Returns true if one or more windows have been displayed, - * else false. - */ - public boolean hasAppShownWindows(); - - /** - * Return true if the application token has been asked to display an - * app starting icon as the application is starting up. - * - * @return Returns true if setAppStartingIcon() was called for this - * window's token. - */ - public boolean hasAppStartingIcon(); - - /** - * Return the Window that is being displayed as this window's - * application token is being started. - * - * @return Returns the currently displayed starting window, or null if - * it was not requested, has not yet been displayed, or has - * been removed. - */ - public WindowState getAppStartingWindow(); - - /** - * Is this window visible? It is not visible if there is no - * surface, or we are in the process of running an exit animation - * that will remove the surface. - */ - boolean isVisibleLw(); - - /** - * Is this window currently visible to the user on-screen? It is - * displayed either if it is visible or it is currently running an - * animation before no longer being visible. Must be called with the - * window manager lock held. - */ - boolean isDisplayedLw(); - - /** - * Returns true if the window is both full screen and opaque. Must be - * called with the window manager lock held. - * - * @param width The width of the screen - * @param height The height of the screen - * @param shownFrame If true, this is based on the actual shown frame of - * the window (taking into account animations); if - * false, this is based on the currently requested - * frame, which any current animation will be moving - * towards. - * @param onlyOpaque If true, this will only pass if the window is - * also opaque. - * @return Returns true if the window is both full screen and opaque - */ - public boolean fillsScreenLw(int width, int height, boolean shownFrame, - boolean onlyOpaque); - - /** - * Returns true if this window has been shown on screen at some time in - * the past. Must be called with the window manager lock held. - * - * @return boolean - */ - public boolean hasDrawnLw(); - - /** - * Can be called by the policy to force a window to be hidden, - * regardless of whether the client or window manager would like - * it shown. Must be called with the window manager lock held. - * Returns true if {@link #showLw} was last called for the window. - */ - public boolean hideLw(boolean doAnimation); - - /** - * Can be called to undo the effect of {@link #hideLw}, allowing a - * window to be shown as long as the window manager and client would - * also like it to be shown. Must be called with the window manager - * lock held. - * Returns true if {@link #hideLw} was last called for the window. - */ - public boolean showLw(boolean doAnimation); - } - - /** No transition happening. */ - public final int TRANSIT_NONE = 0; - /** Window has been added to the screen. */ - public final int TRANSIT_ENTER = 1; - /** Window has been removed from the screen. */ - public final int TRANSIT_EXIT = 2; - /** Window has been made visible. */ - public final int TRANSIT_SHOW = 3; - /** Window has been made invisible. */ - public final int TRANSIT_HIDE = 4; - /** The "application starting" preview window is no longer needed, and will - * animate away to show the real window. */ - public final int TRANSIT_PREVIEW_DONE = 5; - /** A window in a new activity is being opened on top of an existing one - * in the same task. */ - public final int TRANSIT_ACTIVITY_OPEN = 6; - /** The window in the top-most activity is being closed to reveal the - * previous activity in the same task. */ - public final int TRANSIT_ACTIVITY_CLOSE = 7; - /** A window in a new task is being opened on top of an existing one - * in another activity's task. */ - public final int TRANSIT_TASK_OPEN = 8; - /** A window in the top-most activity is being closed to reveal the - * previous activity in a different task. */ - public final int TRANSIT_TASK_CLOSE = 9; - /** A window in an existing task is being displayed on top of an existing one - * in another activity's task. */ - public final int TRANSIT_TASK_TO_FRONT = 10; - /** A window in an existing task is being put below all other tasks. */ - public final int TRANSIT_TASK_TO_BACK = 11; - - /** Screen turned off because of power button */ - public final int OFF_BECAUSE_OF_USER = 1; - /** Screen turned off because of timeout */ - public final int OFF_BECAUSE_OF_TIMEOUT = 2; - - /** - * Magic constant to {@link IWindowManager#setRotation} to not actually - * modify the rotation. - */ - public final int USE_LAST_ROTATION = -1000; - - /** - * Perform initialization of the policy. - * - * @param context The system context we are running in. - * @param powerManager - */ - public void init(Context context, IWindowManager windowManager, - LocalPowerManager powerManager); - - /** - * Check permissions when adding a window. - * - * @param attrs The window's LayoutParams. - * - * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed; - * else an error code, usually - * {@link WindowManagerImpl#ADD_PERMISSION_DENIED}, to abort the add. - */ - public int checkAddPermission(WindowManager.LayoutParams attrs); - - /** - * Sanitize the layout parameters coming from a client. Allows the policy - * to do things like ensure that windows of a specific type can't take - * input focus. - * - * @param attrs The window layout parameters to be modified. These values - * are modified in-place. - */ - public void adjustWindowParamsLw(WindowManager.LayoutParams attrs); - - /** - * After the window manager has computed the current configuration based - * on its knowledge of the display and input devices, it gives the policy - * a chance to adjust the information contained in it. If you want to - * leave it as-is, simply do nothing. - * - * <p>This method may be called by any thread in the window manager, but - * no internal locks in the window manager will be held. - * - * @param config The Configuration being computed, for you to change as - * desired. - */ - public void adjustConfigurationLw(Configuration config); - - /** - * Assign a window type to a layer. Allows you to control how different - * kinds of windows are ordered on-screen. - * - * @param type The type of window being assigned. - * - * @return int An arbitrary integer used to order windows, with lower - * numbers below higher ones. - */ - public int windowTypeToLayerLw(int type); - - /** - * Return how to Z-order sub-windows in relation to the window they are - * attached to. Return positive to have them ordered in front, negative for - * behind. - * - * @param type The sub-window type code. - * - * @return int Layer in relation to the attached window, where positive is - * above and negative is below. - */ - public int subWindowTypeToLayerLw(int type); - - /** - * Called when the system would like to show a UI to indicate that an - * application is starting. You can use this to add a - * APPLICATION_STARTING_TYPE window with the given appToken to the window - * manager (using the normal window manager APIs) that will be shown until - * the application displays its own window. This is called without the - * window manager locked so that you can call back into it. - * - * @param appToken Token of the application being started. - * @param packageName The name of the application package being started. - * @param theme Resource defining the application's overall visual theme. - * @param nonLocalizedLabel The default title label of the application if - * no data is found in the resource. - * @param labelRes The resource ID the application would like to use as its name. - * @param icon The resource ID the application would like to use as its icon. - * - * @return Optionally you can return the View that was used to create the - * window, for easy removal in removeStartingWindow. - * - * @see #removeStartingWindow - */ - public View addStartingWindow(IBinder appToken, String packageName, - int theme, CharSequence nonLocalizedLabel, - int labelRes, int icon); - - /** - * Called when the first window of an application has been displayed, while - * {@link #addStartingWindow} has created a temporary initial window for - * that application. You should at this point remove the window from the - * window manager. This is called without the window manager locked so - * that you can call back into it. - * - * <p>Note: due to the nature of these functions not being called with the - * window manager locked, you must be prepared for this function to be - * called multiple times and/or an initial time with a null View window - * even if you previously returned one. - * - * @param appToken Token of the application that has started. - * @param window Window View that was returned by createStartingWindow. - * - * @see #addStartingWindow - */ - public void removeStartingWindow(IBinder appToken, View window); - - /** - * Prepare for a window being added to the window manager. You can throw an - * exception here to prevent the window being added, or do whatever setup - * you need to keep track of the window. - * - * @param win The window being added. - * @param attrs The window's LayoutParams. - * - * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed, else an - * error code to abort the add. - */ - public int prepareAddWindowLw(WindowState win, - WindowManager.LayoutParams attrs); - - /** - * Called when a window is being removed from a window manager. Must not - * throw an exception -- clean up as much as possible. - * - * @param win The window being removed. - */ - public void removeWindowLw(WindowState win); - - /** - * Control the animation to run when a window's state changes. Return a - * non-0 number to force the animation to a specific resource ID, or 0 - * to use the default animation. - * - * @param win The window that is changing. - * @param transit What is happening to the window: {@link #TRANSIT_ENTER}, - * {@link #TRANSIT_EXIT}, {@link #TRANSIT_SHOW}, or - * {@link #TRANSIT_HIDE}. - * - * @return Resource ID of the actual animation to use, or 0 for none. - */ - public int selectAnimationLw(WindowState win, int transit); - - /** - * Called from the key queue thread before a key is dispatched to the - * input thread. - * - * <p>There are some actions that need to be handled here because they - * affect the power state of the device, for example, the power keys. - * Generally, it's best to keep as little as possible in the queue thread - * because it's the most fragile. - * - * @param event the raw input event as read from the driver - * @param screenIsOn true if the screen is already on - * @return The bitwise or of the {@link #ACTION_PASS_TO_USER}, - * {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags. - */ - public int interceptKeyTq(RawInputEvent event, boolean screenIsOn); - - /** - * Called from the input thread before a key is dispatched to a window. - * - * <p>Allows you to define - * behavior for keys that can not be overridden by applications or redirect - * key events to a different window. This method is called from the - * input thread, with no locks held. - * - * <p>Note that if you change the window a key is dispatched to, the new - * target window will receive the key event without having input focus. - * - * @param win The window that currently has focus. This is where the key - * event will normally go. - * @param code Key code. - * @param metaKeys TODO - * @param down Is this a key press (true) or release (false)? - * @param repeatCount Number of times a key down has repeated. - * @return Returns true if the policy consumed the event and it should - * not be further dispatched. - */ - public boolean interceptKeyTi(WindowState win, int code, - int metaKeys, boolean down, int repeatCount); - - /** - * Called when layout of the windows is about to start. - * - * @param displayWidth The current full width of the screen. - * @param displayHeight The current full height of the screen. - */ - public void beginLayoutLw(int displayWidth, int displayHeight); - - /** - * Called for each window attached to the window manager as layout is - * proceeding. The implementation of this function must take care of - * setting the window's frame, either here or in finishLayout(). - * - * @param win The window being positioned. - * @param attrs The LayoutParams of the window. - * @param attached For sub-windows, the window it is attached to; this - * window will already have had layoutWindow() called on it - * so you can use its Rect. Otherwise null. - */ - public void layoutWindowLw(WindowState win, - WindowManager.LayoutParams attrs, WindowState attached); - - - /** - * Return the insets for the areas covered by system windows. These values - * are computed on the most recent layout, so they are not guaranteed to - * be correct. - * - * @param attrs The LayoutParams of the window. - * @param contentInset The areas covered by system windows, expressed as positive insets - * - */ - public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset); - - /** - * Called when layout of the windows is finished. After this function has - * returned, all windows given to layoutWindow() <em>must</em> have had a - * frame assigned. - */ - public void finishLayoutLw(); - - /** - * Called when animation of the windows is about to start. - * - * @param displayWidth The current full width of the screen. - * @param displayHeight The current full height of the screen. - */ - public void beginAnimationLw(int displayWidth, int displayHeight); - - /** - * Called each time a window is animating. - * - * @param win The window being positioned. - * @param attrs The LayoutParams of the window. - */ - public void animatingWindowLw(WindowState win, - WindowManager.LayoutParams attrs); - - /** - * Called when animation of the windows is finished. If in this function you do - * something that may have modified the animation state of another window, - * be sure to return true in order to perform another animation frame. - * - * @return Return true if animation state may have changed (so that another - * frame of animation will be run). - */ - public boolean finishAnimationLw(); - - /** - * Called after the screen turns off. - * - * @param why {@link #OFF_BECAUSE_OF_USER} or - * {@link #OFF_BECAUSE_OF_TIMEOUT}. - */ - public void screenTurnedOff(int why); - - /** - * Called after the screen turns on. - */ - public void screenTurnedOn(); - - /** - * Perform any initial processing of a low-level input event before the - * window manager handles special keys and generates a high-level event - * that is dispatched to the application. - * - * @param event The input event that has occurred. - * - * @return Return true if you have consumed the event and do not want - * further processing to occur; return false for normal processing. - */ - public boolean preprocessInputEventTq(RawInputEvent event); - - /** - * Determine whether a given key code is used to cause an app switch - * to occur (most often the HOME key, also often ENDCALL). If you return - * true, then the system will go into a special key processing state - * where it drops any pending events that it cans and adjusts timeouts to - * try to get to this key as quickly as possible. - * - * <p>Note that this function is called from the low-level input queue - * thread, with either/or the window or input lock held; be very careful - * about what you do here. You absolutely should never acquire a lock - * that you would ever hold elsewhere while calling out into the window - * manager or view hierarchy. - * - * @param keycode The key that should be checked for performing an - * app switch before delivering to the application. - * - * @return Return true if this is an app switch key and special processing - * should happen; return false for normal processing. - */ - public boolean isAppSwitchKeyTqTiLwLi(int keycode); - - /** - * Determine whether a given key code is used for movement within a UI, - * and does not generally cause actions to be performed (normally the DPAD - * movement keys, NOT the DPAD center press key). This is called - * when {@link #isAppSwitchKeyTiLi} returns true to remove any pending events - * in the key queue that are not needed to switch applications. - * - * <p>Note that this function is called from the low-level input queue - * thread; be very careful about what you do here. - * - * @param keycode The key that is waiting to be delivered to the - * application. - * - * @return Return true if this is a purely navigation key and can be - * dropped without negative consequences; return false to keep it. - */ - public boolean isMovementKeyTi(int keycode); - - /** - * Given the current state of the world, should this relative movement - * wake up the device? - * - * @param device The device the movement came from. - * @param classes The input classes associated with the device. - * @param event The input event that occurred. - * @return - */ - public boolean isWakeRelMovementTq(int device, int classes, - RawInputEvent event); - - /** - * Given the current state of the world, should this absolute movement - * wake up the device? - * - * @param device The device the movement came from. - * @param classes The input classes associated with the device. - * @param event The input event that occurred. - * @return - */ - public boolean isWakeAbsMovementTq(int device, int classes, - RawInputEvent event); - - /** - * Tell the policy if anyone is requesting that keyguard not come on. - * - * @param enabled Whether keyguard can be on or not. does not actually - * turn it on, unless it was previously disabled with this function. - * - * @see android.app.KeyguardManager.KeyguardLock#disableKeyguard() - * @see android.app.KeyguardManager.KeyguardLock#reenableKeyguard() - */ - public void enableKeyguard(boolean enabled); - - /** - * Callback used by {@link WindowManagerPolicy#exitKeyguardSecurely} - */ - interface OnKeyguardExitResult { - void onKeyguardExitResult(boolean success); - } - - /** - * Tell the policy if anyone is requesting the keyguard to exit securely - * (this would be called after the keyguard was disabled) - * @param callback Callback to send the result back. - * @see android.app.KeyguardManager#exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult) - */ - void exitKeyguardSecurely(OnKeyguardExitResult callback); - - /** - * Return if keyguard is currently showing. - */ - public boolean keyguardIsShowingTq(); - - /** - * inKeyguardRestrictedKeyInputMode - * - * if keyguard screen is showing or in restricted key input mode (i.e. in - * keyguard password emergency screen). When in such mode, certain keys, - * such as the Home key and the right soft keys, don't work. - * - * @return true if in keyguard restricted input mode. - */ - public boolean inKeyguardRestrictedKeyInputMode(); - - /** - * Given an orientation constant - * ({@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE - * ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE} or - * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_PORTRAIT - * ActivityInfo.SCREEN_ORIENTATION_PORTRAIT}), return a surface - * rotation. - */ - public int rotationForOrientation(int orientation, int lastRotation, - boolean displayEnabled); - - /** - * Called when the system is mostly done booting to dentermine whether - * the system should go into safe mode. - */ - public boolean detectSafeMode(); - - /** - * Called when the system is mostly done booting. - */ - public void systemReady(); - - /** - * Called when we have finished booting and can now display the home - * screen to the user. This wilWl happen after systemReady(), and at - * this point the display is active. - */ - public void enableScreenAfterBoot(); - - /** - * Returns true if the user's cheek has been pressed against the phone. This is - * determined by comparing the event's size attribute with a threshold value. - * For example for a motion event like down or up or move, if the size exceeds - * the threshold, it is considered as cheek press. - * @param ev the motion event generated when the cheek is pressed - * against the phone - * @return Returns true if the user's cheek has been pressed against the phone - * screen resulting in an invalid motion event - */ - public boolean isCheekPressedAgainstScreen(MotionEvent ev); - - public void setCurrentOrientation(int newOrientation); - - /** - * Call from application to perform haptic feedback on its window. - */ - public boolean performHapticFeedback(WindowState win, int effectId, boolean always); - - /** - * Called when we have stopped keeping the screen on because a window - * requesting this is no longer visible. - */ - public void screenOnStopped(); -} diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java deleted file mode 100755 index 5877932..0000000 --- a/core/java/android/view/WindowOrientationListener.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2008 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.view; - -import android.content.Context; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; -import android.util.Config; -import android.util.Log; - -/** - * A special helper class used by the WindowManager - * for receiving notifications from the SensorManager when - * the orientation of the device has changed. - * @hide - */ -public abstract class WindowOrientationListener { - private static final String TAG = "WindowOrientationListener"; - private static final boolean DEBUG = false; - private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; - private int mOrientation = ORIENTATION_UNKNOWN; - private SensorManager mSensorManager; - private boolean mEnabled = false; - private int mRate; - private Sensor mSensor; - private SensorEventListener mSensorEventListener; - - /** - * Returned from onOrientationChanged when the device orientation cannot be determined - * (typically when the device is in a close to flat position). - * - * @see #onOrientationChanged - */ - public static final int ORIENTATION_UNKNOWN = -1; - /* - * Returned when the device is almost lying flat on a surface - */ - public static final int ORIENTATION_FLAT = -2; - - /** - * Creates a new WindowOrientationListener. - * - * @param context for the WindowOrientationListener. - */ - public WindowOrientationListener(Context context) { - this(context, SensorManager.SENSOR_DELAY_NORMAL); - } - - /** - * Creates a new WindowOrientationListener. - * - * @param context for the WindowOrientationListener. - * @param rate at which sensor events are processed (see also - * {@link android.hardware.SensorManager SensorManager}). Use the default - * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL - * SENSOR_DELAY_NORMAL} for simple screen orientation change detection. - */ - public WindowOrientationListener(Context context, int rate) { - mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); - mRate = rate; - mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - if (mSensor != null) { - // Create listener only if sensors do exist - mSensorEventListener = new SensorEventListenerImpl(); - } - } - - /** - * Enables the WindowOrientationListener so it will monitor the sensor and call - * {@link #onOrientationChanged} when the device orientation changes. - */ - public void enable() { - if (mSensor == null) { - Log.w(TAG, "Cannot detect sensors. Not enabled"); - return; - } - if (mEnabled == false) { - if (localLOGV) Log.d(TAG, "WindowOrientationListener enabled"); - mSensorManager.registerListener(mSensorEventListener, mSensor, mRate); - mEnabled = true; - } - } - - /** - * Disables the WindowOrientationListener. - */ - public void disable() { - if (mSensor == null) { - Log.w(TAG, "Cannot detect sensors. Invalid disable"); - return; - } - if (mEnabled == true) { - if (localLOGV) Log.d(TAG, "WindowOrientationListener disabled"); - mSensorManager.unregisterListener(mSensorEventListener); - mEnabled = false; - } - } - - class SensorEventListenerImpl implements SensorEventListener { - private static final int _DATA_X = 0; - private static final int _DATA_Y = 1; - private static final int _DATA_Z = 2; - - public void onSensorChanged(SensorEvent event) { - float[] values = event.values; - int orientation = ORIENTATION_UNKNOWN; - float X = values[_DATA_X]; - float Y = values[_DATA_Y]; - float Z = values[_DATA_Z]; - float OneEightyOverPi = 57.29577957855f; - float gravity = (float) Math.sqrt(X*X+Y*Y+Z*Z); - float zyangle = Math.abs((float)Math.asin(Z/gravity)*OneEightyOverPi); - // The device is considered flat if the angle is more than 75 - // if the angle is less than 40, its considered too flat to switch - // orientation. if the angle is between 40 - 75, the orientation is unknown - if (zyangle < 40) { - // Check orientation only if the phone is flat enough - // Don't trust the angle if the magnitude is small compared to the y value - float angle = (float)Math.atan2(Y, -X) * OneEightyOverPi; - orientation = 90 - (int)Math.round(angle); - // normalize to 0 - 359 range - while (orientation >= 360) { - orientation -= 360; - } - while (orientation < 0) { - orientation += 360; - } - } else if (zyangle >= 75){ - orientation = ORIENTATION_FLAT; - } - - if (orientation != mOrientation) { - mOrientation = orientation; - onOrientationChanged(orientation); - } - } - - public void onAccuracyChanged(Sensor sensor, int accuracy) { - - } - } - - /* - * Returns true if sensor is enabled and false otherwise - */ - public boolean canDetectOrientation() { - return mSensor != null; - } - - /** - * Called when the orientation of the device has changed. - * orientation parameter is in degrees, ranging from 0 to 359. - * orientation is 0 degrees when the device is oriented in its natural position, - * 90 degrees when its left side is at the top, 180 degrees when it is upside down, - * and 270 degrees when its right side is to the top. - * {@link #ORIENTATION_UNKNOWN} is returned when the device is close to flat - * and the orientation cannot be determined. - * - * @param orientation The new orientation of the device. - * - * @see #ORIENTATION_UNKNOWN - */ - abstract public void onOrientationChanged(int orientation); -} diff --git a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java deleted file mode 100644 index fdb6f9d..0000000 --- a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007 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.view.animation; - -import android.content.Context; -import android.util.AttributeSet; - -/** - * An interpolator where the rate of change starts and ends slowly but - * accelerates through the middle. - * - */ -public class AccelerateDecelerateInterpolator implements Interpolator { - public AccelerateDecelerateInterpolator() { - } - - public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) { - } - - public float getInterpolation(float input) { - return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; - } -} diff --git a/core/java/android/view/animation/AccelerateInterpolator.java b/core/java/android/view/animation/AccelerateInterpolator.java deleted file mode 100644 index b9e293f..0000000 --- a/core/java/android/view/animation/AccelerateInterpolator.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view.animation; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; - -/** - * An interpolator where the rate of change starts out slowly and - * and then accelerates. - * - */ -public class AccelerateInterpolator implements Interpolator { - public AccelerateInterpolator() { - } - - /** - * Constructor - * - * @param factor Degree to which the animation should be eased. Seting - * factor to 1.0f produces a y=x^2 parabola. Increasing factor above - * 1.0f exaggerates the ease-in effect (i.e., it starts even - * slower and ends evens faster) - */ - public AccelerateInterpolator(float factor) { - mFactor = factor; - } - - public AccelerateInterpolator(Context context, AttributeSet attrs) { - TypedArray a = - context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AccelerateInterpolator); - - mFactor = a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor, 1.0f); - - a.recycle(); - } - - public float getInterpolation(float input) { - if (mFactor == 1.0f) { - return (float)(input * input); - } else { - return (float)Math.pow(input, 2 * mFactor); - } - } - - private float mFactor = 1.0f; -} diff --git a/core/java/android/view/animation/AlphaAnimation.java b/core/java/android/view/animation/AlphaAnimation.java deleted file mode 100644 index 16a10a4..0000000 --- a/core/java/android/view/animation/AlphaAnimation.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view.animation; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; - -/** - * An animation that controls the alpha level of an object. - * Useful for fading things in and out. This animation ends up - * changing the alpha property of a {@link Transformation} - * - */ -public class AlphaAnimation extends Animation { - private float mFromAlpha; - private float mToAlpha; - - /** - * Constructor used whan an AlphaAnimation is loaded from a resource. - * - * @param context Application context to use - * @param attrs Attribute set from which to read values - */ - public AlphaAnimation(Context context, AttributeSet attrs) { - super(context, attrs); - - TypedArray a = - context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AlphaAnimation); - - mFromAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_fromAlpha, 1.0f); - mToAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_toAlpha, 1.0f); - - a.recycle(); - } - - /** - * Constructor to use when building an AlphaAnimation from code - * - * @param fromAlpha Starting alpha value for the animation, where 1.0 means - * fully opaque and 0.0 means fully transparent. - * @param toAlpha Ending alpha value for the animation. - */ - public AlphaAnimation(float fromAlpha, float toAlpha) { - mFromAlpha = fromAlpha; - mToAlpha = toAlpha; - } - - /** - * Changes the alpha property of the supplied {@link Transformation} - */ - @Override - protected void applyTransformation(float interpolatedTime, Transformation t) { - final float alpha = mFromAlpha; - t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime)); - } - - @Override - public boolean willChangeTransformationMatrix() { - return false; - } - - @Override - public boolean willChangeBounds() { - return false; - } -} diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java deleted file mode 100644 index b9c8ec3..0000000 --- a/core/java/android/view/animation/Animation.java +++ /dev/null @@ -1,925 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view.animation; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.graphics.RectF; - -/** - * Abstraction for an Animation that can be applied to Views, Surfaces, or - * other objects. See the {@link android.view.animation animation package - * description file}. - */ -public abstract class Animation implements Cloneable { - /** - * Repeat the animation indefinitely. - */ - public static final int INFINITE = -1; - - /** - * When the animation reaches the end and the repeat count is INFINTE_REPEAT - * or a positive value, the animation restarts from the beginning. - */ - public static final int RESTART = 1; - - /** - * When the animation reaches the end and the repeat count is INFINTE_REPEAT - * or a positive value, the animation plays backward (and then forward again). - */ - public static final int REVERSE = 2; - - /** - * Can be used as the start time to indicate the start time should be the current - * time when {@link #getTransformation(long, Transformation)} is invoked for the - * first animation frame. This can is useful for short animations. - */ - public static final int START_ON_FIRST_FRAME = -1; - - /** - * The specified dimension is an absolute number of pixels. - */ - public static final int ABSOLUTE = 0; - - /** - * The specified dimension holds a float and should be multiplied by the - * height or width of the object being animated. - */ - public static final int RELATIVE_TO_SELF = 1; - - /** - * The specified dimension holds a float and should be multiplied by the - * height or width of the parent of the object being animated. - */ - public static final int RELATIVE_TO_PARENT = 2; - - /** - * Requests that the content being animated be kept in its current Z - * order. - */ - public static final int ZORDER_NORMAL = 0; - - /** - * Requests that the content being animated be forced on top of all other - * content for the duration of the animation. - */ - public static final int ZORDER_TOP = 1; - - /** - * Requests that the content being animated be forced under all other - * content for the duration of the animation. - */ - public static final int ZORDER_BOTTOM = -1; - - /** - * Set by {@link #getTransformation(long, Transformation)} when the animation ends. - */ - boolean mEnded = false; - - /** - * Set by {@link #getTransformation(long, Transformation)} when the animation starts. - */ - boolean mStarted = false; - - /** - * Set by {@link #getTransformation(long, Transformation)} when the animation repeats - * in REVERSE mode. - */ - boolean mCycleFlip = false; - - /** - * This value must be set to true by {@link #initialize(int, int, int, int)}. It - * indicates the animation was successfully initialized and can be played. - */ - boolean mInitialized = false; - - /** - * Indicates whether the animation transformation should be applied before the - * animation starts. - */ - boolean mFillBefore = true; - - /** - * Indicates whether the animation transformation should be applied after the - * animation ends. - */ - boolean mFillAfter = false; - - /** - * Indicates whether fillAfter should be taken into account. - */ - boolean mFillEnabled = false; - - /** - * The time in milliseconds at which the animation must start; - */ - long mStartTime = -1; - - /** - * The delay in milliseconds after which the animation must start. When the - * start offset is > 0, the start time of the animation is startTime + startOffset. - */ - long mStartOffset; - - /** - * The duration of one animation cycle in milliseconds. - */ - long mDuration; - - /** - * The number of times the animation must repeat. By default, an animation repeats - * indefinitely. - */ - int mRepeatCount = 0; - - /** - * Indicates how many times the animation was repeated. - */ - int mRepeated = 0; - - /** - * The behavior of the animation when it repeats. The repeat mode is either - * {@link #RESTART} or {@link #REVERSE}. - * - */ - int mRepeatMode = RESTART; - - /** - * The interpolator used by the animation to smooth the movement. - */ - Interpolator mInterpolator; - - /** - * The animation listener to be notified when the animation starts, ends or repeats. - */ - AnimationListener mListener; - - /** - * Desired Z order mode during animation. - */ - private int mZAdjustment; - - private boolean mMore = true; - private boolean mOneMoreTime = true; - - RectF mPreviousRegion = new RectF(); - RectF mRegion = new RectF(); - Transformation mTransformation = new Transformation(); - Transformation mPreviousTransformation = new Transformation(); - - /** - * Creates a new animation with a duration of 0ms, the default interpolator, with - * fillBefore set to true and fillAfter set to false - */ - public Animation() { - ensureInterpolator(); - } - - /** - * Creates a new animation whose parameters come from the specified context and - * attributes set. - * - * @param context the application environment - * @param attrs the set of attributes holding the animation parameters - */ - public Animation(Context context, AttributeSet attrs) { - TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Animation); - - setDuration((long) a.getInt(com.android.internal.R.styleable.Animation_duration, 0)); - setStartOffset((long) a.getInt(com.android.internal.R.styleable.Animation_startOffset, 0)); - - setFillEnabled(a.getBoolean(com.android.internal.R.styleable.Animation_fillEnabled, mFillEnabled)); - setFillBefore(a.getBoolean(com.android.internal.R.styleable.Animation_fillBefore, mFillBefore)); - setFillAfter(a.getBoolean(com.android.internal.R.styleable.Animation_fillAfter, mFillAfter)); - - final int resID = a.getResourceId(com.android.internal.R.styleable.Animation_interpolator, 0); - if (resID > 0) { - setInterpolator(context, resID); - } - - setRepeatCount(a.getInt(com.android.internal.R.styleable.Animation_repeatCount, mRepeatCount)); - setRepeatMode(a.getInt(com.android.internal.R.styleable.Animation_repeatMode, RESTART)); - - setZAdjustment(a.getInt(com.android.internal.R.styleable.Animation_zAdjustment, ZORDER_NORMAL)); - - ensureInterpolator(); - - a.recycle(); - } - - @Override - protected Animation clone() throws CloneNotSupportedException { - final Animation animation = (Animation) super.clone(); - animation.mPreviousRegion = new RectF(); - animation.mRegion = new RectF(); - animation.mTransformation = new Transformation(); - animation.mPreviousTransformation = new Transformation(); - return animation; - } - - /** - * Reset the initialization state of this animation. - * - * @see #initialize(int, int, int, int) - */ - public void reset() { - mPreviousRegion.setEmpty(); - mPreviousTransformation.clear(); - mInitialized = false; - mCycleFlip = false; - mRepeated = 0; - mMore = true; - mOneMoreTime = true; - } - - /** - * Whether or not the animation has been initialized. - * - * @return Has this animation been initialized. - * @see #initialize(int, int, int, int) - */ - public boolean isInitialized() { - return mInitialized; - } - - /** - * Initialize this animation with the dimensions of the object being - * animated as well as the objects parents. (This is to support animation - * sizes being specifed relative to these dimensions.) - * - * <p>Objects that interpret a Animations should call this method when - * the sizes of the object being animated and its parent are known, and - * before calling {@link #getTransformation}. - * - * - * @param width Width of the object being animated - * @param height Height of the object being animated - * @param parentWidth Width of the animated object's parent - * @param parentHeight Height of the animated object's parent - */ - public void initialize(int width, int height, int parentWidth, int parentHeight) { - reset(); - mInitialized = true; - } - - /** - * Sets the acceleration curve for this animation. The interpolator is loaded as - * a resource from the specified context. - * - * @param context The application environment - * @param resID The resource identifier of the interpolator to load - * @attr ref android.R.styleable#Animation_interpolator - */ - public void setInterpolator(Context context, int resID) { - setInterpolator(AnimationUtils.loadInterpolator(context, resID)); - } - - /** - * Sets the acceleration curve for this animation. Defaults to a linear - * interpolation. - * - * @param i The interpolator which defines the acceleration curve - * @attr ref android.R.styleable#Animation_interpolator - */ - public void setInterpolator(Interpolator i) { - mInterpolator = i; - } - - /** - * When this animation should start relative to the start time. This is most - * useful when composing complex animations using an {@link AnimationSet } - * where some of the animations components start at different times. - * - * @param startOffset When this Animation should start, in milliseconds from - * the start time of the root AnimationSet. - * @attr ref android.R.styleable#Animation_startOffset - */ - public void setStartOffset(long startOffset) { - mStartOffset = startOffset; - } - - /** - * How long this animation should last. The duration cannot be negative. - * - * @param durationMillis Duration in milliseconds - * - * @throw java.lang.IllegalArgumentException if the duration is < 0 - * - * @attr ref android.R.styleable#Animation_duration - */ - public void setDuration(long durationMillis) { - if (durationMillis < 0) { - throw new IllegalArgumentException("Animation duration cannot be negative"); - } - mDuration = durationMillis; - } - - /** - * Ensure that the duration that this animation will run is not longer - * than <var>durationMillis</var>. In addition to adjusting the duration - * itself, this ensures that the repeat count also will not make it run - * longer than the given time. - * - * @param durationMillis The maximum duration the animation is allowed - * to run. - */ - public void restrictDuration(long durationMillis) { - if (mStartOffset > durationMillis) { - mStartOffset = durationMillis; - mDuration = 0; - mRepeatCount = 0; - return; - } - - long dur = mDuration + mStartOffset; - if (dur > durationMillis) { - mDuration = dur = durationMillis-mStartOffset; - } - if (mRepeatCount < 0 || mRepeatCount > durationMillis - || (dur*mRepeatCount) > durationMillis) { - mRepeatCount = (int)(durationMillis/dur); - } - } - - /** - * How much to scale the duration by. - * - * @param scale The amount to scale the duration. - */ - public void scaleCurrentDuration(float scale) { - mDuration = (long) (mDuration * scale); - } - - /** - * When this animation should start. When the start time is set to - * {@link #START_ON_FIRST_FRAME}, the animation will start the first time - * {@link #getTransformation(long, Transformation)} is invoked. The time passed - * to this method should be obtained by calling - * {@link AnimationUtils#currentAnimationTimeMillis()} instead of - * {@link System#currentTimeMillis()}. - * - * @param startTimeMillis the start time in milliseconds - */ - public void setStartTime(long startTimeMillis) { - mStartTime = startTimeMillis; - mStarted = mEnded = false; - mCycleFlip = false; - mRepeated = 0; - mMore = true; - } - - /** - * Convenience method to start the animation the first time - * {@link #getTransformation(long, Transformation)} is invoked. - */ - public void start() { - setStartTime(-1); - } - - /** - * Convenience method to start the animation at the current time in - * milliseconds. - */ - public void startNow() { - setStartTime(AnimationUtils.currentAnimationTimeMillis()); - } - - /** - * Defines what this animation should do when it reaches the end. This - * setting is applied only when the repeat count is either greater than - * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}. - * - * @param repeatMode {@link #RESTART} or {@link #REVERSE} - * @attr ref android.R.styleable#Animation_repeatMode - */ - public void setRepeatMode(int repeatMode) { - mRepeatMode = repeatMode; - } - - /** - * Sets how many times the animation should be repeated. If the repeat - * count is 0, the animation is never repeated. If the repeat count is - * greater than 0 or {@link #INFINITE}, the repeat mode will be taken - * into account. The repeat count if 0 by default. - * - * @param repeatCount the number of times the animation should be repeated - * @attr ref android.R.styleable#Animation_repeatCount - */ - public void setRepeatCount(int repeatCount) { - if (repeatCount < 0) { - repeatCount = INFINITE; - } - mRepeatCount = repeatCount; - } - - /** - * If fillEnabled is true, this animation will apply fillBefore and fillAfter. - * - * @return true if the animation will take fillBefore and fillAfter into account - * @attr ref android.R.styleable#Animation_fillEnabled - */ - public boolean isFillEnabled() { - return mFillEnabled; - } - - /** - * If fillEnabled is true, the animation will apply the value of fillBefore and - * fillAfter. Otherwise, fillBefore and fillAfter are ignored and the animation - * transformation is always applied. - * - * @param fillEnabled true if the animation should take fillBefore and fillAfter into account - * @attr ref android.R.styleable#Animation_fillEnabled - * - * @see #setFillBefore(boolean) - * @see #setFillAfter(boolean) - */ - public void setFillEnabled(boolean fillEnabled) { - mFillEnabled = fillEnabled; - } - - /** - * If fillBefore is true, this animation will apply its transformation - * before the start time of the animation. Defaults to true if not set. - * Note that this applies when using an {@link - * android.view.animation.AnimationSet AnimationSet} to chain - * animations. The transformation is not applied before the AnimationSet - * itself starts. - * - * @param fillBefore true if the animation should apply its transformation before it starts - * @attr ref android.R.styleable#Animation_fillBefore - * - * @see #setFillEnabled(boolean) - */ - public void setFillBefore(boolean fillBefore) { - mFillBefore = fillBefore; - } - - /** - * If fillAfter is true, the transformation that this animation performed - * will persist when it is finished. Defaults to false if not set. - * Note that this applies when using an {@link - * android.view.animation.AnimationSet AnimationSet} to chain - * animations. The transformation is not applied before the AnimationSet - * itself starts. - * - * @param fillAfter true if the animation should apply its transformation after it ends - * @attr ref android.R.styleable#Animation_fillAfter - * - * @see #setFillEnabled(boolean) - */ - public void setFillAfter(boolean fillAfter) { - mFillAfter = fillAfter; - } - - /** - * Set the Z ordering mode to use while running the animation. - * - * @param zAdjustment The desired mode, one of {@link #ZORDER_NORMAL}, - * {@link #ZORDER_TOP}, or {@link #ZORDER_BOTTOM}. - * @attr ref android.R.styleable#Animation_zAdjustment - */ - public void setZAdjustment(int zAdjustment) { - mZAdjustment = zAdjustment; - } - - /** - * Gets the acceleration curve type for this animation. - * - * @return the {@link Interpolator} associated to this animation - * @attr ref android.R.styleable#Animation_interpolator - */ - public Interpolator getInterpolator() { - return mInterpolator; - } - - /** - * When this animation should start. If the animation has not startet yet, - * this method might return {@link #START_ON_FIRST_FRAME}. - * - * @return the time in milliseconds when the animation should start or - * {@link #START_ON_FIRST_FRAME} - */ - public long getStartTime() { - return mStartTime; - } - - /** - * How long this animation should last - * - * @return the duration in milliseconds of the animation - * @attr ref android.R.styleable#Animation_duration - */ - public long getDuration() { - return mDuration; - } - - /** - * When this animation should start, relative to StartTime - * - * @return the start offset in milliseconds - * @attr ref android.R.styleable#Animation_startOffset - */ - public long getStartOffset() { - return mStartOffset; - } - - /** - * Defines what this animation should do when it reaches the end. - * - * @return either one of {@link #REVERSE} or {@link #RESTART} - * @attr ref android.R.styleable#Animation_repeatMode - */ - public int getRepeatMode() { - return mRepeatMode; - } - - /** - * Defines how many times the animation should repeat. The default value - * is 0. - * - * @return the number of times the animation should repeat, or {@link #INFINITE} - * @attr ref android.R.styleable#Animation_repeatCount - */ - public int getRepeatCount() { - return mRepeatCount; - } - - /** - * If fillBefore is true, this animation will apply its transformation - * before the start time of the animation. - * - * @return true if the animation applies its transformation before it starts - * @attr ref android.R.styleable#Animation_fillBefore - */ - public boolean getFillBefore() { - return mFillBefore; - } - - /** - * If fillAfter is true, this animation will apply its transformation - * after the end time of the animation. - * - * @return true if the animation applies its transformation after it ends - * @attr ref android.R.styleable#Animation_fillAfter - */ - public boolean getFillAfter() { - return mFillAfter; - } - - /** - * Returns the Z ordering mode to use while running the animation as - * previously set by {@link #setZAdjustment}. - * - * @return Returns one of {@link #ZORDER_NORMAL}, - * {@link #ZORDER_TOP}, or {@link #ZORDER_BOTTOM}. - * @attr ref android.R.styleable#Animation_zAdjustment - */ - public int getZAdjustment() { - return mZAdjustment; - } - - /** - * <p>Indicates whether or not this animation will affect the transformation - * matrix. For instance, a fade animation will not affect the matrix whereas - * a scale animation will.</p> - * - * @return true if this animation will change the transformation matrix - */ - public boolean willChangeTransformationMatrix() { - // assume we will change the matrix - return true; - } - - /** - * <p>Indicates whether or not this animation will affect the bounds of the - * animated view. For instance, a fade animation will not affect the bounds - * whereas a 200% scale animation will.</p> - * - * @return true if this animation will change the view's bounds - */ - public boolean willChangeBounds() { - // assume we will change the bounds - return true; - } - - /** - * <p>Binds an animation listener to this animation. The animation listener - * is notified of animation events such as the end of the animation or the - * repetition of the animation.</p> - * - * @param listener the animation listener to be notified - */ - public void setAnimationListener(AnimationListener listener) { - mListener = listener; - } - - /** - * Gurantees that this animation has an interpolator. Will use - * a AccelerateDecelerateInterpolator is nothing else was specified. - */ - protected void ensureInterpolator() { - if (mInterpolator == null) { - mInterpolator = new AccelerateDecelerateInterpolator(); - } - } - - /** - * Compute a hint at how long the entire animation may last, in milliseconds. - * Animations can be written to cause themselves to run for a different - * duration than what is computed here, but generally this should be - * accurate. - */ - public long computeDurationHint() { - return (getStartOffset() + getDuration()) * (getRepeatCount() + 1); - } - - /** - * Gets the transformation to apply at a specified point in time. Implementations of this - * method should always replace the specified Transformation or document they are doing - * otherwise. - * - * @param currentTime Where we are in the animation. This is wall clock time. - * @param outTransformation A tranformation object that is provided by the - * caller and will be filled in by the animation. - * @return True if the animation is still running - */ - public boolean getTransformation(long currentTime, Transformation outTransformation) { - if (mStartTime == -1) { - mStartTime = currentTime; - } - - final long startOffset = getStartOffset(); - final long duration = mDuration; - float normalizedTime; - if (duration != 0) { - normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) / - (float) duration; - } else { - // time is a step-change with a zero duration - normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f; - } - - final boolean expired = normalizedTime >= 1.0f; - mMore = !expired; - - if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f); - - if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) { - if (!mStarted) { - if (mListener != null) { - mListener.onAnimationStart(this); - } - mStarted = true; - } - - if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f); - - if (mCycleFlip) { - normalizedTime = 1.0f - normalizedTime; - } - - final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime); - applyTransformation(interpolatedTime, outTransformation); - } - - if (expired) { - if (mRepeatCount == mRepeated) { - if (!mEnded) { - if (mListener != null) { - mListener.onAnimationEnd(this); - } - mEnded = true; - } - } else { - if (mRepeatCount > 0) { - mRepeated++; - } - - if (mRepeatMode == REVERSE) { - mCycleFlip = !mCycleFlip; - } - - mStartTime = -1; - mMore = true; - - if (mListener != null) { - mListener.onAnimationRepeat(this); - } - } - } - - if (!mMore && mOneMoreTime) { - mOneMoreTime = false; - return true; - } - - return mMore; - } - - /** - * <p>Indicates whether this animation has started or not.</p> - * - * @return true if the animation has started, false otherwise - */ - public boolean hasStarted() { - return mStarted; - } - - /** - * <p>Indicates whether this animation has ended or not.</p> - * - * @return true if the animation has ended, false otherwise - */ - public boolean hasEnded() { - return mEnded; - } - - /** - * Helper for getTransformation. Subclasses should implement this to apply - * their transforms given an interpolation value. Implementations of this - * method should always replace the specified Transformation or document - * they are doing otherwise. - * - * @param interpolatedTime The value of the normalized time (0.0 to 1.0) - * after it has been run through the interpolation function. - * @param t The Transofrmation object to fill in with the current - * transforms. - */ - protected void applyTransformation(float interpolatedTime, Transformation t) { - } - - /** - * Convert the information in the description of a size to an actual - * dimension - * - * @param type One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or - * Animation.RELATIVE_TO_PARENT. - * @param value The dimension associated with the type parameter - * @param size The size of the object being animated - * @param parentSize The size of the parent of the object being animated - * @return The dimension to use for the animation - */ - protected float resolveSize(int type, float value, int size, int parentSize) { - switch (type) { - case ABSOLUTE: - return value; - case RELATIVE_TO_SELF: - return size * value; - case RELATIVE_TO_PARENT: - return parentSize * value; - default: - return value; - } - } - - /** - * @param left - * @param top - * @param right - * @param bottom - * @param invalidate - * @param transformation - * - * @hide - */ - public void getInvalidateRegion(int left, int top, int right, int bottom, - RectF invalidate, Transformation transformation) { - - final RectF tempRegion = mRegion; - final RectF previousRegion = mPreviousRegion; - - invalidate.set(left, top, right, bottom); - transformation.getMatrix().mapRect(invalidate); - tempRegion.set(invalidate); - invalidate.union(previousRegion); - - previousRegion.set(tempRegion); - - final Transformation tempTransformation = mTransformation; - final Transformation previousTransformation = mPreviousTransformation; - - tempTransformation.set(transformation); - transformation.set(previousTransformation); - previousTransformation.set(tempTransformation); - } - - /** - * @param left - * @param top - * @param right - * @param bottom - * - * @hide - */ - public void initializeInvalidateRegion(int left, int top, int right, int bottom) { - final RectF region = mPreviousRegion; - region.set(left, top, right, bottom); - if (mFillBefore) { - final Transformation previousTransformation = mPreviousTransformation; - applyTransformation(0.0f, previousTransformation); - } - } - - /** - * Utility class to parse a string description of a size. - */ - protected static class Description { - /** - * One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or - * Animation.RELATIVE_TO_PARENT. - */ - public int type; - - /** - * The absolute or relative dimension for this Description. - */ - public float value; - - /** - * Size descriptions can appear inthree forms: - * <ol> - * <li>An absolute size. This is represented by a number.</li> - * <li>A size relative to the size of the object being animated. This - * is represented by a number followed by "%".</li> * - * <li>A size relative to the size of the parent of object being - * animated. This is represented by a number followed by "%p".</li> - * </ol> - * @param value The typed value to parse - * @return The parsed version of the description - */ - static Description parseValue(TypedValue value) { - Description d = new Description(); - if (value == null) { - d.type = ABSOLUTE; - d.value = 0; - } else { - if (value.type == TypedValue.TYPE_FRACTION) { - d.type = (value.data & TypedValue.COMPLEX_UNIT_MASK) == - TypedValue.COMPLEX_UNIT_FRACTION_PARENT ? - RELATIVE_TO_PARENT : RELATIVE_TO_SELF; - d.value = TypedValue.complexToFloat(value.data); - return d; - } else if (value.type == TypedValue.TYPE_FLOAT) { - d.type = ABSOLUTE; - d.value = value.getFloat(); - return d; - } else if (value.type >= TypedValue.TYPE_FIRST_INT && - value.type <= TypedValue.TYPE_LAST_INT) { - d.type = ABSOLUTE; - d.value = value.data; - return d; - } - } - - d.type = ABSOLUTE; - d.value = 0.0f; - - return d; - } - } - - /** - * <p>An animation listener receives notifications from an animation. - * Notifications indicate animation related events, such as the end or the - * repetition of the animation.</p> - */ - public static interface AnimationListener { - /** - * <p>Notifies the start of the animation.</p> - * - * @param animation The started animation. - */ - void onAnimationStart(Animation animation); - - /** - * <p>Notifies the end of the animation. This callback is not invoked - * for animations with repeat count set to INFINITE.</p> - * - * @param animation The animation which reached its end. - */ - void onAnimationEnd(Animation animation); - - /** - * <p>Notifies the repetition of the animation.</p> - * - * @param animation The animation which was repeated. - */ - void onAnimationRepeat(Animation animation); - } -} diff --git a/core/java/android/view/animation/AnimationSet.java b/core/java/android/view/animation/AnimationSet.java deleted file mode 100644 index 7b56f00..0000000 --- a/core/java/android/view/animation/AnimationSet.java +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view.animation; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.graphics.RectF; - -import java.util.ArrayList; -import java.util.List; - -/** - * Represents a group of Animations that should be played together. - * The transformation of each individual animation are composed - * together into a single transform. - * If AnimationSet sets any properties that its children also set - * (for example, duration or fillBefore), the values of AnimationSet - * override the child values. - */ -public class AnimationSet extends Animation { - private static final int PROPERTY_FILL_AFTER_MASK = 0x1; - private static final int PROPERTY_FILL_BEFORE_MASK = 0x2; - private static final int PROPERTY_REPEAT_MODE_MASK = 0x4; - private static final int PROPERTY_START_OFFSET_MASK = 0x8; - private static final int PROPERTY_SHARE_INTERPOLATOR_MASK = 0x10; - private static final int PROPERTY_DURATION_MASK = 0x20; - private static final int PROPERTY_MORPH_MATRIX_MASK = 0x40; - private static final int PROPERTY_CHANGE_BOUNDS_MASK = 0x80; - - private int mFlags = 0; - - private ArrayList<Animation> mAnimations = new ArrayList<Animation>(); - - private Transformation mTempTransformation = new Transformation(); - - private long mLastEnd; - - private long[] mStoredOffsets; - - /** - * Constructor used whan an AnimationSet is loaded from a resource. - * - * @param context Application context to use - * @param attrs Attribute set from which to read values - */ - public AnimationSet(Context context, AttributeSet attrs) { - super(context, attrs); - - TypedArray a = - context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AnimationSet); - - setFlag(PROPERTY_SHARE_INTERPOLATOR_MASK, - a.getBoolean(com.android.internal.R.styleable.AnimationSet_shareInterpolator, true)); - init(); - - a.recycle(); - } - - - /** - * Constructor to use when building an AnimationSet from code - * - * @param shareInterpolator Pass true if all of the animations in this set - * should use the interpolator assocciated with this AnimationSet. - * Pass false if each animation should use its own interpolator. - */ - public AnimationSet(boolean shareInterpolator) { - setFlag(PROPERTY_SHARE_INTERPOLATOR_MASK, shareInterpolator); - init(); - } - - @Override - protected AnimationSet clone() throws CloneNotSupportedException { - final AnimationSet animation = (AnimationSet) super.clone(); - animation.mTempTransformation = new Transformation(); - animation.mAnimations = new ArrayList<Animation>(); - - final int count = mAnimations.size(); - final ArrayList<Animation> animations = mAnimations; - - for (int i = 0; i < count; i++) { - animation.mAnimations.add(animations.get(i).clone()); - } - - return animation; - } - - private void setFlag(int mask, boolean value) { - if (value) { - mFlags |= mask; - } else { - mFlags &= ~mask; - } - } - - private void init() { - mStartTime = 0; - mDuration = 0; - } - - @Override - public void setFillAfter(boolean fillAfter) { - mFlags |= PROPERTY_FILL_AFTER_MASK; - super.setFillAfter(fillAfter); - } - - @Override - public void setFillBefore(boolean fillBefore) { - mFlags |= PROPERTY_FILL_BEFORE_MASK; - super.setFillBefore(fillBefore); - } - - @Override - public void setRepeatMode(int repeatMode) { - mFlags |= PROPERTY_REPEAT_MODE_MASK; - super.setRepeatMode(repeatMode); - } - - @Override - public void setStartOffset(long startOffset) { - mFlags |= PROPERTY_START_OFFSET_MASK; - super.setStartOffset(startOffset); - } - - /** - * <p>Sets the duration of every child animation.</p> - * - * @param durationMillis the duration of the animation, in milliseconds, for - * every child in this set - */ - @Override - public void setDuration(long durationMillis) { - mFlags |= PROPERTY_DURATION_MASK; - super.setDuration(durationMillis); - } - - /** - * Add a child animation to this animation set. - * The transforms of the child animations are applied in the order - * that they were added - * @param a Animation to add. - */ - public void addAnimation(Animation a) { - mAnimations.add(a); - - boolean noMatrix = (mFlags & PROPERTY_MORPH_MATRIX_MASK) == 0; - if (noMatrix && a.willChangeTransformationMatrix()) { - mFlags |= PROPERTY_MORPH_MATRIX_MASK; - } - - boolean changeBounds = (mFlags & PROPERTY_CHANGE_BOUNDS_MASK) == 0; - if (changeBounds && a.willChangeTransformationMatrix()) { - mFlags |= PROPERTY_CHANGE_BOUNDS_MASK; - } - - if (mAnimations.size() == 1) { - mDuration = a.getStartOffset() + a.getDuration(); - mLastEnd = mStartOffset + mDuration; - } else { - mLastEnd = Math.max(mLastEnd, a.getStartOffset() + a.getDuration()); - mDuration = mLastEnd - mStartOffset; - } - } - - /** - * Sets the start time of this animation and all child animations - * - * @see android.view.animation.Animation#setStartTime(long) - */ - @Override - public void setStartTime(long startTimeMillis) { - super.setStartTime(startTimeMillis); - - final int count = mAnimations.size(); - final ArrayList<Animation> animations = mAnimations; - - for (int i = 0; i < count; i++) { - Animation a = animations.get(i); - a.setStartTime(startTimeMillis); - } - } - - @Override - public long getStartTime() { - long startTime = Long.MAX_VALUE; - - final int count = mAnimations.size(); - final ArrayList<Animation> animations = mAnimations; - - for (int i = 0; i < count; i++) { - Animation a = animations.get(i); - startTime = Math.min(startTime, a.getStartTime()); - } - - return startTime; - } - - @Override - public void restrictDuration(long durationMillis) { - super.restrictDuration(durationMillis); - - final ArrayList<Animation> animations = mAnimations; - int count = animations.size(); - - for (int i = 0; i < count; i++) { - animations.get(i).restrictDuration(durationMillis); - } - } - - /** - * The duration of an AnimationSet is defined to be the - * duration of the longest child animation. - * - * @see android.view.animation.Animation#getDuration() - */ - @Override - public long getDuration() { - final ArrayList<Animation> animations = mAnimations; - final int count = animations.size(); - long duration = 0; - - boolean durationSet = (mFlags & PROPERTY_DURATION_MASK) == PROPERTY_DURATION_MASK; - if (durationSet) { - duration = mDuration; - } else { - for (int i = 0; i < count; i++) { - duration = Math.max(duration, animations.get(i).getDuration()); - } - } - - return duration; - } - - /** - * The duration hint of an animation set is the maximum of the duration - * hints of all of its component animations. - * - * @see android.view.animation.Animation#computeDurationHint - */ - public long computeDurationHint() { - long duration = 0; - final int count = mAnimations.size(); - final ArrayList<Animation> animations = mAnimations; - for (int i = count - 1; i >= 0; --i) { - final long d = animations.get(i).computeDurationHint(); - if (d > duration) duration = d; - } - return duration; - } - - /** - * @hide - */ - public void getInvalidateRegion(int left, int top, int right, int bottom, - RectF invalidate, Transformation transformation) { - - final RectF previousRegion = mPreviousRegion; - - invalidate.set(left, top, right, bottom); - transformation.getMatrix().mapRect(invalidate); - invalidate.union(previousRegion); - - previousRegion.set(left, top, right, bottom); - transformation.getMatrix().mapRect(previousRegion); - - final Transformation tempTransformation = mTransformation; - final Transformation previousTransformation = mPreviousTransformation; - - tempTransformation.set(transformation); - transformation.set(previousTransformation); - previousTransformation.set(tempTransformation); - } - - /** - * @hide - */ - public void initializeInvalidateRegion(int left, int top, int right, int bottom) { - final RectF region = mPreviousRegion; - region.set(left, top, right, bottom); - - if (mFillBefore) { - final int count = mAnimations.size(); - final ArrayList<Animation> animations = mAnimations; - final Transformation temp = mTempTransformation; - - final Transformation previousTransformation = mPreviousTransformation; - - for (int i = count - 1; i >= 0; --i) { - final Animation a = animations.get(i); - - temp.clear(); - a.applyTransformation(0.0f, temp); - previousTransformation.compose(temp); - } - } - } - - /** - * The transformation of an animation set is the concatenation of all of its - * component animations. - * - * @see android.view.animation.Animation#getTransformation - */ - @Override - public boolean getTransformation(long currentTime, Transformation t) { - final int count = mAnimations.size(); - final ArrayList<Animation> animations = mAnimations; - final Transformation temp = mTempTransformation; - - boolean more = false; - boolean started = false; - boolean ended = true; - - t.clear(); - - for (int i = count - 1; i >= 0; --i) { - final Animation a = animations.get(i); - - temp.clear(); - more = a.getTransformation(currentTime, temp) || more; - t.compose(temp); - - started = started || a.hasStarted(); - ended = a.hasEnded() && ended; - } - - if (started && !mStarted) { - if (mListener != null) { - mListener.onAnimationStart(this); - } - mStarted = true; - } - - if (ended != mEnded) { - if (mListener != null) { - mListener.onAnimationEnd(this); - } - mEnded = ended; - } - - return more; - } - - /** - * @see android.view.animation.Animation#scaleCurrentDuration(float) - */ - @Override - public void scaleCurrentDuration(float scale) { - final ArrayList<Animation> animations = mAnimations; - int count = animations.size(); - for (int i = 0; i < count; i++) { - animations.get(i).scaleCurrentDuration(scale); - } - } - - /** - * @see android.view.animation.Animation#initialize(int, int, int, int) - */ - @Override - public void initialize(int width, int height, int parentWidth, int parentHeight) { - super.initialize(width, height, parentWidth, parentHeight); - - boolean durationSet = (mFlags & PROPERTY_DURATION_MASK) == PROPERTY_DURATION_MASK; - boolean fillAfterSet = (mFlags & PROPERTY_FILL_AFTER_MASK) == PROPERTY_FILL_AFTER_MASK; - boolean fillBeforeSet = (mFlags & PROPERTY_FILL_BEFORE_MASK) == PROPERTY_FILL_BEFORE_MASK; - boolean repeatModeSet = (mFlags & PROPERTY_REPEAT_MODE_MASK) == PROPERTY_REPEAT_MODE_MASK; - boolean shareInterpolator = (mFlags & PROPERTY_SHARE_INTERPOLATOR_MASK) - == PROPERTY_SHARE_INTERPOLATOR_MASK; - boolean startOffsetSet = (mFlags & PROPERTY_START_OFFSET_MASK) - == PROPERTY_START_OFFSET_MASK; - - if (shareInterpolator) { - ensureInterpolator(); - } - - final ArrayList<Animation> children = mAnimations; - final int count = children.size(); - - final long duration = mDuration; - final boolean fillAfter = mFillAfter; - final boolean fillBefore = mFillBefore; - final int repeatMode = mRepeatMode; - final Interpolator interpolator = mInterpolator; - final long startOffset = mStartOffset; - - - long[] storedOffsets = mStoredOffsets; - if (storedOffsets == null || storedOffsets.length != count) { - storedOffsets = mStoredOffsets = new long[count]; - } - - for (int i = 0; i < count; i++) { - Animation a = children.get(i); - if (durationSet) { - a.setDuration(duration); - } - if (fillAfterSet) { - a.setFillAfter(fillAfter); - } - if (fillBeforeSet) { - a.setFillBefore(fillBefore); - } - if (repeatModeSet) { - a.setRepeatMode(repeatMode); - } - if (shareInterpolator) { - a.setInterpolator(interpolator); - } - if (startOffsetSet) { - long offset = a.getStartOffset(); - a.setStartOffset(offset + startOffset); - storedOffsets[i] = offset; - } - a.initialize(width, height, parentWidth, parentHeight); - } - } - - @Override - public void reset() { - super.reset(); - restoreChildrenStartOffset(); - } - - /** - * @hide - */ - void restoreChildrenStartOffset() { - final long[] offsets = mStoredOffsets; - if (offsets == null) return; - - final ArrayList<Animation> children = mAnimations; - final int count = children.size(); - - - for (int i = 0; i < count; i++) { - children.get(i).setStartOffset(offsets[i]); - } - } - - /** - * @return All the child animations in this AnimationSet. Note that - * this may include other AnimationSets, which are not expanded. - */ - public List<Animation> getAnimations() { - return mAnimations; - } - - @Override - public boolean willChangeTransformationMatrix() { - return (mFlags & PROPERTY_MORPH_MATRIX_MASK) == PROPERTY_MORPH_MATRIX_MASK; - } - - @Override - public boolean willChangeBounds() { - return (mFlags & PROPERTY_CHANGE_BOUNDS_MASK) == PROPERTY_CHANGE_BOUNDS_MASK; - } -} diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java deleted file mode 100644 index ce3cdc5..0000000 --- a/core/java/android/view/animation/AnimationUtils.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2007 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.view.animation; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.content.Context; -import android.content.res.XmlResourceParser; -import android.content.res.Resources.NotFoundException; -import android.util.AttributeSet; -import android.util.Xml; -import android.os.SystemClock; - -import java.io.IOException; - -/** - * Defines common utilities for working with animations. - * - */ -public class AnimationUtils { - /** - * Returns the current animation time in milliseconds. This time should be used when invoking - * {@link Animation#setStartTime(long)}. Refer to {@link android.os.SystemClock} for more - * information about the different available clocks. The clock used by this method is - * <em>not</em> the "wall" clock (it is not {@link System#currentTimeMillis}). - * - * @return the current animation time in milliseconds - * - * @see android.os.SystemClock - */ - public static long currentAnimationTimeMillis() { - return SystemClock.uptimeMillis(); - } - - /** - * Loads an {@link Animation} object from a resource - * - * @param context Application context used to access resources - * @param id The resource id of the animation to load - * @return The animation object reference by the specified id - * @throws NotFoundException when the animation cannot be loaded - */ - public static Animation loadAnimation(Context context, int id) - throws NotFoundException { - - XmlResourceParser parser = null; - try { - parser = context.getResources().getAnimation(id); - return createAnimationFromXml(context, parser); - } catch (XmlPullParserException ex) { - NotFoundException rnf = new NotFoundException( - "Can't load animation resource ID #0x" - + Integer.toHexString(id)); - rnf.initCause(ex); - throw rnf; - } catch (IOException ex) { - NotFoundException rnf = new NotFoundException( - "Can't load animation resource ID #0x" - + Integer.toHexString(id)); - rnf.initCause(ex); - throw rnf; - } finally { - if (parser != null) parser.close(); - } - } - - private static Animation createAnimationFromXml(Context c, XmlPullParser parser) - throws XmlPullParserException, IOException { - return createAnimationFromXml(c, parser, null, Xml.asAttributeSet(parser)); - } - - private static Animation createAnimationFromXml(Context c, XmlPullParser parser, AnimationSet parent, AttributeSet attrs) - throws XmlPullParserException, IOException { - - Animation anim = null; - - // Make sure we are on a start tag. - int type = parser.getEventType(); - int depth = parser.getDepth(); - - while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) - && type != XmlPullParser.END_DOCUMENT) { - - if (type != XmlPullParser.START_TAG) { - continue; - } - - String name = parser.getName(); - - if (name.equals("set")) { - anim = new AnimationSet(c, attrs); - createAnimationFromXml(c, parser, (AnimationSet)anim, attrs); - } else if (name.equals("alpha")) { - anim = new AlphaAnimation(c, attrs); - } else if (name.equals("scale")) { - anim = new ScaleAnimation(c, attrs); - } else if (name.equals("rotate")) { - anim = new RotateAnimation(c, attrs); - } else if (name.equals("translate")) { - anim = new TranslateAnimation(c, attrs); - } else { - throw new RuntimeException("Unknown animation name: " + parser.getName()); - } - - if (parent != null) { - parent.addAnimation(anim); - } - } - - return anim; - - } - - public static LayoutAnimationController loadLayoutAnimation( - Context context, int id) throws NotFoundException { - - XmlResourceParser parser = null; - try { - parser = context.getResources().getAnimation(id); - return createLayoutAnimationFromXml(context, parser); - } catch (XmlPullParserException ex) { - NotFoundException rnf = new NotFoundException( - "Can't load animation resource ID #0x" + - Integer.toHexString(id)); - rnf.initCause(ex); - throw rnf; - } catch (IOException ex) { - NotFoundException rnf = new NotFoundException( - "Can't load animation resource ID #0x" + - Integer .toHexString(id)); - rnf.initCause(ex); - throw rnf; - } finally { - if (parser != null) parser.close(); - } - } - - private static LayoutAnimationController createLayoutAnimationFromXml( - Context c, XmlPullParser parser) - throws XmlPullParserException, IOException { - return createLayoutAnimationFromXml(c, parser, - Xml.asAttributeSet(parser)); - } - - private static LayoutAnimationController createLayoutAnimationFromXml( - Context c, XmlPullParser parser, AttributeSet attrs) - throws XmlPullParserException, IOException { - - LayoutAnimationController controller = null; - - int type; - int depth = parser.getDepth(); - - while (((type = parser.next()) != XmlPullParser.END_TAG - || parser.getDepth() > depth) - && type != XmlPullParser.END_DOCUMENT) { - - if (type != XmlPullParser.START_TAG) { - continue; - } - - String name = parser.getName(); - - if ("layoutAnimation".equals(name)) { - controller = new LayoutAnimationController(c, attrs); - } else if ("gridLayoutAnimation".equals(name)) { - controller = new GridLayoutAnimationController(c, attrs); - } else { - throw new RuntimeException("Unknown layout animation name: " + - name); - } - } - - return controller; - } - - /** - * Make an animation for objects becoming visible. Uses a slide and fade - * effect. - * - * @param c Context for loading resources - * @param fromLeft is the object to be animated coming from the left - * @return The new animation - */ - public static Animation makeInAnimation(Context c, boolean fromLeft) - { - - Animation a; - if (fromLeft) { - a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_left); - } else { - a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_right); - } - - a.setInterpolator(new DecelerateInterpolator()); - a.setStartTime(currentAnimationTimeMillis()); - return a; - } - - /** - * Make an animation for objects becoming invisible. Uses a slide and fade - * effect. - * - * @param c Context for loading resources - * @param toRight is the object to be animated exiting to the right - * @return The new animation - */ - public static Animation makeOutAnimation(Context c, boolean toRight) - { - - Animation a; - if (toRight) { - a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_out_right); - } else { - a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_out_left); - } - - a.setInterpolator(new AccelerateInterpolator()); - a.setStartTime(currentAnimationTimeMillis()); - return a; - } - - - /** - * Make an animation for objects becoming visible. Uses a slide up and fade - * effect. - * - * @param c Context for loading resources - * @return The new animation - */ - public static Animation makeInChildBottomAnimation(Context c) - { - - Animation a; - a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_child_bottom); - a.setInterpolator(new AccelerateInterpolator()); - a.setStartTime(currentAnimationTimeMillis()); - return a; - } - - /** - * Loads an {@link Interpolator} object from a resource - * - * @param context Application context used to access resources - * @param id The resource id of the animation to load - * @return The animation object reference by the specified id - * @throws NotFoundException - */ - public static Interpolator loadInterpolator(Context context, int id) - throws NotFoundException { - - XmlResourceParser parser = null; - try { - parser = context.getResources().getAnimation(id); - return createInterpolatorFromXml(context, parser); - } catch (XmlPullParserException ex) { - NotFoundException rnf = new NotFoundException( - "Can't load animation resource ID #0x" - + Integer.toHexString(id)); - rnf.initCause(ex); - throw rnf; - } catch (IOException ex) { - NotFoundException rnf = new NotFoundException( - "Can't load animation resource ID #0x" - + Integer.toHexString(id)); - rnf.initCause(ex); - throw rnf; - } finally { - if (parser != null) parser.close(); - } - - } - - private static Interpolator createInterpolatorFromXml(Context c, XmlPullParser parser) - throws XmlPullParserException, IOException { - - Interpolator interpolator = null; - - // Make sure we are on a start tag. - int type = parser.getEventType(); - int depth = parser.getDepth(); - - while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) - && type != XmlPullParser.END_DOCUMENT) { - - if (type != XmlPullParser.START_TAG) { - continue; - } - - AttributeSet attrs = Xml.asAttributeSet(parser); - - String name = parser.getName(); - - - if (name.equals("linearInterpolator")) { - interpolator = new LinearInterpolator(c, attrs); - } else if (name.equals("accelerateInterpolator")) { - interpolator = new AccelerateInterpolator(c, attrs); - } else if (name.equals("decelerateInterpolator")) { - interpolator = new DecelerateInterpolator(c, attrs); - } else if (name.equals("accelerateDecelerateInterpolator")) { - interpolator = new AccelerateDecelerateInterpolator(c, attrs); - } else if (name.equals("cycleInterpolator")) { - interpolator = new CycleInterpolator(c, attrs); - } else { - throw new RuntimeException("Unknown interpolator name: " + parser.getName()); - } - - } - - return interpolator; - - } -} diff --git a/core/java/android/view/animation/CycleInterpolator.java b/core/java/android/view/animation/CycleInterpolator.java deleted file mode 100644 index d355c23..0000000 --- a/core/java/android/view/animation/CycleInterpolator.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2007 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.view.animation; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; - -/** - * Repeats the animation for a specified number of cycles. The - * rate of change follows a sinusoidal pattern. - * - */ -public class CycleInterpolator implements Interpolator { - public CycleInterpolator(float cycles) { - mCycles = cycles; - } - - public CycleInterpolator(Context context, AttributeSet attrs) { - TypedArray a = - context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.CycleInterpolator); - - mCycles = a.getFloat(com.android.internal.R.styleable.CycleInterpolator_cycles, 1.0f); - - a.recycle(); - } - - public float getInterpolation(float input) { - return (float)(Math.sin(2 * mCycles * Math.PI * input)); - } - - private float mCycles; -} diff --git a/core/java/android/view/animation/DecelerateInterpolator.java b/core/java/android/view/animation/DecelerateInterpolator.java deleted file mode 100644 index 176169e..0000000 --- a/core/java/android/view/animation/DecelerateInterpolator.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2007 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.view.animation; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; - -/** - * An interpolator where the rate of change starts out quickly and - * and then decelerates. - * - */ -public class DecelerateInterpolator implements Interpolator { - public DecelerateInterpolator() { - } - - /** - * Constructor - * - * @param factor Degree to which the animation should be eased. Seting factor to 1.0f produces - * an upside-down y=x^2 parabola. Increasing factor above 1.0f makes exaggerates the - * ease-out effect (i.e., it starts even faster and ends evens slower) - */ - public DecelerateInterpolator(float factor) { - mFactor = factor; - } - - public DecelerateInterpolator(Context context, AttributeSet attrs) { - TypedArray a = - context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.DecelerateInterpolator); - - mFactor = a.getFloat(com.android.internal.R.styleable.DecelerateInterpolator_factor, 1.0f); - - a.recycle(); - } - - public float getInterpolation(float input) { - if (mFactor == 1.0f) { - return (float)(1.0f - (1.0f - input) * (1.0f - input)); - } else { - return (float)(1.0f - Math.pow((1.0f - input), 2 * mFactor)); - } - } - - private float mFactor = 1.0f; -} diff --git a/core/java/android/view/animation/GridLayoutAnimationController.java b/core/java/android/view/animation/GridLayoutAnimationController.java deleted file mode 100644 index 9161d8b..0000000 --- a/core/java/android/view/animation/GridLayoutAnimationController.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (C) 2007 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.view.animation; - -import android.view.View; -import android.view.ViewGroup; -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; - -import java.util.Random; - -/** - * A layout animation controller is used to animated a grid layout's children. - * - * While {@link LayoutAnimationController} relies only on the index of the child - * in the view group to compute the animation delay, this class uses both the - * X and Y coordinates of the child within a grid. - * - * In addition, the animation direction can be controlled. The default direction - * is <code>DIRECTION_LEFT_TO_RIGHT | DIRECTION_TOP_TO_BOTTOM</code>. You can - * also set the animation priority to columns or rows. The default priority is - * none. - * - * Information used to compute the animation delay of each child are stored - * in an instance of - * {@link android.view.animation.GridLayoutAnimationController.AnimationParameters}, - * itself stored in the {@link android.view.ViewGroup.LayoutParams} of the view. - * - * @see LayoutAnimationController - * @see android.widget.GridView - * - * @attr ref android.R.styleable#GridLayoutAnimation_columnDelay - * @attr ref android.R.styleable#GridLayoutAnimation_rowDelay - * @attr ref android.R.styleable#GridLayoutAnimation_direction - * @attr ref android.R.styleable#GridLayoutAnimation_directionPriority - */ -public class GridLayoutAnimationController extends LayoutAnimationController { - /** - * Animates the children starting from the left of the grid to the right. - */ - public static final int DIRECTION_LEFT_TO_RIGHT = 0x0; - - /** - * Animates the children starting from the right of the grid to the left. - */ - public static final int DIRECTION_RIGHT_TO_LEFT = 0x1; - - /** - * Animates the children starting from the top of the grid to the bottom. - */ - public static final int DIRECTION_TOP_TO_BOTTOM = 0x0; - - /** - * Animates the children starting from the bottom of the grid to the top. - */ - public static final int DIRECTION_BOTTOM_TO_TOP = 0x2; - - /** - * Bitmask used to retrieve the horizontal component of the direction. - */ - public static final int DIRECTION_HORIZONTAL_MASK = 0x1; - - /** - * Bitmask used to retrieve the vertical component of the direction. - */ - public static final int DIRECTION_VERTICAL_MASK = 0x2; - - /** - * Rows and columns are animated at the same time. - */ - public static final int PRIORITY_NONE = 0; - - /** - * Columns are animated first. - */ - public static final int PRIORITY_COLUMN = 1; - - /** - * Rows are animated first. - */ - public static final int PRIORITY_ROW = 2; - - private float mColumnDelay; - private float mRowDelay; - - private int mDirection; - private int mDirectionPriority; - - /** - * Creates a new grid layout animation controller from external resources. - * - * @param context the Context the view group is running in, through which - * it can access the resources - * @param attrs the attributes of the XML tag that is inflating the - * layout animation controller - */ - public GridLayoutAnimationController(Context context, AttributeSet attrs) { - super(context, attrs); - - TypedArray a = context.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.GridLayoutAnimation); - - Animation.Description d = Animation.Description.parseValue( - a.peekValue(com.android.internal.R.styleable.GridLayoutAnimation_columnDelay)); - mColumnDelay = d.value; - d = Animation.Description.parseValue( - a.peekValue(com.android.internal.R.styleable.GridLayoutAnimation_rowDelay)); - mRowDelay = d.value; - //noinspection PointlessBitwiseExpression - mDirection = a.getInt(com.android.internal.R.styleable.GridLayoutAnimation_direction, - DIRECTION_LEFT_TO_RIGHT | DIRECTION_TOP_TO_BOTTOM); - mDirectionPriority = a.getInt(com.android.internal.R.styleable.GridLayoutAnimation_directionPriority, - PRIORITY_NONE); - - a.recycle(); - } - - /** - * Creates a new layout animation controller with a delay of 50% - * for both rows and columns and the specified animation. - * - * @param animation the animation to use on each child of the view group - */ - public GridLayoutAnimationController(Animation animation) { - this(animation, 0.5f, 0.5f); - } - - /** - * Creates a new layout animation controller with the specified delays - * and the specified animation. - * - * @param animation the animation to use on each child of the view group - * @param columnDelay the delay by which each column animation must be offset - * @param rowDelay the delay by which each row animation must be offset - */ - public GridLayoutAnimationController(Animation animation, float columnDelay, float rowDelay) { - super(animation); - mColumnDelay = columnDelay; - mRowDelay = rowDelay; - } - - /** - * Returns the delay by which the children's animation are offset from one - * column to the other. The delay is expressed as a fraction of the - * animation duration. - * - * @return a fraction of the animation duration - * - * @see #setColumnDelay(float) - * @see #getRowDelay() - * @see #setRowDelay(float) - */ - public float getColumnDelay() { - return mColumnDelay; - } - - /** - * Sets the delay, as a fraction of the animation duration, by which the - * children's animations are offset from one column to the other. - * - * @param columnDelay a fraction of the animation duration - * - * @see #getColumnDelay() - * @see #getRowDelay() - * @see #setRowDelay(float) - */ - public void setColumnDelay(float columnDelay) { - mColumnDelay = columnDelay; - } - - /** - * Returns the delay by which the children's animation are offset from one - * row to the other. The delay is expressed as a fraction of the - * animation duration. - * - * @return a fraction of the animation duration - * - * @see #setRowDelay(float) - * @see #getColumnDelay() - * @see #setColumnDelay(float) - */ - public float getRowDelay() { - return mRowDelay; - } - - /** - * Sets the delay, as a fraction of the animation duration, by which the - * children's animations are offset from one row to the other. - * - * @param rowDelay a fraction of the animation duration - * - * @see #getRowDelay() - * @see #getColumnDelay() - * @see #setColumnDelay(float) - */ - public void setRowDelay(float rowDelay) { - mRowDelay = rowDelay; - } - - /** - * Returns the direction of the animation. {@link #DIRECTION_HORIZONTAL_MASK} - * and {@link #DIRECTION_VERTICAL_MASK} can be used to retrieve the - * horizontal and vertical components of the direction. - * - * @return the direction of the animation - * - * @see #setDirection(int) - * @see #DIRECTION_BOTTOM_TO_TOP - * @see #DIRECTION_TOP_TO_BOTTOM - * @see #DIRECTION_LEFT_TO_RIGHT - * @see #DIRECTION_RIGHT_TO_LEFT - * @see #DIRECTION_HORIZONTAL_MASK - * @see #DIRECTION_VERTICAL_MASK - */ - public int getDirection() { - return mDirection; - } - - /** - * Sets the direction of the animation. The direction is expressed as an - * integer containing a horizontal and vertical component. For instance, - * <code>DIRECTION_BOTTOM_TO_TOP | DIRECTION_RIGHT_TO_LEFT</code>. - * - * @param direction the direction of the animation - * - * @see #getDirection() - * @see #DIRECTION_BOTTOM_TO_TOP - * @see #DIRECTION_TOP_TO_BOTTOM - * @see #DIRECTION_LEFT_TO_RIGHT - * @see #DIRECTION_RIGHT_TO_LEFT - * @see #DIRECTION_HORIZONTAL_MASK - * @see #DIRECTION_VERTICAL_MASK - */ - public void setDirection(int direction) { - mDirection = direction; - } - - /** - * Returns the direction priority for the animation. The priority can - * be either {@link #PRIORITY_NONE}, {@link #PRIORITY_COLUMN} or - * {@link #PRIORITY_ROW}. - * - * @return the priority of the animation direction - * - * @see #setDirectionPriority(int) - * @see #PRIORITY_COLUMN - * @see #PRIORITY_NONE - * @see #PRIORITY_ROW - */ - public int getDirectionPriority() { - return mDirectionPriority; - } - - /** - * Specifies the direction priority of the animation. For instance, - * {@link #PRIORITY_COLUMN} will give priority to columns: the animation - * will first play on the column, then on the rows.Z - * - * @param directionPriority the direction priority of the animation - * - * @see #getDirectionPriority() - * @see #PRIORITY_COLUMN - * @see #PRIORITY_NONE - * @see #PRIORITY_ROW - */ - public void setDirectionPriority(int directionPriority) { - mDirectionPriority = directionPriority; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean willOverlap() { - return mColumnDelay < 1.0f || mRowDelay < 1.0f; - } - - /** - * {@inheritDoc} - */ - @Override - protected long getDelayForView(View view) { - ViewGroup.LayoutParams lp = view.getLayoutParams(); - AnimationParameters params = (AnimationParameters) lp.layoutAnimationParameters; - - if (params == null) { - return 0; - } - - final int column = getTransformedColumnIndex(params); - final int row = getTransformedRowIndex(params); - - final int rowsCount = params.rowsCount; - final int columnsCount = params.columnsCount; - - final long duration = mAnimation.getDuration(); - final float columnDelay = mColumnDelay * duration; - final float rowDelay = mRowDelay * duration; - - float totalDelay; - long viewDelay; - - if (mInterpolator == null) { - mInterpolator = new LinearInterpolator(); - } - - switch (mDirectionPriority) { - case PRIORITY_COLUMN: - viewDelay = (long) (row * rowDelay + column * rowsCount * rowDelay); - totalDelay = rowsCount * rowDelay + columnsCount * rowsCount * rowDelay; - break; - case PRIORITY_ROW: - viewDelay = (long) (column * columnDelay + row * columnsCount * columnDelay); - totalDelay = columnsCount * columnDelay + rowsCount * columnsCount * columnDelay; - break; - case PRIORITY_NONE: - default: - viewDelay = (long) (column * columnDelay + row * rowDelay); - totalDelay = columnsCount * columnDelay + rowsCount * rowDelay; - break; - } - - float normalizedDelay = viewDelay / totalDelay; - normalizedDelay = mInterpolator.getInterpolation(normalizedDelay); - - return (long) (normalizedDelay * totalDelay); - } - - private int getTransformedColumnIndex(AnimationParameters params) { - int index; - switch (getOrder()) { - case ORDER_REVERSE: - index = params.columnsCount - 1 - params.column; - break; - case ORDER_RANDOM: - if (mRandomizer == null) { - mRandomizer = new Random(); - } - index = (int) (params.columnsCount * mRandomizer.nextFloat()); - break; - case ORDER_NORMAL: - default: - index = params.column; - break; - } - - int direction = mDirection & DIRECTION_HORIZONTAL_MASK; - if (direction == DIRECTION_RIGHT_TO_LEFT) { - index = params.columnsCount - 1 - index; - } - - return index; - } - - private int getTransformedRowIndex(AnimationParameters params) { - int index; - switch (getOrder()) { - case ORDER_REVERSE: - index = params.rowsCount - 1 - params.row; - break; - case ORDER_RANDOM: - if (mRandomizer == null) { - mRandomizer = new Random(); - } - index = (int) (params.rowsCount * mRandomizer.nextFloat()); - break; - case ORDER_NORMAL: - default: - index = params.row; - break; - } - - int direction = mDirection & DIRECTION_VERTICAL_MASK; - if (direction == DIRECTION_BOTTOM_TO_TOP) { - index = params.rowsCount - 1 - index; - } - - return index; - } - - /** - * The set of parameters that has to be attached to each view contained in - * the view group animated by the grid layout animation controller. These - * parameters are used to compute the start time of each individual view's - * animation. - */ - public static class AnimationParameters extends - LayoutAnimationController.AnimationParameters { - /** - * The view group's column to which the view belongs. - */ - public int column; - - /** - * The view group's row to which the view belongs. - */ - public int row; - - /** - * The number of columns in the view's enclosing grid layout. - */ - public int columnsCount; - - /** - * The number of rows in the view's enclosing grid layout. - */ - public int rowsCount; - } -} diff --git a/core/java/android/view/animation/Interpolator.java b/core/java/android/view/animation/Interpolator.java deleted file mode 100644 index d14c3e3..0000000 --- a/core/java/android/view/animation/Interpolator.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view.animation; - -/** - * An interpolator defines the rate of change of an animation. This allows - * the basic animation effects (alpha, scale, translate, rotate) to be - * accelerated, decelerated, repeated, etc. - */ -public interface Interpolator { - - /** - * Maps a point on the timeline to a multiplier to be applied to the - * transformations of an animation. - * - * @param input A value between 0 and 1.0 indicating our current point - * in the animation where 0 represents the start and 1.0 represents - * the end - * @return The interpolation value. This value can be more than 1.0 for - * Interpolators which overshoot their targets, or less than 0 for - * Interpolators that undershoot their targets. - */ - float getInterpolation(float input); - -} diff --git a/core/java/android/view/animation/LayoutAnimationController.java b/core/java/android/view/animation/LayoutAnimationController.java deleted file mode 100644 index 882e738..0000000 --- a/core/java/android/view/animation/LayoutAnimationController.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (C) 2007 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.view.animation; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; - -import java.util.Random; - -/** - * A layout animation controller is used to animated a layout's, or a view - * group's, children. Each child uses the same animation but for every one of - * them, the animation starts at a different time. A layout animation controller - * is used by {@link android.view.ViewGroup} to compute the delay by which each - * child's animation start must be offset. The delay is computed by using - * characteristics of each child, like its index in the view group. - * - * This standard implementation computes the delay by multiplying a fixed - * amount of miliseconds by the index of the child in its parent view group. - * Subclasses are supposed to override - * {@link #getDelayForView(android.view.View)} to implement a different way - * of computing the delay. For instance, a - * {@link android.view.animation.GridLayoutAnimationController} will compute the - * delay based on the column and row indices of the child in its parent view - * group. - * - * Information used to compute the animation delay of each child are stored - * in an instance of - * {@link android.view.animation.LayoutAnimationController.AnimationParameters}, - * itself stored in the {@link android.view.ViewGroup.LayoutParams} of the view. - * - * @attr ref android.R.styleable#LayoutAnimation_delay - * @attr ref android.R.styleable#LayoutAnimation_animationOrder - * @attr ref android.R.styleable#LayoutAnimation_interpolator - * @attr ref android.R.styleable#LayoutAnimation_animation - */ -public class LayoutAnimationController { - /** - * Distributes the animation delays in the order in which view were added - * to their view group. - */ - public static final int ORDER_NORMAL = 0; - - /** - * Distributes the animation delays in the reverse order in which view were - * added to their view group. - */ - public static final int ORDER_REVERSE = 1; - - /** - * Randomly distributes the animation delays. - */ - public static final int ORDER_RANDOM = 2; - - /** - * The animation applied on each child of the view group on which this - * layout animation controller is set. - */ - protected Animation mAnimation; - - /** - * The randomizer used when the order is set to random. Subclasses should - * use this object to avoid creating their own. - */ - protected Random mRandomizer; - - /** - * The interpolator used to interpolate the delays. - */ - protected Interpolator mInterpolator; - - private float mDelay; - private int mOrder; - - private long mDuration; - private long mMaxDelay; - - /** - * Creates a new layout animation controller from external resources. - * - * @param context the Context the view group is running in, through which - * it can access the resources - * @param attrs the attributes of the XML tag that is inflating the - * layout animation controller - */ - public LayoutAnimationController(Context context, AttributeSet attrs) { - TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.LayoutAnimation); - - Animation.Description d = Animation.Description.parseValue( - a.peekValue(com.android.internal.R.styleable.LayoutAnimation_delay)); - mDelay = d.value; - - mOrder = a.getInt(com.android.internal.R.styleable.LayoutAnimation_animationOrder, ORDER_NORMAL); - - int resource = a.getResourceId(com.android.internal.R.styleable.LayoutAnimation_animation, 0); - if (resource > 0) { - setAnimation(context, resource); - } - - resource = a.getResourceId(com.android.internal.R.styleable.LayoutAnimation_interpolator, 0); - if (resource > 0) { - setInterpolator(context, resource); - } - - a.recycle(); - } - - /** - * Creates a new layout animation controller with a delay of 50% - * and the specified animation. - * - * @param animation the animation to use on each child of the view group - */ - public LayoutAnimationController(Animation animation) { - this(animation, 0.5f); - } - - /** - * Creates a new layout animation controller with the specified delay - * and the specified animation. - * - * @param animation the animation to use on each child of the view group - * @param delay the delay by which each child's animation must be offset - */ - public LayoutAnimationController(Animation animation, float delay) { - mDelay = delay; - setAnimation(animation); - } - - /** - * Returns the order used to compute the delay of each child's animation. - * - * @return one of {@link #ORDER_NORMAL}, {@link #ORDER_REVERSE} or - * {@link #ORDER_RANDOM) - * - * @attr ref android.R.styleable#LayoutAnimation_animationOrder - */ - public int getOrder() { - return mOrder; - } - - /** - * Sets the order used to compute the delay of each child's animation. - * - * @param order one of {@link #ORDER_NORMAL}, {@link #ORDER_REVERSE} or - * {@link #ORDER_RANDOM} - * - * @attr ref android.R.styleable#LayoutAnimation_animationOrder - */ - public void setOrder(int order) { - mOrder = order; - } - - /** - * Sets the animation to be run on each child of the view group on which - * this layout animation controller is . - * - * @param context the context from which the animation must be inflated - * @param resourceID the resource identifier of the animation - * - * @see #setAnimation(Animation) - * @see #getAnimation() - * - * @attr ref android.R.styleable#LayoutAnimation_animation - */ - public void setAnimation(Context context, int resourceID) { - setAnimation(AnimationUtils.loadAnimation(context, resourceID)); - } - - /** - * Sets the animation to be run on each child of the view group on which - * this layout animation controller is . - * - * @param animation the animation to run on each child of the view group - - * @see #setAnimation(android.content.Context, int) - * @see #getAnimation() - * - * @attr ref android.R.styleable#LayoutAnimation_animation - */ - public void setAnimation(Animation animation) { - mAnimation = animation; - mAnimation.setFillBefore(true); - } - - /** - * Returns the animation applied to each child of the view group on which - * this controller is set. - * - * @return an {@link android.view.animation.Animation} instance - * - * @see #setAnimation(android.content.Context, int) - * @see #setAnimation(Animation) - */ - public Animation getAnimation() { - return mAnimation; - } - - /** - * Sets the interpolator used to interpolate the delays between the - * children. - * - * @param context the context from which the interpolator must be inflated - * @param resourceID the resource identifier of the interpolator - * - * @see #getInterpolator() - * @see #setInterpolator(Interpolator) - * - * @attr ref android.R.styleable#LayoutAnimation_interpolator - */ - public void setInterpolator(Context context, int resourceID) { - setInterpolator(AnimationUtils.loadInterpolator(context, resourceID)); - } - - /** - * Sets the interpolator used to interpolate the delays between the - * children. - * - * @param interpolator the interpolator - * - * @see #getInterpolator() - * @see #setInterpolator(Interpolator) - * - * @attr ref android.R.styleable#LayoutAnimation_interpolator - */ - public void setInterpolator(Interpolator interpolator) { - mInterpolator = interpolator; - } - - /** - * Returns the interpolator used to interpolate the delays between the - * children. - * - * @return an {@link android.view.animation.Interpolator} - */ - public Interpolator getInterpolator() { - return mInterpolator; - } - - /** - * Returns the delay by which the children's animation are offset. The - * delay is expressed as a fraction of the animation duration. - * - * @return a fraction of the animation duration - * - * @see #setDelay(float) - */ - public float getDelay() { - return mDelay; - } - - /** - * Sets the delay, as a fraction of the animation duration, by which the - * children's animations are offset. The general formula is: - * - * <pre> - * child animation delay = child index * delay * animation duration - * </pre> - * - * @param delay a fraction of the animation duration - * - * @see #getDelay() - */ - public void setDelay(float delay) { - mDelay = delay; - } - - /** - * Indicates whether two children's animations will overlap. Animations - * overlap when the delay is lower than 100% (or 1.0). - * - * @return true if animations will overlap, false otherwise - */ - public boolean willOverlap() { - return mDelay < 1.0f; - } - - /** - * Starts the animation. - */ - public void start() { - mDuration = mAnimation.getDuration(); - mMaxDelay = Long.MIN_VALUE; - mAnimation.setStartTime(-1); - } - - /** - * Returns the animation to be applied to the specified view. The returned - * animation is delayed by an offset computed according to the information - * provided by - * {@link android.view.animation.LayoutAnimationController.AnimationParameters}. - * This method is called by view groups to obtain the animation to set on - * a specific child. - * - * @param view the view to animate - * @return an animation delayed by the number of milliseconds returned by - * {@link #getDelayForView(android.view.View)} - * - * @see #getDelay() - * @see #setDelay(float) - * @see #getDelayForView(android.view.View) - */ - public final Animation getAnimationForView(View view) { - final long delay = getDelayForView(view) + mAnimation.getStartOffset(); - mMaxDelay = Math.max(mMaxDelay, delay); - - try { - final Animation animation = mAnimation.clone(); - animation.setStartOffset(delay); - return animation; - } catch (CloneNotSupportedException e) { - return null; - } - } - - /** - * Indicates whether the layout animation is over or not. A layout animation - * is considered done when the animation with the longest delay is done. - * - * @return true if all of the children's animations are over, false otherwise - */ - public boolean isDone() { - return AnimationUtils.currentAnimationTimeMillis() > - mAnimation.getStartTime() + mMaxDelay + mDuration; - } - - /** - * Returns the amount of milliseconds by which the specified view's - * animation must be delayed or offset. Subclasses should override this - * method to return a suitable value. - * - * This implementation returns <code>child animation delay</code> - * milliseconds where: - * - * <pre> - * child animation delay = child index * delay - * </pre> - * - * The index is retrieved from the - * {@link android.view.animation.LayoutAnimationController.AnimationParameters} - * found in the view's {@link android.view.ViewGroup.LayoutParams}. - * - * @param view the view for which to obtain the animation's delay - * @return a delay in milliseconds - * - * @see #getAnimationForView(android.view.View) - * @see #getDelay() - * @see #getTransformedIndex(android.view.animation.LayoutAnimationController.AnimationParameters) - * @see android.view.ViewGroup.LayoutParams - */ - protected long getDelayForView(View view) { - ViewGroup.LayoutParams lp = view.getLayoutParams(); - AnimationParameters params = lp.layoutAnimationParameters; - - if (params == null) { - return 0; - } - - final float delay = mDelay * mAnimation.getDuration(); - final long viewDelay = (long) (getTransformedIndex(params) * delay); - final float totalDelay = delay * params.count; - - if (mInterpolator == null) { - mInterpolator = new LinearInterpolator(); - } - - float normalizedDelay = viewDelay / totalDelay; - normalizedDelay = mInterpolator.getInterpolation(normalizedDelay); - - return (long) (normalizedDelay * totalDelay); - } - - /** - * Transforms the index stored in - * {@link android.view.animation.LayoutAnimationController.AnimationParameters} - * by the order returned by {@link #getOrder()}. Subclasses should override - * this method to provide additional support for other types of ordering. - * This method should be invoked by - * {@link #getDelayForView(android.view.View)} prior to any computation. - * - * @param params the animation parameters containing the index - * @return a transformed index - */ - protected int getTransformedIndex(AnimationParameters params) { - switch (getOrder()) { - case ORDER_REVERSE: - return params.count - 1 - params.index; - case ORDER_RANDOM: - if (mRandomizer == null) { - mRandomizer = new Random(); - } - return (int) (params.count * mRandomizer.nextFloat()); - case ORDER_NORMAL: - default: - return params.index; - } - } - - /** - * The set of parameters that has to be attached to each view contained in - * the view group animated by the layout animation controller. These - * parameters are used to compute the start time of each individual view's - * animation. - */ - public static class AnimationParameters { - /** - * The number of children in the view group containing the view to which - * these parameters are attached. - */ - public int count; - - /** - * The index of the view to which these parameters are attached in its - * containing view group. - */ - public int index; - } -} diff --git a/core/java/android/view/animation/LinearInterpolator.java b/core/java/android/view/animation/LinearInterpolator.java deleted file mode 100644 index 96a039f..0000000 --- a/core/java/android/view/animation/LinearInterpolator.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view.animation; - -import android.content.Context; -import android.util.AttributeSet; - -/** - * An interpolator where the rate of change is constant - * - */ -public class LinearInterpolator implements Interpolator { - - public LinearInterpolator() { - } - - public LinearInterpolator(Context context, AttributeSet attrs) { - } - - public float getInterpolation(float input) { - return input; - } -} diff --git a/core/java/android/view/animation/RotateAnimation.java b/core/java/android/view/animation/RotateAnimation.java deleted file mode 100644 index 2f51b91..0000000 --- a/core/java/android/view/animation/RotateAnimation.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view.animation; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; - -/** - * An animation that controls the rotation of an object. This rotation takes - * place int the X-Y plane. You can specify the point to use for the center of - * the rotation, where (0,0) is the top left point. If not specified, (0,0) is - * the default rotation point. - * - */ -public class RotateAnimation extends Animation { - private float mFromDegrees; - private float mToDegrees; - - private int mPivotXType = ABSOLUTE; - private int mPivotYType = ABSOLUTE; - private float mPivotXValue = 0.0f; - private float mPivotYValue = 0.0f; - - private float mPivotX; - private float mPivotY; - - /** - * Constructor used whan an RotateAnimation is loaded from a resource. - * - * @param context Application context to use - * @param attrs Attribute set from which to read values - */ - public RotateAnimation(Context context, AttributeSet attrs) { - super(context, attrs); - - TypedArray a = context.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.RotateAnimation); - - mFromDegrees = a.getFloat( - com.android.internal.R.styleable.RotateAnimation_fromDegrees, 0.0f); - mToDegrees = a.getFloat(com.android.internal.R.styleable.RotateAnimation_toDegrees, 0.0f); - - Description d = Description.parseValue(a.peekValue( - com.android.internal.R.styleable.RotateAnimation_pivotX)); - mPivotXType = d.type; - mPivotXValue = d.value; - - d = Description.parseValue(a.peekValue( - com.android.internal.R.styleable.RotateAnimation_pivotY)); - mPivotYType = d.type; - mPivotYValue = d.value; - - a.recycle(); - } - - /** - * Constructor to use when building a RotateAnimation from code. - * Default pivotX/pivotY point is (0,0). - * - * @param fromDegrees Rotation offset to apply at the start of the - * animation. - * - * @param toDegrees Rotation offset to apply at the end of the animation. - */ - public RotateAnimation(float fromDegrees, float toDegrees) { - mFromDegrees = fromDegrees; - mToDegrees = toDegrees; - mPivotX = 0.0f; - mPivotY = 0.0f; - } - - /** - * Constructor to use when building a RotateAnimation from code - * - * @param fromDegrees Rotation offset to apply at the start of the - * animation. - * - * @param toDegrees Rotation offset to apply at the end of the animation. - * - * @param pivotX The X coordinate of the point about which the object is - * being rotated, specified as an absolute number where 0 is the left - * edge. - * @param pivotY The Y coordinate of the point about which the object is - * being rotated, specified as an absolute number where 0 is the top - * edge. - */ - public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY) { - mFromDegrees = fromDegrees; - mToDegrees = toDegrees; - - mPivotXType = ABSOLUTE; - mPivotYType = ABSOLUTE; - mPivotXValue = pivotX; - mPivotYValue = pivotY; - } - - /** - * Constructor to use when building a RotateAnimation from code - * - * @param fromDegrees Rotation offset to apply at the start of the - * animation. - * - * @param toDegrees Rotation offset to apply at the end of the animation. - * - * @param pivotXType Specifies how pivotXValue should be interpreted. One of - * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or - * Animation.RELATIVE_TO_PARENT. - * @param pivotXValue The X coordinate of the point about which the object - * is being rotated, specified as an absolute number where 0 is the - * left edge. This value can either be an absolute number if - * pivotXType is ABSOLUTE, or a percentage (where 1.0 is 100%) - * otherwise. - * @param pivotYType Specifies how pivotYValue should be interpreted. One of - * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or - * Animation.RELATIVE_TO_PARENT. - * @param pivotYValue The Y coordinate of the point about which the object - * is being rotated, specified as an absolute number where 0 is the - * top edge. This value can either be an absolute number if - * pivotYType is ABSOLUTE, or a percentage (where 1.0 is 100%) - * otherwise. - */ - public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, - int pivotYType, float pivotYValue) { - mFromDegrees = fromDegrees; - mToDegrees = toDegrees; - - mPivotXValue = pivotXValue; - mPivotXType = pivotXType; - mPivotYValue = pivotYValue; - mPivotYType = pivotYType; - } - - @Override - protected void applyTransformation(float interpolatedTime, Transformation t) { - float degrees = mFromDegrees + ((mToDegrees - mFromDegrees) * interpolatedTime); - - if (mPivotX == 0.0f && mPivotY == 0.0f) { - t.getMatrix().setRotate(degrees); - } else { - t.getMatrix().setRotate(degrees, mPivotX, mPivotY); - } - } - - @Override - public void initialize(int width, int height, int parentWidth, int parentHeight) { - super.initialize(width, height, parentWidth, parentHeight); - mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth); - mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight); - } -} diff --git a/core/java/android/view/animation/ScaleAnimation.java b/core/java/android/view/animation/ScaleAnimation.java deleted file mode 100644 index 122ed6d..0000000 --- a/core/java/android/view/animation/ScaleAnimation.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view.animation; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; - -/** - * An animation that controls the scale of an object. You can specify the point - * to use for the center of scaling. - * - */ -public class ScaleAnimation extends Animation { - private float mFromX; - private float mToX; - private float mFromY; - private float mToY; - - private int mPivotXType = ABSOLUTE; - private int mPivotYType = ABSOLUTE; - private float mPivotXValue = 0.0f; - private float mPivotYValue = 0.0f; - - private float mPivotX; - private float mPivotY; - - /** - * Constructor used whan an ScaleAnimation is loaded from a resource. - * - * @param context Application context to use - * @param attrs Attribute set from which to read values - */ - public ScaleAnimation(Context context, AttributeSet attrs) { - super(context, attrs); - - TypedArray a = context.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.ScaleAnimation); - - mFromX = a.getFloat(com.android.internal.R.styleable.ScaleAnimation_fromXScale, 0.0f); - mToX = a.getFloat(com.android.internal.R.styleable.ScaleAnimation_toXScale, 0.0f); - - mFromY = a.getFloat(com.android.internal.R.styleable.ScaleAnimation_fromYScale, 0.0f); - mToY = a.getFloat(com.android.internal.R.styleable.ScaleAnimation_toYScale, 0.0f); - - Description d = Description.parseValue(a.peekValue( - com.android.internal.R.styleable.ScaleAnimation_pivotX)); - mPivotXType = d.type; - mPivotXValue = d.value; - - d = Description.parseValue(a.peekValue( - com.android.internal.R.styleable.ScaleAnimation_pivotY)); - mPivotYType = d.type; - mPivotYValue = d.value; - - a.recycle(); - } - - /** - * Constructor to use when building a ScaleAnimation from code - * - * @param fromX Horizontal scaling factor to apply at the start of the - * animation - * @param toX Horizontal scaling factor to apply at the end of the animation - * @param fromY Vertical scaling factor to apply at the start of the - * animation - * @param toY Vertical scaling factor to apply at the end of the animation - */ - public ScaleAnimation(float fromX, float toX, float fromY, float toY) { - mFromX = fromX; - mToX = toX; - mFromY = fromY; - mToY = toY; - mPivotX = 0; - mPivotY = 0; - } - - /** - * Constructor to use when building a ScaleAnimation from code - * - * @param fromX Horizontal scaling factor to apply at the start of the - * animation - * @param toX Horizontal scaling factor to apply at the end of the animation - * @param fromY Vertical scaling factor to apply at the start of the - * animation - * @param toY Vertical scaling factor to apply at the end of the animation - * @param pivotX The X coordinate of the point about which the object is - * being scaled, specified as an absolute number where 0 is the left - * edge. (This point remains fixed while the object changes size.) - * @param pivotY The Y coordinate of the point about which the object is - * being scaled, specified as an absolute number where 0 is the top - * edge. (This point remains fixed while the object changes size.) - */ - public ScaleAnimation(float fromX, float toX, float fromY, float toY, - float pivotX, float pivotY) { - mFromX = fromX; - mToX = toX; - mFromY = fromY; - mToY = toY; - - mPivotXType = ABSOLUTE; - mPivotYType = ABSOLUTE; - mPivotXValue = pivotX; - mPivotYValue = pivotY; - } - - /** - * Constructor to use when building a ScaleAnimation from code - * - * @param fromX Horizontal scaling factor to apply at the start of the - * animation - * @param toX Horizontal scaling factor to apply at the end of the animation - * @param fromY Vertical scaling factor to apply at the start of the - * animation - * @param toY Vertical scaling factor to apply at the end of the animation - * @param pivotXType Specifies how pivotXValue should be interpreted. One of - * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or - * Animation.RELATIVE_TO_PARENT. - * @param pivotXValue The X coordinate of the point about which the object - * is being scaled, specified as an absolute number where 0 is the - * left edge. (This point remains fixed while the object changes - * size.) This value can either be an absolute number if pivotXType - * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise. - * @param pivotYType Specifies how pivotYValue should be interpreted. One of - * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or - * Animation.RELATIVE_TO_PARENT. - * @param pivotYValue The Y coordinate of the point about which the object - * is being scaled, specified as an absolute number where 0 is the - * top edge. (This point remains fixed while the object changes - * size.) This value can either be an absolute number if pivotYType - * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise. - */ - public ScaleAnimation(float fromX, float toX, float fromY, float toY, - int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) { - mFromX = fromX; - mToX = toX; - mFromY = fromY; - mToY = toY; - - mPivotXValue = pivotXValue; - mPivotXType = pivotXType; - mPivotYValue = pivotYValue; - mPivotYType = pivotYType; - } - - @Override - protected void applyTransformation(float interpolatedTime, Transformation t) { - float sx = 1.0f; - float sy = 1.0f; - - if (mFromX != 1.0f || mToX != 1.0f) { - sx = mFromX + ((mToX - mFromX) * interpolatedTime); - } - if (mFromY != 1.0f || mToY != 1.0f) { - sy = mFromY + ((mToY - mFromY) * interpolatedTime); - } - - if (mPivotX == 0 && mPivotY == 0) { - t.getMatrix().setScale(sx, sy); - } else { - t.getMatrix().setScale(sx, sy, mPivotX, mPivotY); - } - } - - @Override - public void initialize(int width, int height, int parentWidth, int parentHeight) { - super.initialize(width, height, parentWidth, parentHeight); - - mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth); - mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight); - } -} diff --git a/core/java/android/view/animation/Transformation.java b/core/java/android/view/animation/Transformation.java deleted file mode 100644 index f9e85bf..0000000 --- a/core/java/android/view/animation/Transformation.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view.animation; - -import android.graphics.Matrix; - -/** - * Defines the transformation to be applied at - * one point in time of an Animation. - * - */ -public class Transformation { - /** - * Indicates a transformation that has no effect (alpha = 1 and identity matrix.) - */ - public static int TYPE_IDENTITY = 0x0; - /** - * Indicates a transformation that applies an alpha only (uses an identity matrix.) - */ - public static int TYPE_ALPHA = 0x1; - /** - * Indicates a transformation that applies a matrix only (alpha = 1.) - */ - public static int TYPE_MATRIX = 0x2; - /** - * Indicates a transformation that applies an alpha and a matrix. - */ - public static int TYPE_BOTH = TYPE_ALPHA | TYPE_MATRIX; - - protected Matrix mMatrix; - protected float mAlpha; - protected int mTransformationType; - - /** - * Creates a new transformation with alpha = 1 and the identity matrix. - */ - public Transformation() { - clear(); - } - - /** - * Reset the transformation to a state that leaves the object - * being animated in an unmodified state. The transformation type is - * {@link #TYPE_BOTH} by default. - */ - public void clear() { - if (mMatrix == null) { - mMatrix = new Matrix(); - } else { - mMatrix.reset(); - } - mAlpha = 1.0f; - mTransformationType = TYPE_BOTH; - } - - /** - * Indicates the nature of this transformation. - * - * @return {@link #TYPE_ALPHA}, {@link #TYPE_MATRIX}, - * {@link #TYPE_BOTH} or {@link #TYPE_IDENTITY}. - */ - public int getTransformationType() { - return mTransformationType; - } - - /** - * Sets the transformation type. - * - * @param transformationType One of {@link #TYPE_ALPHA}, - * {@link #TYPE_MATRIX}, {@link #TYPE_BOTH} or - * {@link #TYPE_IDENTITY}. - */ - public void setTransformationType(int transformationType) { - mTransformationType = transformationType; - } - - /** - * Clones the specified transformation. - * - * @param t The transformation to clone. - */ - public void set(Transformation t) { - mAlpha = t.getAlpha(); - mMatrix.set(t.getMatrix()); - mTransformationType = t.getTransformationType(); - } - - /** - * Apply this Transformation to an existing Transformation, e.g. apply - * a scale effect to something that has already been rotated. - * @param t - */ - public void compose(Transformation t) { - mAlpha *= t.getAlpha(); - mMatrix.preConcat(t.getMatrix()); - } - - /** - * @return The 3x3 Matrix representing the trnasformation to apply to the - * coordinates of the object being animated - */ - public Matrix getMatrix() { - return mMatrix; - } - - /** - * Sets the degree of transparency - * @param alpha 1.0 means fully opaqe and 0.0 means fully transparent - */ - public void setAlpha(float alpha) { - mAlpha = alpha; - } - - /** - * @return The degree of transparency - */ - public float getAlpha() { - return mAlpha; - } - - @Override - public String toString() { - return "Transformation{alpha=" + mAlpha + " matrix=" - + mMatrix.toShortString() + "}"; - } - - /** - * Return a string representation of the transformation in a compact form. - */ - public String toShortString() { - return "{alpha=" + mAlpha + " matrix=" + mMatrix.toShortString() + "}"; - } -} diff --git a/core/java/android/view/animation/TranslateAnimation.java b/core/java/android/view/animation/TranslateAnimation.java deleted file mode 100644 index ae21768..0000000 --- a/core/java/android/view/animation/TranslateAnimation.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package android.view.animation; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; - -/** - * An animation that controls the position of an object. See the - * {@link android.view.animation full package} description for details and - * sample code. - * - */ -public class TranslateAnimation extends Animation { - private int mFromXType = ABSOLUTE; - private int mToXType = ABSOLUTE; - - private int mFromYType = ABSOLUTE; - private int mToYType = ABSOLUTE; - - private float mFromXValue = 0.0f; - private float mToXValue = 0.0f; - - private float mFromYValue = 0.0f; - private float mToYValue = 0.0f; - - private float mFromXDelta; - private float mToXDelta; - private float mFromYDelta; - private float mToYDelta; - - /** - * Constructor used whan an ScaleAnimation is loaded from a resource. - * - * @param context Application context to use - * @param attrs Attribute set from which to read values - */ - public TranslateAnimation(Context context, AttributeSet attrs) { - super(context, attrs); - - TypedArray a = context.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.TranslateAnimation); - - Description d = Description.parseValue(a.peekValue( - com.android.internal.R.styleable.TranslateAnimation_fromXDelta)); - mFromXType = d.type; - mFromXValue = d.value; - - d = Description.parseValue(a.peekValue( - com.android.internal.R.styleable.TranslateAnimation_toXDelta)); - mToXType = d.type; - mToXValue = d.value; - - d = Description.parseValue(a.peekValue( - com.android.internal.R.styleable.TranslateAnimation_fromYDelta)); - mFromYType = d.type; - mFromYValue = d.value; - - d = Description.parseValue(a.peekValue( - com.android.internal.R.styleable.TranslateAnimation_toYDelta)); - mToYType = d.type; - mToYValue = d.value; - - a.recycle(); - } - - /** - * Constructor to use when building a ScaleAnimation from code - * - * @param fromXDelta Change in X coordinate to apply at the start of the - * animation - * @param toXDelta Change in X coordinate to apply at the end of the - * animation - * @param fromYDelta Change in Y coordinate to apply at the start of the - * animation - * @param toYDelta Change in Y coordinate to apply at the end of the - * animation - */ - public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) { - mFromXValue = fromXDelta; - mToXValue = toXDelta; - mFromYValue = fromYDelta; - mToYValue = toYDelta; - - mFromXType = ABSOLUTE; - mToXType = ABSOLUTE; - mFromYType = ABSOLUTE; - mToYType = ABSOLUTE; - } - - /** - * Constructor to use when building a ScaleAnimation from code - * - * @param fromXType Specifies how fromXValue should be interpreted. One of - * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or - * Animation.RELATIVE_TO_PARENT. - * @param fromXValue Change in X coordinate to apply at the start of the - * animation. This value can either be an absolute number if fromXType - * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise. - * @param toXType Specifies how toXValue should be interpreted. One of - * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or - * Animation.RELATIVE_TO_PARENT. - * @param toXValue Change in X coordinate to apply at the end of the - * animation. This value can either be an absolute number if toXType - * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise. - * @param fromYType Specifies how fromYValue should be interpreted. One of - * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or - * Animation.RELATIVE_TO_PARENT. - * @param fromYValue Change in Y coordinate to apply at the start of the - * animation. This value can either be an absolute number if fromYType - * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise. - * @param toYType Specifies how toYValue should be interpreted. One of - * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or - * Animation.RELATIVE_TO_PARENT. - * @param toYValue Change in Y coordinate to apply at the end of the - * animation. This value can either be an absolute number if toYType - * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise. - */ - public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, - int fromYType, float fromYValue, int toYType, float toYValue) { - - mFromXValue = fromXValue; - mToXValue = toXValue; - mFromYValue = fromYValue; - mToYValue = toYValue; - - mFromXType = fromXType; - mToXType = toXType; - mFromYType = fromYType; - mToYType = toYType; - } - - - @Override - protected void applyTransformation(float interpolatedTime, Transformation t) { - float dx = mFromXDelta; - float dy = mFromYDelta; - if (mFromXDelta != mToXDelta) { - dx = mFromXDelta + ((mToXDelta - mFromXDelta) * interpolatedTime); - } - if (mFromYDelta != mToYDelta) { - dy = mFromYDelta + ((mToYDelta - mFromYDelta) * interpolatedTime); - } - - t.getMatrix().setTranslate(dx, dy); - } - - @Override - public void initialize(int width, int height, int parentWidth, int parentHeight) { - super.initialize(width, height, parentWidth, parentHeight); - mFromXDelta = resolveSize(mFromXType, mFromXValue, width, parentWidth); - mToXDelta = resolveSize(mToXType, mToXValue, width, parentWidth); - mFromYDelta = resolveSize(mFromYType, mFromYValue, height, parentHeight); - mToYDelta = resolveSize(mToYType, mToYValue, height, parentHeight); - } -} diff --git a/core/java/android/view/animation/package.html b/core/java/android/view/animation/package.html deleted file mode 100755 index 87c99bb..0000000 --- a/core/java/android/view/animation/package.html +++ /dev/null @@ -1,20 +0,0 @@ -<html> -<body> -<p>Provides classes that handle tweened animations.</p> -<p>Android provides two mechanisms - that you can use to create simple animations: <strong>tweened - animation</strong>, in which you tell Android to perform a series of simple - transformations (position, size, rotation, and so on) to the content of a - View; and <strong>frame-by-frame animation</strong>, which loads a series of Drawable resources - one after the other. Both animation types can be used in any View object - to provide simple rotating timers, activity icons, and other useful UI elements. - Tweened animation is handled by this package (android.view.animation); frame-by-frame animation is - handled by the {@link android.graphics.drawable.AnimationDrawable} class. - </p> - -<p>For more information on creating tweened or frame-by-frame animations, read the discussion in the -<a href="{@docRoot}guide/topics/graphics/2d-graphics.html#tween-animation">2D Graphics</a> -Dev Guide.</p> - -</body> -</html> diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java deleted file mode 100644 index 6fbc174..0000000 --- a/core/java/android/view/inputmethod/BaseInputConnection.java +++ /dev/null @@ -1,564 +0,0 @@ -/* - * Copyright (C) 2008 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.view.inputmethod; - -import android.content.Context; -import android.content.res.TypedArray; -import android.os.Bundle; -import android.os.Handler; -import android.os.SystemClock; -import android.text.Editable; -import android.text.NoCopySpan; -import android.text.Selection; -import android.text.Spannable; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.TextUtils; -import android.text.method.MetaKeyKeyListener; -import android.util.Log; -import android.util.LogPrinter; -import android.view.KeyCharacterMap; -import android.view.KeyEvent; -import android.view.View; -import android.view.ViewRoot; - -class ComposingText implements NoCopySpan { -} - -/** - * Base class for implementors of the InputConnection interface, taking care - * of most of the common behavior for providing a connection to an Editable. - * Implementors of this class will want to be sure to implement - * {@link #getEditable} to provide access to their own editable object. - */ -public class BaseInputConnection implements InputConnection { - private static final boolean DEBUG = false; - private static final String TAG = "BaseInputConnection"; - static final Object COMPOSING = new ComposingText(); - - final InputMethodManager mIMM; - final Handler mH; - final View mTargetView; - final boolean mDummyMode; - - private Object[] mDefaultComposingSpans; - - Editable mEditable; - KeyCharacterMap mKeyCharacterMap; - - BaseInputConnection(InputMethodManager mgr, boolean dummyMode) { - mIMM = mgr; - mTargetView = null; - mH = null; - mDummyMode = dummyMode; - } - - public BaseInputConnection(View targetView, boolean dummyMode) { - mIMM = (InputMethodManager)targetView.getContext().getSystemService( - Context.INPUT_METHOD_SERVICE); - mH = targetView.getHandler(); - mTargetView = targetView; - mDummyMode = dummyMode; - } - - public static final void removeComposingSpans(Spannable text) { - text.removeSpan(COMPOSING); - Object[] sps = text.getSpans(0, text.length(), Object.class); - if (sps != null) { - for (int i=sps.length-1; i>=0; i--) { - Object o = sps[i]; - if ((text.getSpanFlags(o)&Spanned.SPAN_COMPOSING) != 0) { - text.removeSpan(o); - } - } - } - } - - public static void setComposingSpans(Spannable text) { - final Object[] sps = text.getSpans(0, text.length(), Object.class); - if (sps != null) { - for (int i=sps.length-1; i>=0; i--) { - final Object o = sps[i]; - if (o == COMPOSING) { - text.removeSpan(o); - continue; - } - final int fl = text.getSpanFlags(o); - if ((fl&(Spanned.SPAN_COMPOSING|Spanned.SPAN_POINT_MARK_MASK)) - != (Spanned.SPAN_COMPOSING|Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)) { - text.setSpan(o, text.getSpanStart(o), text.getSpanEnd(o), - (fl&Spanned.SPAN_POINT_MARK_MASK) - | Spanned.SPAN_COMPOSING - | Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - } - } - - text.setSpan(COMPOSING, 0, text.length(), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING); - } - - public static int getComposingSpanStart(Spannable text) { - return text.getSpanStart(COMPOSING); - } - - public static int getComposingSpanEnd(Spannable text) { - return text.getSpanEnd(COMPOSING); - } - - /** - * Return the target of edit operations. The default implementation - * returns its own fake editable that is just used for composing text; - * subclasses that are real text editors should override this and - * supply their own. - */ - public Editable getEditable() { - if (mEditable == null) { - mEditable = Editable.Factory.getInstance().newEditable(""); - Selection.setSelection(mEditable, 0); - } - return mEditable; - } - - /** - * Default implementation does nothing. - */ - public boolean beginBatchEdit() { - return false; - } - - /** - * Default implementation does nothing. - */ - public boolean endBatchEdit() { - return false; - } - - /** - * Default implementation uses - * {@link MetaKeyKeyListener#clearMetaKeyState(long, int) - * MetaKeyKeyListener.clearMetaKeyState(long, int)} to clear the state. - */ - public boolean clearMetaKeyStates(int states) { - final Editable content = getEditable(); - if (content == null) return false; - MetaKeyKeyListener.clearMetaKeyState(content, states); - return true; - } - - /** - * Default implementation does nothing. - */ - public boolean commitCompletion(CompletionInfo text) { - return false; - } - - /** - * Default implementation replaces any existing composing text with - * the given text. In addition, only if dummy mode, a key event is - * sent for the new text and the current editable buffer cleared. - */ - public boolean commitText(CharSequence text, int newCursorPosition) { - if (DEBUG) Log.v(TAG, "commitText " + text); - replaceText(text, newCursorPosition, false); - sendCurrentText(); - return true; - } - - /** - * The default implementation performs the deletion around the current - * selection position of the editable text. - */ - public boolean deleteSurroundingText(int leftLength, int rightLength) { - if (DEBUG) Log.v(TAG, "deleteSurroundingText " + leftLength - + " / " + rightLength); - final Editable content = getEditable(); - if (content == null) return false; - - beginBatchEdit(); - - int a = Selection.getSelectionStart(content); - int b = Selection.getSelectionEnd(content); - - if (a > b) { - int tmp = a; - a = b; - b = tmp; - } - - // ignore the composing text. - int ca = getComposingSpanStart(content); - int cb = getComposingSpanEnd(content); - if (cb < ca) { - int tmp = ca; - ca = cb; - cb = tmp; - } - if (ca != -1 && cb != -1) { - if (ca < a) a = ca; - if (cb > b) b = cb; - } - - int deleted = 0; - - if (leftLength > 0) { - int start = a - leftLength; - if (start < 0) start = 0; - content.delete(start, a); - deleted = a - start; - } - - if (rightLength > 0) { - b = b - deleted; - - int end = b + rightLength; - if (end > content.length()) end = content.length(); - - content.delete(b, end); - } - - endBatchEdit(); - - return true; - } - - /** - * The default implementation removes the composing state from the - * current editable text. In addition, only if dummy mode, a key event is - * sent for the new text and the current editable buffer cleared. - */ - public boolean finishComposingText() { - if (DEBUG) Log.v(TAG, "finishComposingText"); - final Editable content = getEditable(); - if (content != null) { - beginBatchEdit(); - removeComposingSpans(content); - endBatchEdit(); - sendCurrentText(); - } - return true; - } - - /** - * The default implementation uses TextUtils.getCapsMode to get the - * cursor caps mode for the current selection position in the editable - * text, unless in dummy mode in which case 0 is always returned. - */ - public int getCursorCapsMode(int reqModes) { - if (mDummyMode) return 0; - - final Editable content = getEditable(); - if (content == null) return 0; - - int a = Selection.getSelectionStart(content); - int b = Selection.getSelectionEnd(content); - - if (a > b) { - int tmp = a; - a = b; - b = tmp; - } - - return TextUtils.getCapsMode(content, a, reqModes); - } - - /** - * The default implementation always returns null. - */ - public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) { - return null; - } - - /** - * The default implementation returns the given amount of text from the - * current cursor position in the buffer. - */ - public CharSequence getTextBeforeCursor(int length, int flags) { - final Editable content = getEditable(); - if (content == null) return null; - - int a = Selection.getSelectionStart(content); - int b = Selection.getSelectionEnd(content); - - if (a > b) { - int tmp = a; - a = b; - b = tmp; - } - - if (length > a) { - length = a; - } - - if ((flags&GET_TEXT_WITH_STYLES) != 0) { - return content.subSequence(a - length, a); - } - return TextUtils.substring(content, a - length, a); - } - - /** - * The default implementation returns the given amount of text from the - * current cursor position in the buffer. - */ - public CharSequence getTextAfterCursor(int length, int flags) { - final Editable content = getEditable(); - if (content == null) return null; - - int a = Selection.getSelectionStart(content); - int b = Selection.getSelectionEnd(content); - - if (a > b) { - int tmp = a; - a = b; - b = tmp; - } - - if (b + length > content.length()) { - length = content.length() - b; - } - - - if ((flags&GET_TEXT_WITH_STYLES) != 0) { - return content.subSequence(b, b + length); - } - return TextUtils.substring(content, b, b + length); - } - - /** - * The default implementation does nothing. - */ - public boolean performContextMenuAction(int id) { - return false; - } - - /** - * The default implementation does nothing. - */ - public boolean performPrivateCommand(String action, Bundle data) { - return false; - } - - /** - * The default implementation places the given text into the editable, - * replacing any existing composing text. The new text is marked as - * in a composing state with the composing style. - */ - public boolean setComposingText(CharSequence text, int newCursorPosition) { - if (DEBUG) Log.v(TAG, "setComposingText " + text); - replaceText(text, newCursorPosition, true); - return true; - } - - /** - * The default implementation changes the selection position in the - * current editable text. - */ - public boolean setSelection(int start, int end) { - if (DEBUG) Log.v(TAG, "setSelection " + start + ", " + end); - final Editable content = getEditable(); - if (content == null) return false; - int len = content.length(); - if (start > len || end > len) { - // If the given selection is out of bounds, just ignore it. - // Most likely the text was changed out from under the IME, - // the the IME is going to have to update all of its state - // anyway. - return true; - } - Selection.setSelection(content, start, end); - return true; - } - - /** - * Provides standard implementation for sending a key event to the window - * attached to the input connection's view. - */ - public boolean sendKeyEvent(KeyEvent event) { - synchronized (mIMM.mH) { - Handler h = mH; - if (h == null) { - if (mIMM.mServedView != null) { - h = mIMM.mServedView.getHandler(); - } - } - if (h != null) { - h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME, - event)); - } - } - return false; - } - - /** - * Updates InputMethodManager with the current fullscreen mode. - */ - public boolean reportFullscreenMode(boolean enabled) { - mIMM.setFullscreenMode(enabled); - return true; - } - - private void sendCurrentText() { - if (!mDummyMode) { - return; - } - - Editable content = getEditable(); - if (content != null) { - final int N = content.length(); - if (N == 0) { - return; - } - if (N == 1) { - // If it's 1 character, we have a chance of being - // able to generate normal key events... - if (mKeyCharacterMap == null) { - mKeyCharacterMap = KeyCharacterMap.load( - KeyCharacterMap.BUILT_IN_KEYBOARD); - } - char[] chars = new char[1]; - content.getChars(0, 1, chars, 0); - KeyEvent[] events = mKeyCharacterMap.getEvents(chars); - if (events != null) { - for (int i=0; i<events.length; i++) { - if (DEBUG) Log.v(TAG, "Sending: " + events[i]); - sendKeyEvent(events[i]); - } - content.clear(); - return; - } - } - - // Otherwise, revert to the special key event containing - // the actual characters. - KeyEvent event = new KeyEvent(SystemClock.uptimeMillis(), - content.toString(), KeyCharacterMap.BUILT_IN_KEYBOARD, 0); - sendKeyEvent(event); - content.clear(); - } - } - - private void replaceText(CharSequence text, int newCursorPosition, - boolean composing) { - final Editable content = getEditable(); - if (content == null) { - return; - } - - beginBatchEdit(); - - // delete composing text set previously. - int a = getComposingSpanStart(content); - int b = getComposingSpanEnd(content); - - if (DEBUG) Log.v(TAG, "Composing span: " + a + " to " + b); - - if (b < a) { - int tmp = a; - a = b; - b = tmp; - } - - if (a != -1 && b != -1) { - removeComposingSpans(content); - } else { - a = Selection.getSelectionStart(content); - b = Selection.getSelectionEnd(content); - if (a >=0 && b>= 0 && a != b) { - if (b < a) { - int tmp = a; - a = b; - b = tmp; - } - } - } - - if (composing) { - Spannable sp = null; - if (!(text instanceof Spannable)) { - sp = new SpannableStringBuilder(text); - text = sp; - if (mDefaultComposingSpans == null) { - Context context; - if (mTargetView != null) { - context = mTargetView.getContext(); - } else if (mIMM.mServedView != null) { - context = mIMM.mServedView.getContext(); - } else { - context = null; - } - if (context != null) { - TypedArray ta = context.getTheme() - .obtainStyledAttributes(new int[] { - com.android.internal.R.attr.candidatesTextStyleSpans - }); - CharSequence style = ta.getText(0); - ta.recycle(); - if (style != null && style instanceof Spanned) { - mDefaultComposingSpans = ((Spanned)style).getSpans( - 0, style.length(), Object.class); - } - } - } - if (mDefaultComposingSpans != null) { - for (int i = 0; i < mDefaultComposingSpans.length; ++i) { - sp.setSpan(mDefaultComposingSpans[i], 0, sp.length(), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - } - } else { - sp = (Spannable)text; - } - setComposingSpans(sp); - } - - if (DEBUG) Log.v(TAG, "Replacing from " + a + " to " + b + " with \"" - + text + "\", composing=" + composing - + ", type=" + text.getClass().getCanonicalName()); - - if (DEBUG) { - LogPrinter lp = new LogPrinter(Log.VERBOSE, TAG); - lp.println("Current text:"); - TextUtils.dumpSpans(content, lp, " "); - lp.println("Composing text:"); - TextUtils.dumpSpans(text, lp, " "); - } - - // Position the cursor appropriately, so that after replacing the - // desired range of text it will be located in the correct spot. - // This allows us to deal with filters performing edits on the text - // we are providing here. - if (newCursorPosition > 0) { - newCursorPosition += b - 1; - } else { - newCursorPosition += a; - } - if (newCursorPosition < 0) newCursorPosition = 0; - if (newCursorPosition > content.length()) - newCursorPosition = content.length(); - Selection.setSelection(content, newCursorPosition); - - content.replace(a, b, text); - - if (DEBUG) { - LogPrinter lp = new LogPrinter(Log.VERBOSE, TAG); - lp.println("Final text:"); - TextUtils.dumpSpans(content, lp, " "); - } - - endBatchEdit(); - } -} diff --git a/core/java/android/view/inputmethod/CompletionInfo.aidl b/core/java/android/view/inputmethod/CompletionInfo.aidl deleted file mode 100644 index e601054..0000000 --- a/core/java/android/view/inputmethod/CompletionInfo.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2008 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.view.inputmethod; - -parcelable CompletionInfo; diff --git a/core/java/android/view/inputmethod/CompletionInfo.java b/core/java/android/view/inputmethod/CompletionInfo.java deleted file mode 100644 index 3a8fe72..0000000 --- a/core/java/android/view/inputmethod/CompletionInfo.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2007-2008 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.view.inputmethod; - -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -/** - * Information about a single text completion that an editor has reported to - * an input method. - */ -public final class CompletionInfo implements Parcelable { - static final String TAG = "CompletionInfo"; - - final long mId; - final int mPosition; - final CharSequence mText; - final CharSequence mLabel; - - /** - * Create a simple completion with just text, no label. - */ - public CompletionInfo(long id, int index, CharSequence text) { - mId = id; - mPosition = index; - mText = text; - mLabel = null; - } - - /** - * Create a full completion with both text and label. - */ - public CompletionInfo(long id, int index, CharSequence text, CharSequence label) { - mId = id; - mPosition = index; - mText = text; - mLabel = label; - } - - CompletionInfo(Parcel source) { - mId = source.readLong(); - mPosition = source.readInt(); - mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); - mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); - } - - /** - * Return the abstract identifier for this completion, typically - * corresponding to the id associated with it in the original adapter. - */ - public long getId() { - return mId; - } - - /** - * Return the original position of this completion, typically - * corresponding to its position in the original adapter. - */ - public int getPosition() { - return mPosition; - } - - /** - * Return the actual text associated with this completion. This is the - * real text that will be inserted into the editor if the user selects it. - */ - public CharSequence getText() { - return mText; - } - - /** - * Return the user-visible label for the completion, or null if the plain - * text should be shown. If non-null, this will be what the user sees as - * the completion option instead of the actual text. - */ - public CharSequence getLabel() { - return mLabel; - } - - @Override - public String toString() { - return "CompletionInfo{#" + mPosition + " \"" + mText - + "\" id=" + mId + " label=" + mLabel + "}"; - } - - /** - * Used to package this object into a {@link Parcel}. - * - * @param dest The {@link Parcel} to be written. - * @param flags The flags used for parceling. - */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(mId); - dest.writeInt(mPosition); - TextUtils.writeToParcel(mText, dest, flags); - TextUtils.writeToParcel(mLabel, dest, flags); - } - - /** - * Used to make this class parcelable. - */ - public static final Parcelable.Creator<CompletionInfo> CREATOR - = new Parcelable.Creator<CompletionInfo>() { - public CompletionInfo createFromParcel(Parcel source) { - return new CompletionInfo(source); - } - - public CompletionInfo[] newArray(int size) { - return new CompletionInfo[size]; - } - }; - - public int describeContents() { - return 0; - } -} diff --git a/core/java/android/view/inputmethod/EditorInfo.aidl b/core/java/android/view/inputmethod/EditorInfo.aidl deleted file mode 100644 index 48068f0..0000000 --- a/core/java/android/view/inputmethod/EditorInfo.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2008 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.view.inputmethod; - -parcelable EditorInfo; diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java deleted file mode 100644 index b2f26d7..0000000 --- a/core/java/android/view/inputmethod/EditorInfo.java +++ /dev/null @@ -1,171 +0,0 @@ -package android.view.inputmethod; - -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.InputType; -import android.text.TextUtils; -import android.util.Printer; - -/** - * An EditorInfo describes several attributes of a text editing object - * that an input method is communicating with (typically an EditText), most - * importantly the type of text content it contains. - */ -public class EditorInfo implements InputType, Parcelable { - /** - * The content type of the text box, whose bits are defined by - * {@link InputType}. - * - * @see InputType - * @see #TYPE_MASK_CLASS - * @see #TYPE_MASK_VARIATION - * @see #TYPE_MASK_FLAGS - */ - public int inputType = TYPE_NULL; - - /** - * A string supplying additional information about the content type that - * is private to a particular IME implementation. The string must be - * scoped to a package owned by the implementation, to ensure there are - * no conflicts between implementations, but other than that you can put - * whatever you want in it to communicate with the IME. For example, - * you could have a string that supplies an argument like - * <code>"com.example.myapp.SpecialMode=3"</code>. This field is can be - * filled in from the {@link android.R.attr#editorPrivateContentType} - * attribute of a TextView. - */ - public String privateContentType = null; - - /** - * The text offset of the start of the selection at the time editing - * began; -1 if not known. - */ - public int initialSelStart = -1; - - /** - * The text offset of the end of the selection at the time editing - * began; -1 if not known. - */ - public int initialSelEnd = -1; - - /** - * The capitalization mode of the first character being edited in the - * text. Values may be any combination of - * {@link TextUtils#CAP_MODE_CHARACTERS TextUtils.CAP_MODE_CHARACTERS}, - * {@link TextUtils#CAP_MODE_WORDS TextUtils.CAP_MODE_WORDS}, and - * {@link TextUtils#CAP_MODE_SENTENCES TextUtils.CAP_MODE_SENTENCES}, though - * you should generally just take a non-zero value to mean start out in - * caps mode. - */ - public int initialCapsMode = 0; - - /** - * The "hint" text of the text view, typically shown in-line when the - * text is empty to tell the user what to enter. - */ - public CharSequence hintText; - - /** - * A label to show to the user describing the text they are writing. - */ - public CharSequence label; - - /** - * Name of the package that owns this editor. - */ - public String packageName; - - /** - * Identifier for the editor's field. This is optional, and may be - * 0. By default it is filled in with the result of - * {@link android.view.View#getId() View.getId()} on the View that - * is being edited. - */ - public int fieldId; - - /** - * Additional name for the editor's field. This can supply additional - * name information for the field. By default it is null. The actual - * contents have no meaning. - */ - public String fieldName; - - /** - * Any extra data to supply to the input method. This is for extended - * communication with specific input methods; the name fields in the - * bundle should be scoped (such as "com.mydomain.im.SOME_FIELD") so - * that they don't conflict with others. This field is can be - * filled in from the {@link android.R.attr#editorExtras} - * attribute of a TextView. - */ - public Bundle extras; - - /** - * Write debug output of this object. - */ - public void dump(Printer pw, String prefix) { - pw.println(prefix + "inputType=0x" + Integer.toHexString(inputType) - + " privateContentType=" + privateContentType); - pw.println(prefix + "initialSelStart=" + initialSelStart - + " initialSelEnd=" + initialSelEnd - + " initialCapsMode=0x" - + Integer.toHexString(initialCapsMode)); - pw.println(prefix + "hintText=" + hintText - + " label=" + label); - pw.println(prefix + "packageName=" + packageName - + " fieldId=" + fieldId - + " fieldName=" + fieldName); - pw.println(prefix + "extras=" + extras); - } - - /** - * Used to package this object into a {@link Parcel}. - * - * @param dest The {@link Parcel} to be written. - * @param flags The flags used for parceling. - */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(inputType); - dest.writeString(privateContentType); - dest.writeInt(initialSelStart); - dest.writeInt(initialSelEnd); - dest.writeInt(initialCapsMode); - TextUtils.writeToParcel(hintText, dest, flags); - TextUtils.writeToParcel(label, dest, flags); - dest.writeString(packageName); - dest.writeInt(fieldId); - dest.writeString(fieldName); - dest.writeBundle(extras); - } - - /** - * Used to make this class parcelable. - */ - public static final Parcelable.Creator<EditorInfo> CREATOR = new Parcelable.Creator<EditorInfo>() { - public EditorInfo createFromParcel(Parcel source) { - EditorInfo res = new EditorInfo(); - res.inputType = source.readInt(); - res.privateContentType = source.readString(); - res.initialSelStart = source.readInt(); - res.initialSelEnd = source.readInt(); - res.initialCapsMode = source.readInt(); - res.hintText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); - res.label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); - res.packageName = source.readString(); - res.fieldId = source.readInt(); - res.fieldName = source.readString(); - res.extras = source.readBundle(); - return res; - } - - public EditorInfo[] newArray(int size) { - return new EditorInfo[size]; - } - }; - - public int describeContents() { - return 0; - } - -} diff --git a/core/java/android/view/inputmethod/ExtractedText.aidl b/core/java/android/view/inputmethod/ExtractedText.aidl deleted file mode 100644 index 95e56d7..0000000 --- a/core/java/android/view/inputmethod/ExtractedText.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2008 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.view.inputmethod; - -parcelable ExtractedText; diff --git a/core/java/android/view/inputmethod/ExtractedText.java b/core/java/android/view/inputmethod/ExtractedText.java deleted file mode 100644 index e5d3cae..0000000 --- a/core/java/android/view/inputmethod/ExtractedText.java +++ /dev/null @@ -1,102 +0,0 @@ -package android.view.inputmethod; - -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -/** - * Information about text that has been extracted for use by an input method. - */ -public class ExtractedText implements Parcelable { - /** - * The text that has been extracted. - */ - public CharSequence text; - - /** - * The offset in the overall text at which the extracted text starts. - */ - public int startOffset; - - /** - * If the content is a report of a partial text change, this is the - * offset where the change starts and it runs until - * {@link #partialEndOffset}. If the content is the full text, this - * field is -1. - */ - public int partialStartOffset; - - /** - * If the content is a report of a partial text change, this is the offset - * where the change ends. Note that the actual text may be larger or - * smaller than the difference between this and {@link #partialEndOffset}, - * meaning a reduction or increase, respectively, in the total text. - */ - public int partialEndOffset; - - /** - * The offset where the selection currently starts within the extracted - * text. The real selection start position is at - * <var>startOffset</var>+<var>selectionStart</var>. - */ - public int selectionStart; - - /** - * The offset where the selection currently ends within the extracted - * text. The real selection end position is at - * <var>startOffset</var>+<var>selectionEnd</var>. - */ - public int selectionEnd; - - /** - * Bit for {@link #flags}: set if the text being edited can only be on - * a single line. - */ - public static final int FLAG_SINGLE_LINE = 0x0001; - - /** - * Additional bit flags of information about the edited text. - */ - public int flags; - - /** - * Used to package this object into a {@link Parcel}. - * - * @param dest The {@link Parcel} to be written. - * @param flags The flags used for parceling. - */ - public void writeToParcel(Parcel dest, int flags) { - TextUtils.writeToParcel(text, dest, flags); - dest.writeInt(startOffset); - dest.writeInt(partialStartOffset); - dest.writeInt(partialEndOffset); - dest.writeInt(selectionStart); - dest.writeInt(selectionEnd); - dest.writeInt(flags); - } - - /** - * Used to make this class parcelable. - */ - public static final Parcelable.Creator<ExtractedText> CREATOR = new Parcelable.Creator<ExtractedText>() { - public ExtractedText createFromParcel(Parcel source) { - ExtractedText res = new ExtractedText(); - res.text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); - res.startOffset = source.readInt(); - res.partialStartOffset = source.readInt(); - res.partialEndOffset = source.readInt(); - res.selectionStart = source.readInt(); - res.selectionEnd = source.readInt(); - res.flags = source.readInt(); - return res; - } - - public ExtractedText[] newArray(int size) { - return new ExtractedText[size]; - } - }; - - public int describeContents() { - return 0; - } -} diff --git a/core/java/android/view/inputmethod/ExtractedTextRequest.aidl b/core/java/android/view/inputmethod/ExtractedTextRequest.aidl deleted file mode 100644 index c69acc7..0000000 --- a/core/java/android/view/inputmethod/ExtractedTextRequest.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2008 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.view.inputmethod; - -parcelable ExtractedTextRequest; diff --git a/core/java/android/view/inputmethod/ExtractedTextRequest.java b/core/java/android/view/inputmethod/ExtractedTextRequest.java deleted file mode 100644 index e84b094..0000000 --- a/core/java/android/view/inputmethod/ExtractedTextRequest.java +++ /dev/null @@ -1,70 +0,0 @@ -package android.view.inputmethod; - -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -/** - * Description of what an input method would like from an application when - * extract text from its input editor. - */ -public class ExtractedTextRequest implements Parcelable { - /** - * Arbitrary integer that can be supplied in the request, which will be - * delivered back when reporting updates. - */ - public int token; - - /** - * Additional request flags, having the same possible values as the - * flags parameter of {@link InputConnection#getTextBeforeCursor - * InputConnection.getTextBeforeCursor()}. - */ - public int flags; - - /** - * Hint for the maximum number of lines to return. - */ - public int hintMaxLines; - - /** - * Hint for the maximum number of characters to return. - */ - public int hintMaxChars; - - /** - * Used to package this object into a {@link Parcel}. - * - * @param dest The {@link Parcel} to be written. - * @param flags The flags used for parceling. - */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(token); - dest.writeInt(this.flags); - dest.writeInt(hintMaxLines); - dest.writeInt(hintMaxChars); - } - - /** - * Used to make this class parcelable. - */ - public static final Parcelable.Creator<ExtractedTextRequest> CREATOR - = new Parcelable.Creator<ExtractedTextRequest>() { - public ExtractedTextRequest createFromParcel(Parcel source) { - ExtractedTextRequest res = new ExtractedTextRequest(); - res.token = source.readInt(); - res.flags = source.readInt(); - res.hintMaxLines = source.readInt(); - res.hintMaxChars = source.readInt(); - return res; - } - - public ExtractedTextRequest[] newArray(int size) { - return new ExtractedTextRequest[size]; - } - }; - - public int describeContents() { - return 0; - } -} diff --git a/core/java/android/view/inputmethod/InputBinding.aidl b/core/java/android/view/inputmethod/InputBinding.aidl deleted file mode 100644 index ea09d8b..0000000 --- a/core/java/android/view/inputmethod/InputBinding.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2008 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.view.inputmethod; - -parcelable InputBinding; diff --git a/core/java/android/view/inputmethod/InputBinding.java b/core/java/android/view/inputmethod/InputBinding.java deleted file mode 100644 index f4209ef..0000000 --- a/core/java/android/view/inputmethod/InputBinding.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2007-2008 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.view.inputmethod; - -import android.os.IBinder; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -/** - * Information given to an {@link InputMethod} about a client connecting - * to it. - */ -public final class InputBinding implements Parcelable { - static final String TAG = "InputBinding"; - - /** - * The connection back to the client. - */ - final InputConnection mConnection; - - /** - * A remotable token for the connection back to the client. - */ - final IBinder mConnectionToken; - - /** - * The UID where this binding came from. - */ - final int mUid; - - /** - * The PID where this binding came from. - */ - final int mPid; - - /** - * Constructor. - * - * @param conn The interface for communicating back with the application. - * @param connToken A remoteable token for communicating across processes. - * @param uid The user id of the client of this binding. - * @param pid The process id of where the binding came from. - */ - public InputBinding(InputConnection conn, IBinder connToken, - int uid, int pid) { - mConnection = conn; - mConnectionToken = connToken; - mUid = uid; - mPid = pid; - } - - /** - * Constructor from an existing InputBinding taking a new local input - * connection interface. - * - * @param conn The new connection interface. - * @param binding Existing binding to copy. - */ - public InputBinding(InputConnection conn, InputBinding binding) { - mConnection = conn; - mConnectionToken = binding.getConnectionToken(); - mUid = binding.getUid(); - mPid = binding.getPid(); - } - - InputBinding(Parcel source) { - mConnection = null; - mConnectionToken = source.readStrongBinder(); - mUid = source.readInt(); - mPid = source.readInt(); - } - - /** - * Return the connection for interacting back with the application. - */ - public InputConnection getConnection() { - return mConnection; - } - - /** - * Return the token for the connection back to the application. You can - * not use this directly, it must be converted to a {@link InputConnection} - * for you. - */ - public IBinder getConnectionToken() { - return mConnectionToken; - } - - /** - * Return the user id of the client associated with this binding. - */ - public int getUid() { - return mUid; - } - - /** - * Return the process id where this binding came from. - */ - public int getPid() { - return mPid; - } - - @Override - public String toString() { - return "InputBinding{" + mConnectionToken - + " / uid " + mUid + " / pid " + mPid + "}"; - } - - /** - * Used to package this object into a {@link Parcel}. - * - * @param dest The {@link Parcel} to be written. - * @param flags The flags used for parceling. - */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeStrongBinder(mConnectionToken); - dest.writeInt(mUid); - dest.writeInt(mPid); - } - - /** - * Used to make this class parcelable. - */ - public static final Parcelable.Creator<InputBinding> CREATOR = new Parcelable.Creator<InputBinding>() { - public InputBinding createFromParcel(Parcel source) { - return new InputBinding(source); - } - - public InputBinding[] newArray(int size) { - return new InputBinding[size]; - } - }; - - public int describeContents() { - return 0; - } -} diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java deleted file mode 100644 index 530127d..0000000 --- a/core/java/android/view/inputmethod/InputConnection.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (C) 2007-2008 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.view.inputmethod; - -import android.os.Bundle; -import android.text.Spanned; -import android.view.KeyCharacterMap; -import android.view.KeyEvent; - -/** - * The InputConnection interface is the communication channel from an - * {@link InputMethod} back to the application that is receiving its input. It - * is used to perform such things as reading text around the cursor, - * committing text to the text box, and sending raw key events to the application. - * - * <p>Implementations of this interface should generally be done by - * subclassing {@link BaseInputConnection}. - */ -public interface InputConnection { - /** - * Flag for use with {@link #getTextAfterCursor} and - * {@link #getTextBeforeCursor} to have style information returned along - * with the text. If not set, you will receive only the raw text. If - * set, you may receive a complex CharSequence of both text and style - * spans. - */ - static final int GET_TEXT_WITH_STYLES = 0x0001; - - /** - * Flag for use with {@link #getExtractedText} to indicate you would - * like to receive updates when the extracted text changes. - */ - public static final int GET_EXTRACTED_TEXT_MONITOR = 0x0001; - - /** - * Get <var>n</var> characters of text before the current cursor position. - * - * <p>This method may fail either if the input connection has become invalid - * (such as its process crashing) or the client is taking too long to - * respond with the text (it is given a couple seconds to return). - * In either case, a null is returned. - * - * @param n The expected length of the text. - * @param flags Supplies additional options controlling how the text is - * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}. - * - * @return Returns the text before the cursor position; the length of the - * returned text might be less than <var>n</var>. - */ - public CharSequence getTextBeforeCursor(int n, int flags); - - /** - * Get <var>n</var> characters of text after the current cursor position. - * - * <p>This method may fail either if the input connection has become invalid - * (such as its process crashing) or the client is taking too long to - * respond with the text (it is given a couple seconds to return). - * In either case, a null is returned. - * - * @param n The expected length of the text. - * @param flags Supplies additional options controlling how the text is - * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}. - * - * @return Returns the text after the cursor position; the length of the - * returned text might be less than <var>n</var>. - */ - public CharSequence getTextAfterCursor(int n, int flags); - - /** - * Retrieve the current capitalization mode in effect at the current - * cursor position in the text. See - * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode} for - * more information. - * - * <p>This method may fail either if the input connection has become invalid - * (such as its process crashing) or the client is taking too long to - * respond with the text (it is given a couple seconds to return). - * In either case, a 0 is returned. - * - * @param reqModes The desired modes to retrieve, as defined by - * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode}. These - * constants are defined so that you can simply pass the current - * {@link EditorInfo#inputType TextBoxAttribute.contentType} value - * directly in to here. - * - * @return Returns the caps mode flags that are in effect. - */ - public int getCursorCapsMode(int reqModes); - - /** - * Retrieve the current text in the input connection's editor, and monitor - * for any changes to it. This function returns with the current text, - * and optionally the input connection can send updates to the - * input method when its text changes. - * - * <p>This method may fail either if the input connection has become invalid - * (such as its process crashing) or the client is taking too long to - * respond with the text (it is given a couple seconds to return). - * In either case, a null is returned. - * - * @param request Description of how the text should be returned. - * @param flags Additional options to control the client, either 0 or - * {@link #GET_EXTRACTED_TEXT_MONITOR}. - * - * @return Returns an ExtractedText object describing the state of the - * text view and containing the extracted text itself. - */ - public ExtractedText getExtractedText(ExtractedTextRequest request, - int flags); - - /** - * Delete <var>leftLength</var> characters of text before the current cursor - * position, and delete <var>rightLength</var> characters of text after the - * current cursor position, excluding composing text. - * - * @param leftLength The number of characters to be deleted before the - * current cursor position. - * @param rightLength The number of characters to be deleted after the - * current cursor position. - * - * @return Returns true on success, false if the input connection is no longer - * valid. - */ - boolean deleteSurroundingText(int leftLength, int rightLength); - - /** - * Set composing text around the current cursor position with the given text, - * and set the new cursor position. Any composing text set previously will - * be removed automatically. - * - * @param text The composing text with styles if necessary. If no style - * object attached to the text, the default style for composing text - * is used. See {#link android.text.Spanned} for how to attach style - * object to the text. {#link android.text.SpannableString} and - * {#link android.text.SpannableStringBuilder} are two - * implementations of the interface {#link android.text.Spanned}. - * @param newCursorPosition The new cursor position around the text. If - * > 0, this is relative to the end of the text - 1; if <= 0, this - * is relative to the start of the text. So a value of 1 will - * always advance you to the position after the full text being - * inserted. Note that this means you can't position the cursor - * within the text, because the editor can make modifications to - * the text you are providing so it is not possible to correctly - * specify locations there. - * - * @return Returns true on success, false if the input connection is no longer - * valid. - */ - public boolean setComposingText(CharSequence text, int newCursorPosition); - - /** - * Have the text editor finish whatever composing text is currently - * active. This simply leaves the text as-is, removing any special - * composing styling or other state that was around it. The cursor - * position remains unchanged. - */ - public boolean finishComposingText(); - - /** - * Commit text to the text box and set the new cursor position. - * Any composing text set previously will be removed - * automatically. - * - * @param text The committed text. - * @param newCursorPosition The new cursor position around the text. If - * > 0, this is relative to the end of the text - 1; if <= 0, this - * is relative to the start of the text. So a value of 1 will - * always advance you to the position after the full text being - * inserted. Note that this means you can't position the cursor - * within the text, because the editor can make modifications to - * the text you are providing so it is not possible to correctly - * specify locations there. - * - * - * @return Returns true on success, false if the input connection is no longer - * valid. - */ - public boolean commitText(CharSequence text, int newCursorPosition); - - /** - * Commit a completion the user has selected from the possible ones - * previously reported to {@link InputMethodSession#displayCompletions - * InputMethodSession.displayCompletions()}. This will result in the - * same behavior as if the user had selected the completion from the - * actual UI. - * - * @param text The committed completion. - * - * @return Returns true on success, false if the input connection is no longer - * valid. - */ - public boolean commitCompletion(CompletionInfo text); - - /** - * Set the selection of the text editor. To set the cursor position, - * start and end should have the same value. - */ - public boolean setSelection(int start, int end); - - /** - * Perform a context menu action on the field. The given id may be one of: - * {@link android.R.id#selectAll}, - * {@link android.R.id#startSelectingText}, {@link android.R.id#stopSelectingText}, - * {@link android.R.id#cut}, {@link android.R.id#copy}, - * {@link android.R.id#paste}, {@link android.R.id#copyUrl}, - * or {@link android.R.id#switchInputMethod} - */ - public boolean performContextMenuAction(int id); - - /** - * Tell the editor that you are starting a batch of editor operations. - * The editor will try to avoid sending you updates about its state - * until {@link #endBatchEdit} is called. - */ - public boolean beginBatchEdit(); - - /** - * Tell the editor that you are done with a batch edit previously - * initiated with {@link #endBatchEdit}. - */ - public boolean endBatchEdit(); - - /** - * Send a key event to the process that is currently attached through - * this input connection. The event will be dispatched like a normal - * key event, to the currently focused; this generally is the view that - * is providing this InputConnection, but due to the asynchronous nature - * of this protocol that can not be guaranteed and the focus may have - * changed by the time the event is received. - * - * <p> - * This method can be used to send key events to the application. For - * example, an on-screen keyboard may use this method to simulate a hardware - * keyboard. There are three types of standard keyboards, numeric (12-key), - * predictive (20-key) and ALPHA (QWERTY). You can specify the keyboard type - * by specify the device id of the key event. - * - * <p> - * You will usually want to set the flag - * {@link KeyEvent#FLAG_SOFT_KEYBOARD KeyEvent.FLAG_SOFT_KEYBOARD} on all - * key event objects you give to this API; the flag will not be set - * for you. - * - * @param event The key event. - * - * @return Returns true on success, false if the input connection is no longer - * valid. - * - * @see KeyEvent - * @see KeyCharacterMap#NUMERIC - * @see KeyCharacterMap#PREDICTIVE - * @see KeyCharacterMap#ALPHA - */ - public boolean sendKeyEvent(KeyEvent event); - - /** - * Clear the given meta key pressed states in the given input connection. - * - * @param states The states to be cleared, may be one or more bits as - * per {@link KeyEvent#getMetaState() KeyEvent.getMetaState()}. - * - * @return Returns true on success, false if the input connection is no longer - * valid. - */ - public boolean clearMetaKeyStates(int states); - - /** - * Called by the IME to tell the client when it switches between fullscreen - * and normal modes. This will normally be called for you by the standard - * implementation of {@link android.inputmethodservice.InputMethodService}. - */ - public boolean reportFullscreenMode(boolean enabled); - - /** - * API to send private commands from an input method to its connected - * editor. This can be used to provide domain-specific features that are - * only known between certain input methods and their clients. Note that - * because the InputConnection protocol is asynchronous, you have no way - * to get a result back or know if the client understood the command; you - * can use the information in {@link EditorInfo} to determine if - * a client supports a particular command. - * - * @param action Name of the command to be performed. This <em>must</em> - * be a scoped name, i.e. prefixed with a package name you own, so that - * different developers will not create conflicting commands. - * @param data Any data to include with the command. - * @return Returns true if the command was sent (whether or not the - * associated editor understood it), false if the input connection is no longer - * valid. - */ - public boolean performPrivateCommand(String action, Bundle data); -} diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java deleted file mode 100644 index 740dca8..0000000 --- a/core/java/android/view/inputmethod/InputMethod.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2007-2008 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.view.inputmethod; - -import android.inputmethodservice.InputMethodService; -import android.os.IBinder; - -/** - * The InputMethod interface represents an input method which can generate key - * events and text, such as digital, email addresses, CJK characters, other - * language characters, and etc., while handling various input events, and send - * the text back to the application that requests text input. See - * {@link InputMethodManager} for more general information about the - * architecture. - * - * <p>Applications will not normally use this interface themselves, instead - * relying on the standard interaction provided by - * {@link android.widget.TextView} and {@link android.widget.EditText}. - * - * <p>Those implementing input methods should normally do so by deriving from - * {@link InputMethodService} or one of its subclasses. When implementing - * an input method, the service component containing it must also supply - * a {@link #SERVICE_META_DATA} meta-data field, referencing an XML resource - * providing details about the input method. All input methods also must - * require that clients hold the - * {@link android.Manifest.permission#BIND_INPUT_METHOD} in order to interact - * with the service; if this is not required, the system will not use that - * input method, because it can not trust that it is not compromised. - * - * <p>The InputMethod interface is actually split into two parts: the interface - * here is the top-level interface to the input method, providing all - * access to it, which only the system can access (due to the BIND_INPUT_METHOD - * permission requirement). In addition its method - * {@link #createSession(android.view.inputmethod.InputMethod.SessionCallback)} - * can be called to instantate a secondary {@link InputMethodSession} interface - * which is what clients use to communicate with the input method. - */ -public interface InputMethod { - /** - * This is the interface name that a service implementing an input - * method should say that it supports -- that is, this is the action it - * uses for its intent filter. (Note: this name is used because this - * interface should be moved to the view package.) - */ - public static final String SERVICE_INTERFACE = "android.view.InputMethod"; - - /** - * Name under which an InputMethod service component publishes information - * about itself. This meta-data must reference an XML resource containing - * an - * <code><{@link android.R.styleable#InputMethod input-method}></code> - * tag. - */ - public static final String SERVICE_META_DATA = "android.view.im"; - - public interface SessionCallback { - public void sessionCreated(InputMethodSession session); - } - - /** - * Called first thing after an input method is created, this supplies a - * unique token for the session it has with the system service. It is - * needed to identify itself with the service to validate its operations. - * This token <strong>must not</strong> be passed to applications, since - * it grants special priviledges that should not be given to applications. - * - * <p>Note: to protect yourself from malicious clients, you should only - * accept the first token given to you. Any after that may come from the - * client. - */ - public void attachToken(IBinder token); - - /** - * Bind a new application environment in to the input method, so that it - * can later start and stop input processing. - * Typically this method is called when this input method is enabled in an - * application for the first time. - * - * @param binding Information about the application window that is binding - * to the input method. - * - * @see InputBinding - * @see #unbindInput() - */ - public void bindInput(InputBinding binding); - - /** - * Unbind an application environment, called when the information previously - * set by {@link #bindInput} is no longer valid for this input method. - * - * <p> - * Typically this method is called when the application changes to be - * non-foreground. - */ - public void unbindInput(); - - /** - * This method is called when the application starts to receive text and it - * is ready for this input method to process received events and send result - * text back to the application. - * - * @param inputConnection Optional specific input connection for - * communicating with the text box; if null, you should use the generic - * bound input connection. - * @param info Information about the text box (typically, an EditText) - * that requests input. - * - * @see EditorInfo - */ - public void startInput(InputConnection inputConnection, EditorInfo info); - - /** - * This method is called when the state of this input method needs to be - * reset. - * - * <p> - * Typically, this method is called when the input focus is moved from one - * text box to another. - * - * @param inputConnection Optional specific input connection for - * communicating with the text box; if null, you should use the generic - * bound input connection. - * @param attribute The attribute of the text box (typically, a EditText) - * that requests input. - * - * @see EditorInfo - */ - public void restartInput(InputConnection inputConnection, EditorInfo attribute); - - /** - * Create a new {@link InputMethodSession} that can be handed to client - * applications for interacting with the input method. You can later - * use {@link #revokeSession(InputMethodSession)} to destroy the session - * so that it can no longer be used by any clients. - * - * @param callback Interface that is called with the newly created session. - */ - public void createSession(SessionCallback callback); - - /** - * Control whether a particular input method session is active. - * - * @param session The {@link InputMethodSession} previously provided through - * SessionCallback.sessionCreated() that is to be changed. - */ - public void setSessionEnabled(InputMethodSession session, boolean enabled); - - /** - * Disable and destroy a session that was previously created with - * {@link #createSession(android.view.inputmethod.InputMethod.SessionCallback)}. - * After this call, the given session interface is no longer active and - * calls on it will fail. - * - * @param session The {@link InputMethodSession} previously provided through - * SessionCallback.sessionCreated() that is to be revoked. - */ - public void revokeSession(InputMethodSession session); - - /** - * Flag for {@link #showSoftInput(int)}: this show has been explicitly - * requested by the user. If not set, the system has decided it may be - * a good idea to show the input method based on a navigation operation - * in the UI. - */ - public static final int SHOW_EXPLICIT = 0x00001; - - /** - * Flag for {@link #showSoftInput(int)}: this show has been forced to - * happen by the user. If set, the input method should remain visible - * until deliberated dismissed by the user in its UI. - */ - public static final int SHOW_FORCED = 0x00002; - - /** - * Request that any soft input part of the input method be shown to the user. - * - * @param flags Provide additional information about the show request. - * Currently may be 0 or have the bit {@link #SHOW_EXPLICIT} set. - */ - public void showSoftInput(int flags); - - /** - * Request that any soft input part of the input method be hidden from the user. - */ - public void hideSoftInput(); -} diff --git a/core/java/android/view/inputmethod/InputMethodInfo.aidl b/core/java/android/view/inputmethod/InputMethodInfo.aidl deleted file mode 100644 index 5f4d6b6..0000000 --- a/core/java/android/view/inputmethod/InputMethodInfo.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2008 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.view.inputmethod; - -parcelable InputMethodInfo; diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java deleted file mode 100644 index e8f4b54..0000000 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (C) 2007-2008 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.view.inputmethod; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.content.ComponentName; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.graphics.drawable.Drawable; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.util.Printer; -import android.util.Xml; - -import java.io.IOException; - -/** - * This class is used to specify meta information of an input method. - */ -public final class InputMethodInfo implements Parcelable { - static final String TAG = "InputMethodMetaInfo"; - - /** - * The Service that implements this input method component. - */ - final ResolveInfo mService; - - /** - * The unique string Id to identify the input method. This is generated - * from the input method component. - */ - final String mId; - - /** - * The input method setting activity's name, used by the system settings to - * launch the setting activity of this input method. - */ - final String mSettingsActivityName; - - /** - * The resource in the input method's .apk that holds a boolean indicating - * whether it should be considered the default input method for this - * system. This is a resource ID instead of the final value so that it - * can change based on the configuration (in particular locale). - */ - final int mIsDefaultResId; - - /** - * Constructor. - * - * @param context The Context in which we are parsing the input method. - * @param service The ResolveInfo returned from the package manager about - * this input method's component. - */ - public InputMethodInfo(Context context, ResolveInfo service) - throws XmlPullParserException, IOException { - mService = service; - ServiceInfo si = service.serviceInfo; - mId = new ComponentName(si.packageName, si.name).flattenToShortString(); - - PackageManager pm = context.getPackageManager(); - String settingsActivityComponent = null; - int isDefaultResId = 0; - - XmlResourceParser parser = null; - try { - parser = si.loadXmlMetaData(pm, InputMethod.SERVICE_META_DATA); - if (parser == null) { - throw new XmlPullParserException("No " - + InputMethod.SERVICE_META_DATA + " meta-data"); - } - - AttributeSet attrs = Xml.asAttributeSet(parser); - - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && type != XmlPullParser.START_TAG) { - } - - String nodeName = parser.getName(); - if (!"input-method".equals(nodeName)) { - throw new XmlPullParserException( - "Meta-data does not start with input-method tag"); - } - - TypedArray sa = context.getResources().obtainAttributes(attrs, - com.android.internal.R.styleable.InputMethod); - settingsActivityComponent = sa.getString( - com.android.internal.R.styleable.InputMethod_settingsActivity); - isDefaultResId = sa.getResourceId( - com.android.internal.R.styleable.InputMethod_isDefault, 0); - sa.recycle(); - } finally { - if (parser != null) parser.close(); - } - - mSettingsActivityName = settingsActivityComponent; - mIsDefaultResId = isDefaultResId; - } - - InputMethodInfo(Parcel source) { - mId = source.readString(); - mSettingsActivityName = source.readString(); - mIsDefaultResId = source.readInt(); - mService = ResolveInfo.CREATOR.createFromParcel(source); - } - - /** - * Temporary API for creating a built-in input method. - */ - public InputMethodInfo(String packageName, String className, - CharSequence label, String settingsActivity) { - ResolveInfo ri = new ResolveInfo(); - ServiceInfo si = new ServiceInfo(); - ApplicationInfo ai = new ApplicationInfo(); - ai.packageName = packageName; - ai.enabled = true; - si.applicationInfo = ai; - si.enabled = true; - si.packageName = packageName; - si.name = className; - si.exported = true; - si.nonLocalizedLabel = label; - ri.serviceInfo = si; - mService = ri; - mId = new ComponentName(si.packageName, si.name).flattenToShortString(); - mSettingsActivityName = settingsActivity; - mIsDefaultResId = 0; - } - - /** - * Return a unique ID for this input method. The ID is generated from - * the package and class name implementing the method. - */ - public String getId() { - return mId; - } - - /** - * Return the .apk package that implements this input method. - */ - public String getPackageName() { - return mService.serviceInfo.packageName; - } - - /** - * Return the class name of the service component that implements - * this input method. - */ - public String getServiceName() { - return mService.serviceInfo.name; - } - - /** - * Return the component of the service that implements this input - * method. - */ - public ComponentName getComponent() { - return new ComponentName(mService.serviceInfo.packageName, - mService.serviceInfo.name); - } - - /** - * Load the user-displayed label for this input method. - * - * @param pm Supply a PackageManager used to load the input method's - * resources. - */ - public CharSequence loadLabel(PackageManager pm) { - return mService.loadLabel(pm); - } - - /** - * Load the user-displayed icon for this input method. - * - * @param pm Supply a PackageManager used to load the input method's - * resources. - */ - public Drawable loadIcon(PackageManager pm) { - return mService.loadIcon(pm); - } - - /** - * Return the class name of an activity that provides a settings UI for - * the input method. You can launch this activity be starting it with - * an {@link android.content.Intent} whose action is MAIN and with an - * explicit {@link android.content.ComponentName} - * composed of {@link #getPackageName} and the class name returned here. - * - * <p>A null will be returned if there is no settings activity associated - * with the input method. - */ - public String getSettingsActivity() { - return mSettingsActivityName; - } - - /** - * Return the resource identifier of a resource inside of this input - * method's .apk that determines whether it should be considered a - * default input method for the system. - */ - public int getIsDefaultResourceId() { - return mIsDefaultResId; - } - - /** - * Returns true if this input method is one of the components that is - * built in to the system. - */ - public boolean isBuiltin() { - return mService.serviceInfo.packageName.equals( - InputMethodManager.BUILDIN_INPUTMETHOD_PACKAGE); - } - - public void dump(Printer pw, String prefix) { - pw.println(prefix + "mId=" + mId - + " mSettingsActivityName=" + mSettingsActivityName); - pw.println(prefix + "mIsDefaultResId=0x" - + Integer.toHexString(mIsDefaultResId)); - pw.println(prefix + "Service:"); - mService.dump(pw, prefix + " "); - } - - @Override - public String toString() { - return "InputMethodMetaInfo{" + mId - + ", settings: " - + mSettingsActivityName + "}"; - } - - /** - * Used to test whether the given parameter object is an - * {@link InputMethodInfo} and its Id is the same to this one. - * - * @return true if the given parameter object is an - * {@link InputMethodInfo} and its Id is the same to this one. - */ - @Override - public boolean equals(Object o) { - if (o == this) return true; - if (o == null) return false; - - if (!(o instanceof InputMethodInfo)) return false; - - InputMethodInfo obj = (InputMethodInfo) o; - return mId.equals(obj.mId); - } - - /** - * Used to package this object into a {@link Parcel}. - * - * @param dest The {@link Parcel} to be written. - * @param flags The flags used for parceling. - */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(mId); - dest.writeString(mSettingsActivityName); - dest.writeInt(mIsDefaultResId); - mService.writeToParcel(dest, flags); - } - - /** - * Used to make this class parcelable. - */ - public static final Parcelable.Creator<InputMethodInfo> CREATOR = new Parcelable.Creator<InputMethodInfo>() { - public InputMethodInfo createFromParcel(Parcel source) { - return new InputMethodInfo(source); - } - - public InputMethodInfo[] newArray(int size) { - return new InputMethodInfo[size]; - } - }; - - public int describeContents() { - return 0; - } -} diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java deleted file mode 100644 index 91fa211..0000000 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ /dev/null @@ -1,1185 +0,0 @@ -/* - * Copyright (C) 2007-2008 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.view.inputmethod; - -import android.content.Context; -import android.graphics.Rect; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.util.Log; -import android.util.PrintWriterPrinter; -import android.util.Printer; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewRoot; - -import com.android.internal.os.HandlerCaller; -import com.android.internal.view.IInputConnectionWrapper; -import com.android.internal.view.IInputContext; -import com.android.internal.view.IInputMethodCallback; -import com.android.internal.view.IInputMethodClient; -import com.android.internal.view.IInputMethodManager; -import com.android.internal.view.IInputMethodSession; -import com.android.internal.view.InputBindResult; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * Central system API to the overall input method framework (IMF) architecture, - * which arbitrates interaction between applications and the current input method. - * You can retrieve an instance of this interface with - * {@link Context#getSystemService(String) Context.getSystemService()}. - * - * <p>Topics covered here: - * <ol> - * <li><a href="#ArchitectureOverview">Architecture Overview</a> - * </ol> - * - * <a name="ArchitectureOverview"></a> - * <h3>Architecture Overview</h3> - * - * <p>There are three primary parties involved in the input method - * framework (IMF) architecture:</p> - * - * <ul> - * <li> The <strong>input method manager</strong> as expressed by this class - * is the central point of the system that manages interaction between all - * other parts. It is expressed as the client-side API here which exists - * in each application context and communicates with a global system service - * that manages the interaction across all processes. - * <li> An <strong>input method (IME)</strong> implements a particular - * interaction model allowing the user to generate text. The system binds - * to the current input method that is use, causing it to be created and run, - * and tells it when to hide and show its UI. Only one IME is running at a time. - * <li> Multiple <strong>client applications</strong> arbitrate with the input - * method manager for input focus and control over the state of the IME. Only - * one such client is ever active (working with the IME) at a time. - * </ul> - * - * - * <a name="Applications"></a> - * <h3>Applications</h3> - * - * <p>In most cases, applications that are using the standard - * {@link android.widget.TextView} or its subclasses will have little they need - * to do to work well with soft input methods. The main things you need to - * be aware of are:</p> - * - * <ul> - * <li> Properly set the {@link android.R.attr#inputType} if your editable - * text views, so that the input method will have enough context to help the - * user in entering text into them. - * <li> Deal well with losing screen space when the input method is - * displayed. Ideally an application should handle its window being resized - * smaller, but it can rely on the system performing panning of the window - * if needed. You should set the {@link android.R.attr#windowSoftInputMode} - * attribute on your activity or the corresponding values on windows you - * create to help the system determine whether to pan or resize (it will - * try to determine this automatically but may get it wrong). - * <li> You can also control the preferred soft input state (open, closed, etc) - * for your window using the same {@link android.R.attr#windowSoftInputMode} - * attribute. - * </ul> - * - * <p>More finer-grained control is available through the APIs here to directly - * interact with the IMF and its IME -- either showing or hiding the input - * area, letting the user pick an input method, etc.</p> - * - * <p>For the rare people amongst us writing their own text editors, you - * will need to implement {@link android.view.View#onCreateInputConnection} - * to return a new instance of your own {@link InputConnection} interface - * allowing the IME to interact with your editor.</p> - * - * - * <a name="InputMethods"></a> - * <h3>Input Methods</h3> - * - * <p>An input method (IME) is implemented - * as a {@link android.app.Service}, typically deriving from - * {@link android.inputmethodservice.InputMethodService}. It must provide - * the core {@link InputMethod} interface, though this is normally handled by - * {@link android.inputmethodservice.InputMethodService} and implementors will - * only need to deal with the higher-level API there.</p> - * - * See the {@link android.inputmethodservice.InputMethodService} class for - * more information on implementing IMEs. - * - * - * <a name="Security"></a> - * <h3>Security</h3> - * - * <p>There are a lot of security issues associated with input methods, - * since they essentially have freedom to completely drive the UI and monitor - * everything the user enters. The Android input method framework also allows - * arbitrary third party IMEs, so care must be taken to restrict their - * selection and interactions.</p> - * - * <p>Here are some key points about the security architecture behind the - * IMF:</p> - * - * <ul> - * <li> <p>Only the system is allowed to directly access an IME's - * {@link InputMethod} interface, via the - * {@link android.Manifest.permission#BIND_INPUT_METHOD} permission. This is - * enforced in the system by not binding to an input method service that does - * not require this permission, so the system can guarantee no other untrusted - * clients are accessing the current input method outside of its control.</p> - * - * <li> <p>There may be many client processes of the IMF, but only one may - * be active at a time. The inactive clients can not interact with key - * parts of the IMF through the mechanisms described below.</p> - * - * <li> <p>Clients of an input method are only given access to its - * {@link InputMethodSession} interface. One instance of this interface is - * created for each client, and only calls from the session associated with - * the active client will be processed by the current IME. This is enforced - * by {@link android.inputmethodservice.AbstractInputMethodService} for normal - * IMEs, but must be explicitly handled by an IME that is customizing the - * raw {@link InputMethodSession} implementation.</p> - * - * <li> <p>Only the active client's {@link InputConnection} will accept - * operations. The IMF tells each client process whether it is active, and - * the framework enforces that in inactive processes calls on to the current - * InputConnection will be ignored. This ensures that the current IME can - * only deliver events and text edits to the UI that the user sees as - * being in focus.</p> - * - * <li> <p>An IME can never interact with an {@link InputConnection} while - * the screen is off. This is enforced by making all clients inactive while - * the screen is off, and prevents bad IMEs from driving the UI when the user - * can not be aware of its behavior.</p> - * - * <li> <p>A client application can ask that the system let the user pick a - * new IME, but can not programmatically switch to one itself. This avoids - * malicious applications from switching the user to their own IME, which - * remains running when the user navigates away to another application. An - * IME, on the other hand, <em>is</em> allowed to programmatically switch - * the system to another IME, since it already has full control of user - * input.</p> - * - * <li> <p>The user must explicitly enable a new IME in settings before - * they can switch to it, to confirm with the system that they know about it - * and want to make it available for use.</p> - * </ul> - */ -public final class InputMethodManager { - static final boolean DEBUG = false; - static final String TAG = "InputMethodManager"; - - /** - * The package name of the build-in input method. - * {@hide} - */ - public static final String BUILDIN_INPUTMETHOD_PACKAGE = "android.text.inputmethod"; - - static final Object mInstanceSync = new Object(); - static InputMethodManager mInstance; - - final IInputMethodManager mService; - final Looper mMainLooper; - - // For scheduling work on the main thread. This also serves as our - // global lock. - final H mH; - - // Our generic input connection if the current target does not have its own. - final IInputContext mIInputContext; - - /** - * True if this input method client is active, initially false. - */ - boolean mActive = false; - - /** - * As reported by IME through InputConnection. - */ - boolean mFullscreenMode; - - // ----------------------------------------------------------- - - /** - * This is the view that should currently be served by an input method, - * regardless of the state of setting that up. - */ - View mServedView; - /* - * Keep track of the view that was set when our window gained focus. - */ - View mWindowFocusedView; - /** - * For evaluating the state after a focus change, this is the view that - * had focus. - */ - View mLastServedView; - /** - * This is set when we are in the process of connecting, to determine - * when we have actually finished. - */ - boolean mServedConnecting; - /** - * This is non-null when we have connected the served view; it holds - * the attributes that were last retrieved from the served view and given - * to the input connection. - */ - EditorInfo mCurrentTextBoxAttribute; - /** - * The InputConnection that was last retrieved from the served view. - */ - InputConnection mServedInputConnection; - /** - * The completions that were last provided by the served view. - */ - CompletionInfo[] mCompletions; - - // Cursor position on the screen. - Rect mTmpCursorRect = new Rect(); - Rect mCursorRect = new Rect(); - int mCursorSelStart; - int mCursorSelEnd; - int mCursorCandStart; - int mCursorCandEnd; - - // ----------------------------------------------------------- - - /** - * Sequence number of this binding, as returned by the server. - */ - int mBindSequence = -1; - /** - * ID of the method we are bound to. - */ - String mCurId; - /** - * The actual instance of the method to make calls on it. - */ - IInputMethodSession mCurMethod; - - // ----------------------------------------------------------- - - static final int MSG_DUMP = 1; - - class H extends Handler { - H(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_DUMP: { - HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj; - try { - doDump((FileDescriptor)args.arg1, - (PrintWriter)args.arg2, (String[])args.arg3); - } catch (RuntimeException e) { - ((PrintWriter)args.arg2).println("Exception: " + e); - } - synchronized (args.arg4) { - ((CountDownLatch)args.arg4).countDown(); - } - return; - } - } - } - } - - class ControlledInputConnectionWrapper extends IInputConnectionWrapper { - public ControlledInputConnectionWrapper(Looper mainLooper, InputConnection conn) { - super(mainLooper, conn); - } - - public boolean isActive() { - return mActive; - } - } - - final IInputMethodClient.Stub mClient = new IInputMethodClient.Stub() { - @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { - // No need to check for dump permission, since we only give this - // interface to the system. - - CountDownLatch latch = new CountDownLatch(1); - HandlerCaller.SomeArgs sargs = new HandlerCaller.SomeArgs(); - sargs.arg1 = fd; - sargs.arg2 = fout; - sargs.arg3 = args; - sargs.arg4 = latch; - mH.sendMessage(mH.obtainMessage(MSG_DUMP, sargs)); - try { - if (!latch.await(5, TimeUnit.SECONDS)) { - fout.println("Timeout waiting for dump"); - } - } catch (InterruptedException e) { - fout.println("Interrupted waiting for dump"); - } - } - - public void setUsingInputMethod(boolean state) { - } - - public void onBindMethod(InputBindResult res) { - synchronized (mH) { - if (mBindSequence < 0 || mBindSequence != res.sequence) { - Log.w(TAG, "Ignoring onBind: cur seq=" + mBindSequence - + ", given seq=" + res.sequence); - return; - } - - mCurMethod = res.method; - mCurId = res.id; - mBindSequence = res.sequence; - } - startInputInner(); - } - - public void onUnbindMethod(int sequence) { - synchronized (mH) { - if (mBindSequence == sequence) { - if (false) { - // XXX the server has already unbound! - if (mCurMethod != null && mCurrentTextBoxAttribute != null) { - try { - mCurMethod.finishInput(); - } catch (RemoteException e) { - Log.w(TAG, "IME died: " + mCurId, e); - } - } - } - clearBindingLocked(); - - // If we were actively using the last input method, then - // we would like to re-connect to the next input method. - if (mServedView != null && mServedView.isFocused()) { - mServedConnecting = true; - } - } - startInputInner(); - } - } - - public void setActive(boolean active) { - mActive = active; - mFullscreenMode = false; - } - }; - - final InputConnection mDummyInputConnection = new BaseInputConnection(this, true); - - InputMethodManager(IInputMethodManager service, Looper looper) { - mService = service; - mMainLooper = looper; - mH = new H(looper); - mIInputContext = new ControlledInputConnectionWrapper(looper, - mDummyInputConnection); - - if (mInstance == null) { - mInstance = this; - } - } - - /** - * Retrieve the global InputMethodManager instance, creating it if it - * doesn't already exist. - * @hide - */ - static public InputMethodManager getInstance(Context context) { - synchronized (mInstanceSync) { - if (mInstance != null) { - return mInstance; - } - IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE); - IInputMethodManager service = IInputMethodManager.Stub.asInterface(b); - mInstance = new InputMethodManager(service, context.getMainLooper()); - } - return mInstance; - } - - /** - * Private optimization: retrieve the global InputMethodManager instance, - * if it exists. - * @hide - */ - static public InputMethodManager peekInstance() { - return mInstance; - } - - /** @hide */ - public IInputMethodClient getClient() { - return mClient; - } - - /** @hide */ - public IInputContext getInputContext() { - return mIInputContext; - } - - public List<InputMethodInfo> getInputMethodList() { - try { - return mService.getInputMethodList(); - } catch (RemoteException e) { - throw new RuntimeException(e); - } - } - - public List<InputMethodInfo> getEnabledInputMethodList() { - try { - return mService.getEnabledInputMethodList(); - } catch (RemoteException e) { - throw new RuntimeException(e); - } - } - - public void showStatusIcon(IBinder imeToken, String packageName, int iconId) { - try { - mService.updateStatusIcon(imeToken, packageName, iconId); - } catch (RemoteException e) { - throw new RuntimeException(e); - } - } - - public void hideStatusIcon(IBinder imeToken) { - try { - mService.updateStatusIcon(imeToken, null, 0); - } catch (RemoteException e) { - throw new RuntimeException(e); - } - } - - /** @hide */ - public void setFullscreenMode(boolean fullScreen) { - mFullscreenMode = fullScreen; - } - - /** - * Allows you to discover whether the attached input method is running - * in fullscreen mode. Return true if it is fullscreen, entirely covering - * your UI, else returns false. - */ - public boolean isFullscreenMode() { - return mFullscreenMode; - } - - /** - * Return true if the given view is the currently active view for the - * input method. - */ - public boolean isActive(View view) { - synchronized (mH) { - return mServedView == view && mCurrentTextBoxAttribute != null; - } - } - - /** - * Return true if any view is currently active in the input method. - */ - public boolean isActive() { - synchronized (mH) { - return mServedView != null && mCurrentTextBoxAttribute != null; - } - } - - /** - * Return true if the currently served view is accepting full text edits. - * If false, it has no input connection, so can only handle raw key events. - */ - public boolean isAcceptingText() { - return mServedInputConnection != null; - } - - /** - * Reset all of the state associated with being bound to an input method. - */ - void clearBindingLocked() { - clearConnectionLocked(); - mBindSequence = -1; - mCurId = null; - mCurMethod = null; - } - - /** - * Reset all of the state associated with a served view being connected - * to an input method - */ - void clearConnectionLocked() { - mCurrentTextBoxAttribute = null; - mServedInputConnection = null; - } - - /** - * Disconnect any existing input connection, clearing the served view. - */ - void finishInputLocked() { - if (mServedView != null) { - if (DEBUG) Log.v(TAG, "FINISH INPUT: " + mServedView); - - if (mCurrentTextBoxAttribute != null) { - try { - mService.finishInput(mClient); - } catch (RemoteException e) { - } - } - - if (mServedInputConnection != null) { - // We need to tell the previously served view that it is no - // longer the input target, so it can reset its state. Schedule - // this call on its window's Handler so it will be on the correct - // thread and outside of our lock. - Handler vh = mServedView.getHandler(); - if (vh != null) { - // This will result in a call to reportFinishInputConnection() - // below. - vh.sendMessage(vh.obtainMessage(ViewRoot.FINISH_INPUT_CONNECTION, - mServedInputConnection)); - } - } - - mServedView = null; - mCompletions = null; - mServedConnecting = false; - clearConnectionLocked(); - } - } - - /** - * Called from the FINISH_INPUT_CONNECTION message above. - * @hide - */ - public void reportFinishInputConnection(InputConnection ic) { - if (mServedInputConnection != ic) { - ic.finishComposingText(); - } - } - - public void displayCompletions(View view, CompletionInfo[] completions) { - synchronized (mH) { - if (mServedView != view) { - return; - } - - mCompletions = completions; - if (mCurMethod != null) { - try { - mCurMethod.displayCompletions(mCompletions); - } catch (RemoteException e) { - } - } - } - } - - public void updateExtractedText(View view, int token, ExtractedText text) { - synchronized (mH) { - if (mServedView != view) { - return; - } - - if (mCurMethod != null) { - try { - mCurMethod.updateExtractedText(token, text); - } catch (RemoteException e) { - } - } - } - } - - /** - * Flag for {@link #showSoftInput} to indicate that this is an implicit - * request to show the input window, not as the result of a direct request - * by the user. The window may not be shown in this case. - */ - public static final int SHOW_IMPLICIT = 0x0001; - - /** - * Flag for {@link #showSoftInput} to indicate that the user has forced - * the input method open (such as by long-pressing menu) so it should - * not be closed until they explicitly do so. - */ - public static final int SHOW_FORCED = 0x0002; - - /** - * Explicitly request that the current input method's soft input area be - * shown to the user, if needed. Call this if the user interacts with - * your view in such a way that they have expressed they would like to - * start performing input into it. - * - * @param view The currently focused view, which would like to receive - * soft keyboard input. - * @param flags Provides additional operating flags. Currently may be - * 0 or have the {@link #SHOW_IMPLICIT} bit set. - */ - public void showSoftInput(View view, int flags) { - synchronized (mH) { - if (mServedView != view) { - return; - } - - try { - mService.showSoftInput(mClient, flags); - } catch (RemoteException e) { - } - } - } - - /** @hide */ - public void showSoftInputUnchecked(int flags) { - try { - mService.showSoftInput(mClient, flags); - } catch (RemoteException e) { - } - } - - /** - * Flag for {@link #hideSoftInputFromWindow} to indicate that the soft - * input window should only be hidden if it was not explicitly shown - * by the user. - */ - public static final int HIDE_IMPLICIT_ONLY = 0x0001; - - /** - * Flag for {@link #hideSoftInputFromWindow} to indicate that the soft - * input window should normally be hidden, unless it was originally - * shown with {@link #SHOW_FORCED}. - */ - public static final int HIDE_NOT_ALWAYS = 0x0002; - - /** - * Request to hide the soft input window from the context of the window - * that is currently accepting input. This should be called as a result - * of the user doing some actually than fairly explicitly requests to - * have the input window hidden. - * - * @param windowToken The token of the window that is making the request, - * as returned by {@link View#getWindowToken() View.getWindowToken()}. - * @param flags Provides additional operating flags. Currently may be - * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set. - */ - public void hideSoftInputFromWindow(IBinder windowToken, int flags) { - synchronized (mH) { - if (mServedView == null || mServedView.getWindowToken() != windowToken) { - return; - } - - try { - mService.hideSoftInput(mClient, flags); - } catch (RemoteException e) { - } - } - } - - /** - * If the input method is currently connected to the given view, - * restart it with its new contents. You should call this when the text - * within your view changes outside of the normal input method or key - * input flow, such as when an application calls TextView.setText(). - * - * @param view The view whose text has changed. - */ - public void restartInput(View view) { - synchronized (mH) { - if (mServedView != view) { - return; - } - - mServedConnecting = true; - } - - startInputInner(); - } - - void startInputInner() { - final View view; - synchronized (mH) { - view = mServedView; - - // Make sure we have a window token for the served view. - if (DEBUG) Log.v(TAG, "Starting input: view=" + view); - if (view == null) { - if (DEBUG) Log.v(TAG, "ABORT input: no served view!"); - return; - } - } - - // Now we need to get an input connection from the served view. - // This is complicated in a couple ways: we can't be holding our lock - // when calling out to the view, and we need to make sure we call into - // the view on the same thread that is driving its view hierarchy. - Handler vh = view.getHandler(); - if (vh == null) { - // If the view doesn't have a handler, something has changed out - // from under us, so just bail. - if (DEBUG) Log.v(TAG, "ABORT input: no handler for view!"); - return; - } - if (vh.getLooper() != Looper.myLooper()) { - // The view is running on a different thread than our own, so - // we need to reschedule our work for over there. - if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread"); - vh.post(new Runnable() { - public void run() { - startInputInner(); - } - }); - } - - // Okay we are now ready to call into the served view and have it - // do its stuff. - // Life is good: let's hook everything up! - EditorInfo tba = new EditorInfo(); - tba.packageName = view.getContext().getPackageName(); - tba.fieldId = view.getId(); - InputConnection ic = view.onCreateInputConnection(tba); - if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic); - - synchronized (mH) { - // Now that we are locked again, validate that our state hasn't - // changed. - if (mServedView != view || !mServedConnecting) { - // Something else happened, so abort. - if (DEBUG) Log.v(TAG, - "Starting input: finished by someone else (view=" - + mServedView + " conn=" + mServedConnecting + ")"); - return; - } - - // If we already have a text box, then this view is already - // connected so we want to restart it. - final boolean initial = mCurrentTextBoxAttribute == null; - - // Hook 'em up and let 'er rip. - mCurrentTextBoxAttribute = tba; - mServedConnecting = false; - mServedInputConnection = ic; - IInputContext servedContext; - if (ic != null) { - mCursorSelStart = tba.initialSelStart; - mCursorSelEnd = tba.initialSelEnd; - mCursorCandStart = -1; - mCursorCandEnd = -1; - mCursorRect.setEmpty(); - servedContext = new ControlledInputConnectionWrapper(vh.getLooper(), ic); - } else { - servedContext = null; - } - - try { - if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic=" - + ic + " tba=" + tba + " initial=" + initial); - InputBindResult res = mService.startInput(mClient, - servedContext, tba, initial, mCurMethod == null); - if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res); - if (res != null) { - if (res.id != null) { - mBindSequence = res.sequence; - mCurMethod = res.method; - } else { - // This means there is no input method available. - if (DEBUG) Log.v(TAG, "ABORT input: no input method!"); - return; - } - } - if (mCurMethod != null && mCompletions != null) { - try { - mCurMethod.displayCompletions(mCompletions); - } catch (RemoteException e) { - } - } - } catch (RemoteException e) { - Log.w(TAG, "IME died: " + mCurId, e); - } - } - } - - /** - * When the focused window is dismissed, this method is called to finish the - * input method started before. - * @hide - */ - public void windowDismissed(IBinder appWindowToken) { - synchronized (mH) { - if (mServedView != null && - mServedView.getWindowToken() == appWindowToken) { - finishInputLocked(); - } - } - } - - /** - * Call this when a view receives focus. - * @hide - */ - public void focusIn(View view) { - synchronized (mH) { - focusInLocked(view); - } - - startInputInner(); - } - - void focusInLocked(View view) { - if (DEBUG) Log.v(TAG, "focusIn: " + view); - // Okay we have a new view that is being served. - if (mServedView != view) { - mCurrentTextBoxAttribute = null; - } - mServedView = view; - mCompletions = null; - mServedConnecting = true; - } - - /** - * Call this when a view loses focus. - * @hide - */ - public void focusOut(View view) { - InputConnection ic = null; - synchronized (mH) { - if (DEBUG) Log.v(TAG, "focusOut: " + view - + " mServedView=" + mServedView - + " winFocus=" + view.hasWindowFocus()); - if (mServedView == view) { - ic = mServedInputConnection; - // The following code would auto-hide the IME if we end up - // with no more views with focus. This can happen, however, - // whenever we go into touch mode, so it ends up hiding - // at times when we don't really want it to. For now it - // seems better to just turn it all off. - if (false && view.hasWindowFocus()) { - mLastServedView = view; - Handler vh = view.getHandler(); - if (vh != null) { - // This will result in a call to checkFocus() below. - vh.removeMessages(ViewRoot.CHECK_FOCUS); - vh.sendMessage(vh.obtainMessage(ViewRoot.CHECK_FOCUS, - view)); - } - } - } - } - - if (ic != null) { - ic.finishComposingText(); - } - } - - /** - * @hide - */ - public void checkFocus(View view) { - synchronized (mH) { - if (view != mLastServedView) { - return; - } - if (DEBUG) Log.v(TAG, "checkFocus: view=" + mServedView - + " last=" + mLastServedView); - if (mServedView == mLastServedView) { - finishInputLocked(); - // In this case, we used to have a focused view on the window, - // but no longer do. We should make sure the input method is - // no longer shown, since it serves no purpose. - closeCurrentInput(); - } - mLastServedView = null; - } - } - - void closeCurrentInput() { - try { - mService.hideSoftInput(mClient, HIDE_NOT_ALWAYS); - } catch (RemoteException e) { - } - } - - /** - * Called by ViewRoot the first time it gets window focus. - * @hide - */ - public void onWindowFocus(View rootView, View focusedView, int softInputMode, - boolean first, int windowFlags) { - boolean needStartInput = false; - synchronized (mH) { - if (DEBUG) Log.v(TAG, "onWindowFocus: " + focusedView - + " softInputMode=" + softInputMode - + " first=" + first + " flags=#" - + Integer.toHexString(windowFlags)); - if (mWindowFocusedView == null) { - focusInLocked(focusedView != null ? focusedView : rootView); - needStartInput = true; - } - } - - if (needStartInput) { - startInputInner(); - } - - synchronized (mH) { - try { - final boolean isTextEditor = focusedView != null && - focusedView.onCheckIsTextEditor(); - mService.windowGainedFocus(mClient, focusedView != null, - isTextEditor, softInputMode, first, windowFlags); - } catch (RemoteException e) { - } - } - } - - /** @hide */ - public void startGettingWindowFocus() { - synchronized (mH) { - mWindowFocusedView = null; - } - } - - /** - * Report the current selection range. - */ - public void updateSelection(View view, int selStart, int selEnd, - int candidatesStart, int candidatesEnd) { - synchronized (mH) { - if (mServedView != view || mCurrentTextBoxAttribute == null - || mCurMethod == null) { - return; - } - - if (mCursorSelStart != selStart || mCursorSelEnd != selEnd - || mCursorCandStart != candidatesStart - || mCursorCandEnd != candidatesEnd) { - if (DEBUG) Log.d(TAG, "updateSelection"); - - try { - if (DEBUG) Log.v(TAG, "SELECTION CHANGE: " + mCurMethod); - mCurMethod.updateSelection(mCursorSelStart, mCursorSelEnd, - selStart, selEnd, candidatesStart, candidatesEnd); - mCursorSelStart = selStart; - mCursorSelEnd = selEnd; - mCursorCandStart = candidatesStart; - mCursorCandEnd = candidatesEnd; - } catch (RemoteException e) { - Log.w(TAG, "IME died: " + mCurId, e); - } - } - } - } - - /** - * Returns true if the current input method wants to watch the location - * of the input editor's cursor in its window. - */ - public boolean isWatchingCursor(View view) { - return false; - } - - /** - * Report the current cursor location in its window. - */ - public void updateCursor(View view, int left, int top, int right, int bottom) { - synchronized (mH) { - if (mServedView != view || mCurrentTextBoxAttribute == null - || mCurMethod == null) { - return; - } - - mTmpCursorRect.set(left, top, right, bottom); - if (!mCursorRect.equals(mTmpCursorRect)) { - if (DEBUG) Log.d(TAG, "updateCursor"); - - try { - if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod); - mCurMethod.updateCursor(mTmpCursorRect); - mCursorRect.set(mTmpCursorRect); - } catch (RemoteException e) { - Log.w(TAG, "IME died: " + mCurId, e); - } - } - } - } - - /** - * Call {@link InputMethodSession#appPrivateCommand(String, Bundle) - * InputMethodSession.appPrivateCommand()} on the current Input Method. - * @param view Optional View that is sending the command, or null if - * you want to send the command regardless of the view that is attached - * to the input method. - * @param action Name of the command to be performed. This <em>must</em> - * be a scoped name, i.e. prefixed with a package name you own, so that - * different developers will not create conflicting commands. - * @param data Any data to include with the command. - */ - public void sendAppPrivateCommand(View view, String action, Bundle data) { - synchronized (mH) { - if ((view != null && mServedView != view) - || mCurrentTextBoxAttribute == null || mCurMethod == null) { - return; - } - try { - if (DEBUG) Log.v(TAG, "APP PRIVATE COMMAND " + action + ": " + data); - mCurMethod.appPrivateCommand(action, data); - } catch (RemoteException e) { - Log.w(TAG, "IME died: " + mCurId, e); - } - } - } - - /** - * Force switch to a new input method component. This can only be called - * from the currently active input method, as validated by the given token. - * @param token Supplies the identifying token given to an input method - * when it was started, which allows it to perform this operation on - * itself. - * @param id The unique identifier for the new input method to be switched to. - */ - public void setInputMethod(IBinder token, String id) { - try { - mService.setInputMethod(token, id); - } catch (RemoteException e) { - throw new RuntimeException(e); - } - } - - /** - * Close/hide the input method's soft input area, so the user no longer - * sees it or can interact with it. This can only be called - * from the currently active input method, as validated by the given token. - * - * @param token Supplies the identifying token given to an input method - * when it was started, which allows it to perform this operation on - * itself. - * @param flags Provides additional operating flags. Currently may be - * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set. - */ - public void hideSoftInputFromInputMethod(IBinder token, int flags) { - try { - mService.hideMySoftInput(token, flags); - } catch (RemoteException e) { - throw new RuntimeException(e); - } - } - - /** - * @hide - */ - public void dispatchKeyEvent(Context context, int seq, KeyEvent key, - IInputMethodCallback callback) { - synchronized (mH) { - if (DEBUG) Log.d(TAG, "dispatchKeyEvent"); - - if (mCurMethod == null) { - try { - callback.finishedEvent(seq, false); - } catch (RemoteException e) { - } - return; - } - - if (key.getAction() == KeyEvent.ACTION_DOWN - && key.getKeyCode() == KeyEvent.KEYCODE_SYM) { - showInputMethodPicker(); - try { - callback.finishedEvent(seq, true); - } catch (RemoteException e) { - } - return; - } - try { - if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod); - mCurMethod.dispatchKeyEvent(seq, key, callback); - } catch (RemoteException e) { - Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e); - try { - callback.finishedEvent(seq, false); - } catch (RemoteException ex) { - } - } - } - } - - /** - * @hide - */ - void dispatchTrackballEvent(Context context, int seq, MotionEvent motion, - IInputMethodCallback callback) { - synchronized (mH) { - if (DEBUG) Log.d(TAG, "dispatchTrackballEvent"); - - if (mCurMethod == null || mCurrentTextBoxAttribute == null) { - try { - callback.finishedEvent(seq, false); - } catch (RemoteException e) { - } - return; - } - - try { - if (DEBUG) Log.v(TAG, "DISPATCH TRACKBALL: " + mCurMethod); - mCurMethod.dispatchTrackballEvent(seq, motion, callback); - } catch (RemoteException e) { - Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e); - try { - callback.finishedEvent(seq, false); - } catch (RemoteException ex) { - } - } - } - } - - public void showInputMethodPicker() { - synchronized (mH) { - try { - mService.showInputMethodPickerFromClient(mClient); - } catch (RemoteException e) { - Log.w(TAG, "IME died: " + mCurId, e); - } - } - } - - void doDump(FileDescriptor fd, PrintWriter fout, String[] args) { - final Printer p = new PrintWriterPrinter(fout); - p.println("Input method client state for " + this + ":"); - - p.println(" mService=" + mService); - p.println(" mMainLooper=" + mMainLooper); - p.println(" mIInputContext=" + mIInputContext); - p.println(" mActive=" + mActive - + " mBindSequence=" + mBindSequence - + " mCurId=" + mCurId); - p.println(" mCurMethod=" + mCurMethod); - p.println(" mServedView=" + mServedView); - p.println(" mLastServedView=" + mLastServedView); - p.println(" mServedConnecting=" + mServedConnecting); - if (mCurrentTextBoxAttribute != null) { - p.println(" mCurrentTextBoxAttribute:"); - mCurrentTextBoxAttribute.dump(p, " "); - } else { - p.println(" mCurrentTextBoxAttribute: null"); - } - p.println(" mServedInputConnection=" + mServedInputConnection); - p.println(" mCompletions=" + mCompletions); - p.println(" mCursorRect=" + mCursorRect); - p.println(" mCursorSelStart=" + mCursorSelStart - + " mCursorSelEnd=" + mCursorSelEnd - + " mCursorCandStart=" + mCursorCandStart - + " mCursorCandEnd=" + mCursorCandEnd); - } -} diff --git a/core/java/android/view/inputmethod/InputMethodSession.java b/core/java/android/view/inputmethod/InputMethodSession.java deleted file mode 100644 index b5bbaff..0000000 --- a/core/java/android/view/inputmethod/InputMethodSession.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2007-2008 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.view.inputmethod; - -import android.graphics.Rect; -import android.os.Bundle; -import android.view.KeyEvent; -import android.view.MotionEvent; - -/** - * The InputMethodSession interface provides the per-client functionality - * of {@link InputMethod} that is safe to expose to applications. - * - * <p>Applications will not normally use this interface themselves, instead - * relying on the standard interaction provided by - * {@link android.widget.TextView} and {@link android.widget.EditText}. - */ -public interface InputMethodSession { - - public interface EventCallback { - void finishedEvent(int seq, boolean handled); - } - - /** - * This method is called when the application would like to stop - * receiving text input. - */ - public void finishInput(); - - /** - * This method is called when the selection or cursor in the current - * target input field has changed. - * - * @param oldSelStart The previous text offset of the cursor selection - * start position. - * @param oldSelEnd The previous text offset of the cursor selection - * end position. - * @param newSelStart The new text offset of the cursor selection - * start position. - * @param newSelEnd The new text offset of the cursor selection - * end position. - * @param candidatesStart The text offset of the current candidate - * text start position. - * @param candidatesEnd The text offset of the current candidate - * text end position. - */ - public void updateSelection(int oldSelStart, int oldSelEnd, - int newSelStart, int newSelEnd, - int candidatesStart, int candidatesEnd); - - /** - * This method is called when cursor location of the target input field - * has changed within its window. This is not normally called, but will - * only be reported if requested by the input method. - * - * @param newCursor The rectangle of the cursor currently being shown in - * the input field's window coordinates. - */ - public void updateCursor(Rect newCursor); - - /** - * Called by a text editor that performs auto completion, to tell the - * input method about the completions it has available. This can be used - * by the input method to display them to the user to select the text to - * be inserted. - * - * @param completions Array of text completions that are available, starting with - * the best. If this array is null, any existing completions will be - * removed. - */ - public void displayCompletions(CompletionInfo[] completions); - - /** - * Called by a text editor to report its new extracted text when its - * contents change. This will only be called if the input method - * calls {@link InputConnection#getExtractedText(ExtractedTextRequest, int) - * InputConnection.getExtractedText()} with the option to report updates. - * - * @param token The input method supplied token for identifying its request. - * @param text The new extracted text. - */ - public void updateExtractedText(int token, ExtractedText text); - - /** - * This method is called when a key is pressed. When done with the event, - * the implementation must call back on <var>callback</var> with its - * result. - * - * <p> - * If the input method wants to handle this event, return true, otherwise - * return false and the caller (i.e. the application) will handle the event. - * - * @param event The key event. - * - * @return Whether the input method wants to handle this event. - * - * @see #dispatchKeyUp - * @see android.view.KeyEvent - */ - public void dispatchKeyEvent(int seq, KeyEvent event, EventCallback callback); - - /** - * This method is called when there is a track ball event. - * - * <p> - * If the input method wants to handle this event, return true, otherwise - * return false and the caller (i.e. the application) will handle the event. - * - * @param event The motion event. - * - * @return Whether the input method wants to handle this event. - * - * @see android.view.MotionEvent - */ - public void dispatchTrackballEvent(int seq, MotionEvent event, EventCallback callback); - - /** - * Process a private command sent from the application to the input method. - * This can be used to provide domain-specific features that are - * only known between certain input methods and their clients. - * - * @param action Name of the command to be performed. This <em>must</em> - * be a scoped name, i.e. prefixed with a package name you own, so that - * different developers will not create conflicting commands. - * @param data Any data to include with the command. - */ - public void appPrivateCommand(String action, Bundle data); -} diff --git a/core/java/android/view/inputmethod/package.html b/core/java/android/view/inputmethod/package.html deleted file mode 100644 index 328c7b3..0000000 --- a/core/java/android/view/inputmethod/package.html +++ /dev/null @@ -1,12 +0,0 @@ -<html> -<body> -Framework classes for interaction between views and input methods (such -as soft keyboards). See {@link android.view.inputmethod.InputMethodManager} for -an overview. In most cases the main classes here are not needed for -most applications, since they are dealt with for you by -{@link android.widget.TextView}. When implementing a custom text editor, -however, you will need to implement the -{@link android.view.inputmethod.InputConnection} class to allow the current -input method to interact with your view. -</body> -</html> diff --git a/core/java/android/view/package.html b/core/java/android/view/package.html deleted file mode 100644 index 1c58765..0000000 --- a/core/java/android/view/package.html +++ /dev/null @@ -1,6 +0,0 @@ -<HTML> -<BODY> -Provides classes that expose basic user interface classes that handle -screen layout and interaction with the user. -</BODY> -</HTML>
\ No newline at end of file |