Workspace.java revision 6569f2c80e179c2f8ed73dae6b01d971ec20f005
131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/* 231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License. 631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at 731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and 1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License. 1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 17a5902524d4403885eb4c50360bf3465c6be796efJoe Onoratopackage com.android.launcher2; 1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 198edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurkaimport com.android.launcher.R; 208edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka 21495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.app.WallpaperManager; 220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.appwidget.AppWidgetManager; 238edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurkaimport android.appwidget.AppWidgetProviderInfo; 24b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.content.ComponentName; 250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.content.Context; 26cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.content.Intent; 27cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.content.pm.PackageManager; 288edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurkaimport android.content.pm.ProviderInfo; 29cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.content.res.TypedArray; 3068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport android.graphics.Canvas; 318f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport android.graphics.Paint; 32629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.graphics.Rect; 33629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.graphics.drawable.Drawable; 34a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.net.Uri; 35a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.os.IBinder; 36495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.os.Parcel; 3731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.Parcelable; 3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet; 39495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.util.Log; 405c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.view.MotionEvent; 417247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroyimport android.view.VelocityTracker; 4231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View; 434be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.view.ViewConfiguration; 446b879f0a5885274a85333531e091283405d490ccAdam Lesinskiimport android.view.ViewGroup; 4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.ViewParent; 46a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurkaimport android.view.animation.Animation; 47a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.view.animation.Animation.AnimationListener; 4831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.animation.Interpolator; 49a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.view.animation.RotateAnimation; 504be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.widget.Scroller; 51f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.widget.TextView; 525c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.widget.Toast; 53956091ba7863bd72086275e61084864994dd6fa7Joe Onorato 54495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport java.util.ArrayList; 5531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport java.util.HashSet; 56291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler 57580e27748137ff08599aa719d106b31215a28353Winson Chung/** 58a34abf8c781485b788fddacb352d586bffca886cWinson Chung * The workspace is a wide area with a wallpaper and a finite number of screens. 59a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung * Each screen contains a number of icons, folders or widgets the user can 6031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * interact with. A workspace is meant to be used with a fixed width only. 6131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 626e3140865d3f0def2e55934d8b0b2c1503386e54Winson Chungpublic class Workspace extends ViewGroup implements DropTarget, DragSource, DragScroller { 63cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy @SuppressWarnings({"UnusedDeclaration"}) 643c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka private static final String TAG = "Launcher.Workspace"; 653c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka private static final int INVALID_SCREEN = -1; 66f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project 67a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung /** 6831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * The velocity at which a fling gesture will cause us to snap to the next 698edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka * screen 708edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka */ 718edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka private static final int SNAP_VELOCITY = 600; 72edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy 7331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private final WallpaperManager mWallpaperManager; 740142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 750142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka private int mDefaultScreen; 76aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung 7731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private boolean mFirstLayout = true; 780142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 79e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy private int mCurrentScreen; 80e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy private int mNextScreen = INVALID_SCREEN; 81e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy private Scroller mScroller; 823a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato private VelocityTracker mVelocityTracker; 830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 84dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka /** 85dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka * CellInfo for the cell that is currently being dragged 86dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka */ 87a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen private CellLayout.CellInfo mDragInfo; 88d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka 89d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka /** 90d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka * Target drop area calculated during last acceptDrop call. 91f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen */ 92f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen private int[] mTargetCell = null; 93a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen 94a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen /** 95a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen * The CellLayout that is currently being dragged over 961b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen */ 97a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen private CellLayout mDragTargetLayout = null; 981b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen 99a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen private float mLastMotionX; 10068d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen private float mLastMotionY; 10168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen 1029171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung private final static int TOUCH_STATE_REST = 0; 103f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen private final static int TOUCH_STATE_SCROLLING = 1; 104f135c6c364e92cddb84c1b4a94ed535214b712a6Winson Chung 1059171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung private int mTouchState = TOUCH_STATE_REST; 1069171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung 1079171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung private OnTouchListener mInterceptTouchListener; 1089171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung private OnLongClickListener mLongClickListener; 1099171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung 1109171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung private Launcher mLauncher; 1119171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung private IconCache mIconCache; 1129171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung private DragController mDragController; 113e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka 114e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka /** 1159171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung * Cache of vacant cells, used during drag events and invalidated as needed. 1168d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung */ 11725356e75ebae5d6e0be43f38d2c73b5cb59d05f2Michael Jurka private CellLayout.CellInfo mVacantCache = null; 1188d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung 119f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen private int[] mTempCell = new int[2]; 12068d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen private int[] mTempEstimate = new int[2]; 121e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen 122f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen private boolean mAllowLongPress = true; 12388127038178b3bbf0eb91103a31e682cc0615074Winson Chung 12488127038178b3bbf0eb91103a31e682cc0615074Winson Chung private int mTouchSlop; 12588127038178b3bbf0eb91103a31e682cc0615074Winson Chung private int mMaximumVelocity; 12688127038178b3bbf0eb91103a31e682cc0615074Winson Chung 12788127038178b3bbf0eb91103a31e682cc0615074Winson Chung private static final int INVALID_POINTER = -1; 1288f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn 1299c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka private int mActivePointerId = INVALID_POINTER; 130aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung 1310142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka private Drawable mPreviousIndicator; 13231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private Drawable mNextIndicator; 133d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka 13421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen private static final float NANOTIME_DIV = 1000000000.0f; 13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private static final float SMOOTHING_SPEED = 0.75f; 13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private static final float SMOOTHING_CONSTANT = (float) (0.016 / Math.log(SMOOTHING_SPEED)); 13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private float mSmoothingTime; 13831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private float mTouchX; 139aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung 14070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey private WorkspaceOvershootInterpolator mScrollInterpolator; 14170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey 14270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey private static final float BASELINE_FLING_VELOCITY = 2500.f; 14370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey private static final float FLING_VELOCITY_INFLUENCE = 0.4f; 14431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 1456569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy private Paint mDropIndicatorPaint; 1466569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy 1476569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy private static class WorkspaceOvershootInterpolator implements Interpolator { 1486569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy private static final float DEFAULT_TENSION = 1.3f; 1496569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy private float mTension; 15031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 1510589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato public WorkspaceOvershootInterpolator() { 15200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mTension = DEFAULT_TENSION; 153aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung } 1544516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka 1554516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka public void setDistance(int distance) { 15631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mTension = distance > 0 ? DEFAULT_TENSION / distance : DEFAULT_TENSION; 15770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey } 1580280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka 159a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka public void disableSettle() { 1604516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka mTension = 0.f; 1614516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka } 162a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka 1630280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka public float getInterpolation(float t) { 16431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project // _o(t) = t * t * ((tension + 1) * t + tension) 165c2f7f4794867cd1b3e97fd0f379ad8ad15958a6cMichael Jurka // o(t) = _o(t - 1) + 1 166d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka t -= 1.0f; 167d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen return t * t * ((mTension + 1) * t + mTension) + 1.0f; 168d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen } 16931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 1708a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy 1718a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy /** 172aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung * Used to inflate the Workspace from XML. 1731262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy * 174dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka * @param context The application's context. 175c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka * @param attrs The attribtues set containing the Workspace's customization values. 176c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka */ 177bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka public Workspace(Context context, AttributeSet attrs) { 178b8e14479da7209ca811a753b3256fe4a0b49a873Michael Jurka this(context, attrs, 0); 179af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka } 180af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka 181d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka /** 182883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka * Used to inflate the Workspace from XML. 183af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka * 1843c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka * @param context The application's context. 185dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka * @param attrs The attribtues set containing the Workspace's customization values. 18654fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy * @param defStyle Unused. 1871262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy */ 1881262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy public Workspace(Context context, AttributeSet attrs, int defStyle) { 18954fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy super(context, attrs, defStyle); 19054fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy 19154fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy mWallpaperManager = WallpaperManager.getInstance(context); 1928e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy 1934be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato TypedArray a = context.obtainStyledAttributes(attrs, 1948e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy R.styleable.Workspace, defStyle, 0); 1958e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy int canonicalDeviceWidth = a.getInt(R.styleable.Workspace_canonicalDeviceWidth, 4); 1964be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato int canonicalDeviceHeight = a.getInt(R.styleable.Workspace_canonicalDeviceHeight, 4); 197cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy mDefaultScreen = a.getInt(R.styleable.Workspace_defaultScreen, 1); 198cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy a.recycle(); 199cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy 200cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy LauncherModel.updateWorkspaceLayoutCells(canonicalDeviceWidth, 201cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy canonicalDeviceHeight); 202a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung setHapticFeedbackEnabled(false); 203a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung initWorkspace(); 204a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung } 2056b879f0a5885274a85333531e091283405d490ccAdam Lesinski 2066b879f0a5885274a85333531e091283405d490ccAdam Lesinski /** 2076b879f0a5885274a85333531e091283405d490ccAdam Lesinski * Initializes various states for this workspace. 2086b879f0a5885274a85333531e091283405d490ccAdam Lesinski */ 2096b879f0a5885274a85333531e091283405d490ccAdam Lesinski private void initWorkspace() { 210c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka Context context = getContext(); 211c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka mScrollInterpolator = new WorkspaceOvershootInterpolator(); 212c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka mScroller = new Scroller(context, mScrollInterpolator); 213ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka mCurrentScreen = mDefaultScreen; 214c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka Launcher.setScreen(mCurrentScreen); 215ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka LauncherApplication app = (LauncherApplication)context.getApplicationContext(); 216c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka mIconCache = app.getIconCache(); 2170bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka 2180bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka final ViewConfiguration configuration = ViewConfiguration.get(getContext()); 2190bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka mTouchSlop = configuration.getScaledTouchSlop(); 2200bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); 2210bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka } 2220bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka 2230bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka @Override 224f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen public void addView(View child, int index, LayoutParams params) { 225f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen if (!(child instanceof CellLayout)) { 226f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen throw new IllegalArgumentException("A Workspace can only have CellLayout children."); 227f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen } 228f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen super.addView(child, index, params); 229f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen } 230f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen 23131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 23231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public void addView(View child) { 23331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (!(child instanceof CellLayout)) { 23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project throw new IllegalArgumentException("A Workspace can only have CellLayout children."); 2350142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka } 23631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super.addView(child); 23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 23931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public void addView(View child, int index) { 24131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (!(child instanceof CellLayout)) { 24231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project throw new IllegalArgumentException("A Workspace can only have CellLayout children."); 24331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 24431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super.addView(child, index); 2450142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka } 24631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 24731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 24831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public void addView(View child, int width, int height) { 24931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (!(child instanceof CellLayout)) { 2500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka throw new IllegalArgumentException("A Workspace can only have CellLayout children."); 2515f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka } 2525f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka super.addView(child, width, height); 2535f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka } 2545f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 2568f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn public void addView(View child, LayoutParams params) { 257aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung if (!(child instanceof CellLayout)) { 258aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung throw new IllegalArgumentException("A Workspace can only have CellLayout children."); 259aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung } 260d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen super.addView(child, params); 261d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen } 2620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @return The open folder on the current screen, or null if there is none 265d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen */ 2660d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato Folder getOpenFolder() { 2670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka CellLayout currentScreen = (CellLayout) getChildAt(mCurrentScreen); 26831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int count = currentScreen.getChildCount(); 269c35afb2c9df8cc56c77bf21ce2eaa213f6f31251Winson Chung for (int i = 0; i < count; i++) { 270c35afb2c9df8cc56c77bf21ce2eaa213f6f31251Winson Chung View child = currentScreen.getChildAt(i); 271c35afb2c9df8cc56c77bf21ce2eaa213f6f31251Winson Chung if (child instanceof Folder) { 27231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Folder folder = (Folder) child; 27331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (folder.getInfo().opened) 27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return folder; 27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 2770142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka return null; 2780589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } 2790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 2800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka ArrayList<Folder> getOpenFolders() { 2810589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato final int screens = getChildCount(); 2820589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato ArrayList<Folder> folders = new ArrayList<Folder>(screens); 283a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung 284cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy for (int screen = 0; screen < screens; screen++) { 28531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project CellLayout currentScreen = (CellLayout) getChildAt(screen); 286b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung int count = currentScreen.getChildCount(); 287b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung for (int i = 0; i < count; i++) { 288b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung View child = currentScreen.getChildAt(i); 2898d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child 290b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung .getLayoutParams(); 291b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung if (child instanceof Folder) { 292b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung Folder folder = (Folder) child; 2939171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung if (folder.getInfo().opened) 2948edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka folders.add(folder); 2953c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka break; 296c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka } 297c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka } 298c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka } 2990bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka 3003c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka return folders; 3018edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka } 302c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka 303ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka boolean isDefaultScreenShowing() { 3040bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka return mCurrentScreen == mDefaultScreen; 3050bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka } 3060bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka 3070bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka /** 3080bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka * Returns the index of the currently displayed screen. 3090bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka * 3100bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka * @return The index of the currently displayed screen. 3110bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka */ 312a58f8bb1947af39d4d18d849b3e4d6bd0d3954d7Winson Chung int getCurrentScreen() { 313a58f8bb1947af39d4d18d849b3e4d6bd0d3954d7Winson Chung return mCurrentScreen; 314ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka } 31560b7c53ccc6384b65aaca77d97794e8f09e8cfc8Patrick Dubroy 316ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka /** 317bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka * Sets the current screen. 318bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka * 319bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka * @param currentScreen 320bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka */ 321ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka void setCurrentScreen(int currentScreen) { 322ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka if (!mScroller.isFinished()) 323ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka mScroller.abortAnimation(); 324ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka clearVacantCache(); 325bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1)); 326ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka if (mPreviousIndicator != null) { 32760b7c53ccc6384b65aaca77d97794e8f09e8cfc8Patrick Dubroy mPreviousIndicator.setLevel(mCurrentScreen); 328dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka mNextIndicator.setLevel(mCurrentScreen); 329dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka } 3300142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 331ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka scrollTo(mCurrentScreen * getWidth(), 0); 33231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project updateWallpaperOffset(); 33331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project invalidate(); 33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 335f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen 336f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen /** 337e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen * Adds the specified child in the current screen. The position and dimension of 338f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen * the child are defined by x, y, spanX and spanY. 339e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen * 340f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen * @param child The child to add in one of the workspace's screens. 341f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen * @param x The X position of the child in the screen's grid. 342f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen * @param y The Y position of the child in the screen's grid. 343f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen * @param spanX The number of cells spanned horizontally by the child. 34431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param spanY The number of cells spanned vertically by the child. 34531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project void addInCurrentScreen(View child, int x, int y, int spanX, int spanY) { 34731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project addInScreen(child, mCurrentScreen, x, y, spanX, spanY, false); 34821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen } 349e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy 350e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy /** 35131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Adds the specified child in the current screen. The position and dimension of 35231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * the child are defined by x, y, spanX and spanY. 35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param child The child to add in one of the workspace's screens. 35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param x The X position of the child in the screen's grid. 35631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param y The Y position of the child in the screen's grid. 35731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param spanX The number of cells spanned horizontally by the child. 35831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param spanY The number of cells spanned vertically by the child. 35921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen * @param insert When true, the child is inserted at the beginning of the children list. 360e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy */ 361e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy void addInCurrentScreen(View child, int x, int y, int spanX, int spanY, boolean insert) { 36231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project addInScreen(child, mCurrentScreen, x, y, spanX, spanY, insert); 36331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 36431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 36531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 36631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Adds the specified child in the specified screen. The position and dimension of 36731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * the child are defined by x, y, spanX and spanY. 36831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 36931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param child The child to add in one of the workspace's screens. 37021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen * @param screen The screen in which to add the child. 371e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy * @param x The X position of the child in the screen's grid. 372e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy * @param y The Y position of the child in the screen's grid. 37331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param spanX The number of cells spanned horizontally by the child. 37431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param spanY The number of cells spanned vertically by the child. 37531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 37631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) { 37731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project addInScreen(child, screen, x, y, spanX, spanY, false); 37831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 37931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 38031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project void addInFullScreen(View child, int screen) { 38121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen addInScreen(child, screen, 0, 0, -1, -1); 382e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy } 383e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy 38431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public void rotateCurrentScreensChildren() { 38531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 38631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project // close all the folders first 38731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final ArrayList<Folder> openFolders = getOpenFolders(); 38831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 38931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project WorkspaceOvershootInterpolator wi = new WorkspaceOvershootInterpolator(); 39031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project RotateAnimation ra = new RotateAnimation((float) LauncherModel 39131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project .getPreviousOrientationRelativeToCurrent(), 0, 39221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 393e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy 0.5f); 394e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy ra.setInterpolator(wi); 39531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project CellLayout currentScreen = (CellLayout) getChildAt(mCurrentScreen); 39631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project ra.setStartOffset(150); 39731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project ra.setDuration(650 + (int) (Math.random() * 400) - 200); 39831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 39931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project CellLayout.CellLayoutAnimationController animationController = new CellLayout.CellLayoutAnimationController( 40031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project ra, 0.0f); 40131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project currentScreen.setLayoutAnimation(animationController); 4026e3140865d3f0def2e55934d8b0b2c1503386e54Winson Chung currentScreen.setLayoutAnimationListener(new AnimationListener() { 4030142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka public void onAnimationStart(Animation animation) { 40431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project // do nothing 4050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka } 406aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung 407aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung public void onAnimationRepeat(Animation animation) { 408aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung // do nothing 409aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung } 41031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 41131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public void onAnimationEnd(Animation animation) { 41231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project for (int j = 0; j < openFolders.size(); ++j) { 41331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Folder folder = openFolders.get(j); 41431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (!folder.getInfo().opened) { 41531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mLauncher.openFolder(folder.getInfo()); 416dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka } 417dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka } 41831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 419dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka }); 4206e3140865d3f0def2e55934d8b0b2c1503386e54Winson Chung animationController.start(); 4210142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 42231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project for (int j = 0; j < openFolders.size(); ++j) { 4230142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka mLauncher.closeFolder(openFolders.get(j)); 424aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung } 425aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung } 426aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung 427aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung public void refreshWorkspaceChildren() { 42831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int count = getChildCount(); 42931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project View child; 43031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 43131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project CellLayout.LayoutParams lp; 43231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int widthMeasureSpec = MeasureSpec.makeMeasureSpec(LauncherModel 43331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project .getLocalDeviceWidth(), MeasureSpec.EXACTLY); 43431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int heightMeasureSpec = MeasureSpec.makeMeasureSpec(LauncherModel 435a0aa0121b91fde17e427ab2763ce312e64cf5d33Patrick Dubroy .getLocalDeviceHeight(), MeasureSpec.EXACTLY); 436a0aa0121b91fde17e427ab2763ce312e64cf5d33Patrick Dubroy 43731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project clearVacantCache(); 43831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 43931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project for (int i = 0; i < count; i++) { 44031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final CellLayout layout = (CellLayout) getChildAt(i); 44131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int numChildren = layout.getChildCount(); 44231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 44331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project // save reference to all current children 44431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project for (int j = 0; j < numChildren; j++) { 44531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project child = layout.getChildAt(j); 44631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 44731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project lp = (CellLayout.LayoutParams) child.getLayoutParams(); 44831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project LauncherModelOrientationHelper.Coordinates localCoord = LauncherModel 44931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project .getLocalCoordinatesFromPreviousLocalCoordinates(lp); 45031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 45131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project lp.cellX = localCoord.x; 45231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project lp.cellY = localCoord.y; 45331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 454aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung 455aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung layout.measure(widthMeasureSpec, heightMeasureSpec); 456aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung } 457aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung } 45831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 45931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 46031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Adds the specified child in the specified screen. The position and dimension of 46131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * the child are defined by x, y, spanX and spanY. 46231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 46331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param child The child to add in one of the workspace's screens. 46431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param screen The screen in which to add the child. 46531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param x The X position of the child in the screen's grid. 46631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param y The Y position of the child in the screen's grid. 46731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param spanX The number of cells spanned horizontally by the child. 46831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param spanY The number of cells spanned vertically by the child. 46931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param insert When true, the child is inserted at the beginning of the children list. 47031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 47131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) { 472291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler if (screen < 0 || screen >= getChildCount()) { 473291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler Log.e(TAG, "The screen must be >= 0 and < " + getChildCount() 474291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler + " (was " + screen + "); skipping child"); 47531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return; 47631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 47731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 47831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project clearVacantCache(); 47931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 48031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final CellLayout group = (CellLayout) getChildAt(screen); 48131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 48231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (lp == null) { 48331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project lp = new CellLayout.LayoutParams(x, y, spanX, spanY); 48431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } else { 48531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project lp.cellX = x; 48631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project lp.cellY = y; 487aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung lp.cellHSpan = spanX; 4886569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy lp.cellVSpan = spanY; 489845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka } 490f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka 491f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka // Get the canonical child id to uniquely represent this view in this screen 492aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung int childId = LauncherModel.getCanonicalCellLayoutChildId(child.getId(), screen, x, y, spanX, spanY); 493aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp)) { 4946569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy // TODO: This branch occurs when the workspace is adding views 495aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung // outside of the defined grid 496aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung // maybe we should be deleting these items from the LauncherModel? 497aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout"); 49831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 4990d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato 50031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (!(child instanceof Folder)) { 50131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project child.setHapticFeedbackEnabled(false); 50200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato child.setOnLongClickListener(mLongClickListener); 503aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung } 50400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato if (child instanceof DropTarget) { 50531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mDragController.addDropTarget((DropTarget) child); 50631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 507d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy } 508d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy 509d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy CellLayout.CellInfo findAllVacantCells(boolean[] occupied) { 510d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy CellLayout group = (CellLayout) getChildAt(mCurrentScreen); 511d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy if (group != null) { 512d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy return group.findAllVacantCells(occupied, null); 513d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy } 514d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy return null; 515d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy } 516d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy 517d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy private void clearVacantCache() { 518d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy if (mVacantCache != null) { 519d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy mVacantCache.clearVacantCells(); 520d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy mVacantCache = null; 521d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy } 522d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy } 523d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy 524d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy public void setOnInterceptTouchListener(View.OnTouchListener listener) { 525d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy mInterceptTouchListener = listener; 526d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy } 527d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy 528d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy /** 529d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy * Registers the specified listener on each screen contained in this workspace. 530d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy * 531d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy * @param l The listener used to respond to long clicks. 532d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy */ 533d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy @Override 534d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy public void setOnLongClickListener(OnLongClickListener l) { 535d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy mLongClickListener = l; 536d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy final int count = getChildCount(); 537e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy for (int i = 0; i < count; i++) { 538e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy getChildAt(i).setOnLongClickListener(l); 539e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy } 540e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy } 541e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy 542e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy private void updateWallpaperOffset() { 543dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft)); 544e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy } 545e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy 546e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy private void updateWallpaperOffset(int scrollRange) { 547e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy IBinder token = getWindowToken(); 548e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy if (token != null) { 549e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 ); 550e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy mWallpaperManager.setWallpaperOffsets(getWindowToken(), 551e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0); 552e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy } 553e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy } 554e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy 555dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka @Override 5560e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka public void scrollTo(int x, int y) { 5570e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka super.scrollTo(x, y); 558ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen mTouchX = x; 559ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen mSmoothingTime = System.nanoTime() / NANOTIME_DIV; 560ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen } 561ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen 5625f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka @Override 5635f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka public void computeScroll() { 564c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka if (mScroller.computeScrollOffset()) { 5655f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka mTouchX = mScrollX = mScroller.getCurrX(); 5665f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka mSmoothingTime = System.nanoTime() / NANOTIME_DIV; 5675f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka mScrollY = mScroller.getCurrY(); 5685f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka updateWallpaperOffset(); 5695f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka postInvalidate(); 5705f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka } else if (mNextScreen != INVALID_SCREEN) { 5715f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1)); 5725f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka if (mPreviousIndicator != null) { 573f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen mPreviousIndicator.setLevel(mCurrentScreen); 574f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen mNextIndicator.setLevel(mCurrentScreen); 575f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen } 576f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen Launcher.setScreen(mCurrentScreen); 577f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen mNextScreen = INVALID_SCREEN; 578c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka clearChildrenCache(); 579e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy } else if (mTouchState == TOUCH_STATE_SCROLLING) { 5806b879f0a5885274a85333531e091283405d490ccAdam Lesinski final float now = System.nanoTime() / NANOTIME_DIV; 5816b879f0a5885274a85333531e091283405d490ccAdam Lesinski final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT); 582be9093426aec3a6d412811a12d2400e645613242Adam Cohen final float dx = mTouchX - mScrollX; 583be9093426aec3a6d412811a12d2400e645613242Adam Cohen mScrollX += dx * e; 584be9093426aec3a6d412811a12d2400e645613242Adam Cohen mSmoothingTime = now; 585be9093426aec3a6d412811a12d2400e645613242Adam Cohen 586be9093426aec3a6d412811a12d2400e645613242Adam Cohen // Keep generating points as long as we're more than 1px away from the target 5876b879f0a5885274a85333531e091283405d490ccAdam Lesinski if (dx > 1.f || dx < -1.f) { 5886b879f0a5885274a85333531e091283405d490ccAdam Lesinski updateWallpaperOffset(); 5895f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka postInvalidate(); 5905f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka } 5915f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka } 5925f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka } 5935f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka 5941adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka @Override 5951adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka protected void dispatchDraw(Canvas canvas) { 59669c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen boolean restore = false; 59769c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen int restoreCount = 0; 59869c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen 599f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen // ViewGroup.dispatchDraw() supports many features we don't need: 60069c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen // clip to padding, layout animation, animation listener, disappearing 601f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen // children, etc. The following implementation attempts to fast-track 60269c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen // the drawing dispatch by drawing only what we know needs to be drawn. 60369c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen 604f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN; 60569c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen // If we are not scrolling or flinging, draw only the current screen 60669c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen if (fastDraw) { 60769c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime()); 608f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen } else { 60969c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen final long drawingTime = getDrawingTime(); 61069c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen final float scrollPos = (float) mScrollX / getWidth(); 61169c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen final int leftScreen = (int) scrollPos; 61269c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen final int rightScreen = leftScreen + 1; 61369c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen if (leftScreen >= 0) { 61469c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen drawChild(canvas, getChildAt(leftScreen), drawingTime); 61569c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen } 61669c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen if (scrollPos != leftScreen && rightScreen < getChildCount()) { 61769c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen drawChild(canvas, getChildAt(rightScreen), drawingTime); 61869c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen } 61969c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen } 62069c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen 62169c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen if (restore) { 62269c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen canvas.restoreToCount(restoreCount); 62369c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen } 62469c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen } 625f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen 6261adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka protected void onAttachedToWindow() { 6271adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka super.onAttachedToWindow(); 6281262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy computeScroll(); 6290142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka mDragController.setWindowToken(getWindowToken()); 6300142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka } 63116fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka 6320142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka @Override 6330142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 6340142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka super.onMeasure(widthMeasureSpec, heightMeasureSpec); 63516fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka 63631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int width = MeasureSpec.getSize(widthMeasureSpec); 637f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 63831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (widthMode != MeasureSpec.EXACTLY) { 63931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project throw new IllegalStateException("Workspace can only be used in EXACTLY mode."); 6401262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy } 64116fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka 6421262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 6431262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy if (heightMode != MeasureSpec.EXACTLY) { 6441262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy throw new IllegalStateException("Workspace can only be used in EXACTLY mode."); 6451262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy } 64668d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen 647e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen // The children are given the same width and height as the workspace 6480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka final int count = getChildCount(); 6490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka for (int i = 0; i < count; i++) { 6500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); 6510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka } 6520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 6530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka if (mFirstLayout) { 6540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka setHorizontalScrollBarEnabled(false); 6550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka scrollTo(mCurrentScreen * width, 0); 6560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka setHorizontalScrollBarEnabled(true); 6570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka updateWallpaperOffset(width * (getChildCount() - 1)); 6580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka mFirstLayout = false; 6590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka } 6600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka } 6610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 6620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka @Override 6630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 6640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka int childLeft = 0; 6650142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 6660142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka final int count = getChildCount(); 667c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka for (int i = 0; i < count; i++) { 668c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka final View child = getChildAt(i); 669c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka if (child.getVisibility() != View.GONE) { 670c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka final int childWidth = child.getMeasuredWidth(); 671c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight()); 672c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka childLeft += childWidth; 673c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 674c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 675c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka 676c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka if (LauncherApplication.isInPlaceRotationEnabled()) { 677c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka // When the device is rotated, the scroll position of the current screen 678c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka // needs to be refreshed 679c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka setCurrentScreen(getCurrentScreen()); 680c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 681c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 682c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka 683c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka @Override 684c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) { 685c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka int screen = indexOfChild(child); 686c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka if (screen != mCurrentScreen || !mScroller.isFinished()) { 687c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka if (!mLauncher.isWorkspaceLocked()) { 688c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka snapToScreen(screen); 689c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 690c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka return true; 691c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 692c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka return false; 693c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 694c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka 695c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka @Override 696c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { 697c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka if (!mLauncher.isAllAppsVisible()) { 698c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka final Folder openFolder = getOpenFolder(); 699c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka if (openFolder != null) { 700c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka return openFolder.requestFocus(direction, previouslyFocusedRect); 701c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } else { 702c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka int focusableScreen; 703c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka if (mNextScreen != INVALID_SCREEN) { 704c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka focusableScreen = mNextScreen; 705c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } else { 706c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka focusableScreen = mCurrentScreen; 707c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 708c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka getChildAt(focusableScreen).requestFocus(direction, previouslyFocusedRect); 709c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 710c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 711c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka return false; 712c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 713c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka 714f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung @Override 715f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung public boolean dispatchUnhandledMove(View focused, int direction) { 716f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung if (direction == View.FOCUS_LEFT) { 717f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung if (getCurrentScreen() > 0) { 718f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung snapToScreen(getCurrentScreen() - 1); 719c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka return true; 720c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 721ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } else if (direction == View.FOCUS_RIGHT) { 722ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (getCurrentScreen() < getChildCount() - 1) { 723ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka snapToScreen(getCurrentScreen() + 1); 724ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka return true; 725ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 726ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 727ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka return super.dispatchUnhandledMove(focused, direction); 728ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 729ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 730ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka @Override 731ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka public void addFocusables(ArrayList<View> views, int direction, int focusableMode) { 732c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka if (!mLauncher.isAllAppsVisible()) { 733c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka final Folder openFolder = getOpenFolder(); 734ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (openFolder == null) { 735ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka getChildAt(mCurrentScreen).addFocusables(views, direction); 736f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka if (direction == View.FOCUS_LEFT) { 737ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (mCurrentScreen > 0) { 738ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka getChildAt(mCurrentScreen - 1).addFocusables(views, direction); 739ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 740ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } else if (direction == View.FOCUS_RIGHT) { 741ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (mCurrentScreen < getChildCount() - 1) { 742f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka getChildAt(mCurrentScreen + 1).addFocusables(views, direction); 743f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka } 744f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka } 745ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } else { 746ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka openFolder.addFocusables(views, direction); 747ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 748ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 749ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 750ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 75109d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka @Override 75209d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka public boolean dispatchTouchEvent(MotionEvent ev) { 75309d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka if (ev.getAction() == MotionEvent.ACTION_DOWN) { 75409d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka if (mLauncher.isWorkspaceLocked() || mLauncher.isAllAppsVisible()) { 75509d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka return false; 75609d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka } 75709d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka } 75809d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka return super.dispatchTouchEvent(ev); 75909d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka } 76009d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka 76109d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka @Override 76209d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka public boolean onInterceptTouchEvent(MotionEvent ev) { 76309d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka if (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev)) { 764ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka return true; 76509d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka } 766ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final boolean workspaceLocked = mLauncher.isWorkspaceLocked(); 767f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka final boolean allAppsVisible = mLauncher.isAllAppsVisible(); 768ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (workspaceLocked || allAppsVisible) { 769ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka return false; // We don't want the events. Let them fall through to the all apps view. 770ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 771ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 772340c5f3a708efa280a120708594247952ca65182Michael Jurka /* 773ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka * This method JUST determines whether we want to intercept the motion. 774c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka * If we return true, onTouchEvent will be called and we do the actual 775c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka * scrolling there. 776c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka */ 777c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka 778c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka /* 779c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka * Shortcut the most recurring case: the user is in the dragging 780c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka * state and he is moving his finger. We want to intercept this 781ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka * motion. 782ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka */ 783ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final int action = ev.getAction(); 784ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) { 785ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka return true; 786ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 787ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 788ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (mVelocityTracker == null) { 789c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka mVelocityTracker = VelocityTracker.obtain(); 790ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 791ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka mVelocityTracker.addMovement(ev); 792ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 7939c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka switch (action & MotionEvent.ACTION_MASK) { 7949c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka case MotionEvent.ACTION_MOVE: { 795ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka /* 796ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check 797ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka * whether the user has moved far enough from his original down touch. 798ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka */ 7992763be3150d429d338b9848286e9365b4052c100Michael Jurka 800956091ba7863bd72086275e61084864994dd6fa7Joe Onorato /* 801ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka * Locally do absolute value. mLastMotionX is set to the y value 802ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka * of the down event. 803ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka */ 804ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final int pointerIndex = ev.findPointerIndex(mActivePointerId); 805ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final float x = ev.getX(pointerIndex); 806ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final float y = ev.getY(pointerIndex); 807ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final int xDiff = (int) Math.abs(x - mLastMotionX); 808ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final int yDiff = (int) Math.abs(y - mLastMotionY); 809ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka 810ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka final int touchSlop = mTouchSlop; 811ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka boolean xMoved = xDiff > touchSlop; 812ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka boolean yMoved = yDiff > touchSlop; 813ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 814ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (xMoved || yMoved) { 815ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 816ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (xMoved) { 817ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka // Scroll if the user moved far enough along the X axis 818ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mTouchState = TOUCH_STATE_SCROLLING; 819ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mLastMotionX = x; 820ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mTouchX = mScrollX; 821ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mSmoothingTime = System.nanoTime() / NANOTIME_DIV; 822ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1); 823ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka } 824ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka // Either way, cancel any pending longpress 825ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka if (mAllowLongPress) { 826ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mAllowLongPress = false; 827ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka // Try canceling the long press. It could also have been scheduled 828ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka // by a distant descendant, so use the mAllowLongPress flag to block 829ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka // everything 830ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final View currentScreen = getChildAt(mCurrentScreen); 831ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka currentScreen.cancelLongPress(); 832ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka } 833ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 834ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka break; 835ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 836ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 837ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka case MotionEvent.ACTION_DOWN: { 838ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final float x = ev.getX(); 839ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final float y = ev.getY(); 840ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka // Remember location of down touch 841ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka mLastMotionX = x; 842ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mLastMotionY = y; 843ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mActivePointerId = ev.getPointerId(0); 844ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mAllowLongPress = true; 845ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka 846ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka /* 847ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka * If being flinged and user touches the screen, initiate drag; 848ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka * otherwise don't. mScroller.isFinished should be false when 849ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka * being flinged. 850ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka */ 851ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING; 852ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka break; 853ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka } 854ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka 855ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka case MotionEvent.ACTION_CANCEL: 856ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka case MotionEvent.ACTION_UP: 857ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka 858ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka if (mTouchState != TOUCH_STATE_SCROLLING) { 859ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka final CellLayout currentScreen = (CellLayout)getChildAt(mCurrentScreen); 860ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka if (!currentScreen.lastDownOnOccupiedCell()) { 861ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka getLocationOnScreen(mTempCell); 862ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka // Send a tap to the wallpaper if the last down was on empty space 863ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final int pointerIndex = ev.findPointerIndex(mActivePointerId); 864ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka mWallpaperManager.sendWallpaperCommand(getWindowToken(), 865ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka "android.wallpaper.tap", 866ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mTempCell[0] + (int) ev.getX(pointerIndex), 867ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mTempCell[1] + (int) ev.getY(pointerIndex), 0, null); 868ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 869ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 870ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 871ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka // Release the drag 872ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka clearChildrenCache(); 873ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mTouchState = TOUCH_STATE_REST; 874ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka mActivePointerId = INVALID_POINTER; 875ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mAllowLongPress = false; 876ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 877ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (mVelocityTracker != null) { 878ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka mVelocityTracker.recycle(); 879ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka mVelocityTracker = null; 880ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 881ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 882ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka break; 883ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 884ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka case MotionEvent.ACTION_POINTER_UP: 885ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka onSecondaryPointerUp(ev); 886ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka break; 887ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 888ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 889ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka /* 890ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka * The only time we want to intercept motion events is if we are in the 891ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka * drag mode. 892ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka */ 893ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka return mTouchState != TOUCH_STATE_REST; 894ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 895ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 896ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka private void onSecondaryPointerUp(MotionEvent ev) { 897ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> 898ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka MotionEvent.ACTION_POINTER_INDEX_SHIFT; 899ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final int pointerId = ev.getPointerId(pointerIndex); 900ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (pointerId == mActivePointerId) { 901ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka // This was our active pointer going up. Choose a new 902ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka // active pointer and adjust accordingly. 903ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka // TODO: Make this decision more intelligent. 904ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 905ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka mLastMotionX = ev.getX(newPointerIndex); 906ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka mLastMotionY = ev.getY(newPointerIndex); 907ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka mActivePointerId = ev.getPointerId(newPointerIndex); 908ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (mVelocityTracker != null) { 909ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka mVelocityTracker.clear(); 910ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 911ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 9128f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn } 913aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung 914340c5f3a708efa280a120708594247952ca65182Michael Jurka /** 915340c5f3a708efa280a120708594247952ca65182Michael Jurka * If one of our descendant views decides that it could be focused now, only 916340c5f3a708efa280a120708594247952ca65182Michael Jurka * pass that along if it's on the current screen. 917ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka * 918ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka * This happens when live folders requery, and if they're off screen, they 919ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka * end up calling requestFocus, which pulls it on screen. 920340c5f3a708efa280a120708594247952ca65182Michael Jurka */ 921340c5f3a708efa280a120708594247952ca65182Michael Jurka @Override 92294f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy public void focusableViewAvailable(View focused) { 9233e7c7634531302271270c8cf418abc959d621cbcMichael Jurka View current = getChildAt(mCurrentScreen); 9249171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung View v = focused; 9259171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung while (true) { 9269171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung if (v == current) { 9279171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung super.focusableViewAvailable(focused); 9289171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung return; 9293e7c7634531302271270c8cf418abc959d621cbcMichael Jurka } 930f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen if (v == this) { 931f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen return; 93294f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy } 9333e7c7634531302271270c8cf418abc959d621cbcMichael Jurka ViewParent parent = v.getParent(); 9349171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung if (parent instanceof View) { 9359171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung v = (View) v.getParent(); 9369171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung } else { 9379171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung return; 9389171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung } 9399171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung } 9403e7c7634531302271270c8cf418abc959d621cbcMichael Jurka } 941f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen 942f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen void enableChildrenCache(int fromScreen, int toScreen) { 94394f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy if (fromScreen > toScreen) { 94494f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy final int temp = fromScreen; 94594f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy fromScreen = toScreen; 94694f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy toScreen = temp; 94794f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy } 94894f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy 9499171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung final int count = getChildCount(); 9509171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung 951f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen fromScreen = Math.max(fromScreen, 0); 952f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen toScreen = Math.min(toScreen, count - 1); 953f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen 954f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen for (int i = fromScreen; i <= toScreen; i++) { 955f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen final CellLayout layout = (CellLayout) getChildAt(i); 956f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen layout.setChildrenDrawnWithCacheEnabled(true); 9579171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung layout.setChildrenDrawingCacheEnabled(true); 9589171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung } 9599171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung } 9609171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung 9619c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka void clearChildrenCache() { 9629c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka final int count = getChildCount(); 9639c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka for (int i = 0; i < count; i++) { 9649c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka final CellLayout layout = (CellLayout) getChildAt(i); 9659c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka layout.setChildrenDrawnWithCacheEnabled(false); 9669c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka } 9679c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka } 968760e5375f003accf04f789e90a919ed476d4c335Winson Chung 969760e5375f003accf04f789e90a919ed476d4c335Winson Chung @Override 970760e5375f003accf04f789e90a919ed476d4c335Winson Chung public boolean onTouchEvent(MotionEvent ev) { 971760e5375f003accf04f789e90a919ed476d4c335Winson Chung 972760e5375f003accf04f789e90a919ed476d4c335Winson Chung if (mLauncher.isWorkspaceLocked()) { 9738d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung return false; // We don't want the events. Let them fall through to the all apps view. 9748d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung } 9758d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung if (mLauncher.isAllAppsVisible()) { 9768d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung // Cancel any scrolling that is in progress. 9778d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung if (!mScroller.isFinished()) { 9788d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung mScroller.abortAnimation(); 979b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung } 9809171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung snapToScreen(mCurrentScreen); 9819171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung return false; // We don't want the events. Let them fall through to the all apps view. 982e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka } 983e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka 984e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka if (mVelocityTracker == null) { 985e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka mVelocityTracker = VelocityTracker.obtain(); 986e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka } 987e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka mVelocityTracker.addMovement(ev); 988f135c6c364e92cddb84c1b4a94ed535214b712a6Winson Chung 9899171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung final int action = ev.getAction(); 9909171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung 9919171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung switch (action & MotionEvent.ACTION_MASK) { 9929171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung case MotionEvent.ACTION_DOWN: 9938d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung /* 994b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung * If being flinged and user touches, stop the fling. isFinished 9959171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung * will be false if being flinged. 9969171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung */ 997e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka if (!mScroller.isFinished()) { 998e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka mScroller.abortAnimation(); 999e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka } 1000e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka 1001e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka // Remember where the motion event started 1002e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka mLastMotionX = ev.getX(); 1003f135c6c364e92cddb84c1b4a94ed535214b712a6Winson Chung mActivePointerId = ev.getPointerId(0); 10049171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung if (mTouchState == TOUCH_STATE_SCROLLING) { 10059171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1); 10069171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung } 10079171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung break; 10089171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung case MotionEvent.ACTION_MOVE: 10099c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka if (mTouchState == TOUCH_STATE_SCROLLING) { 10109c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka // Scroll to follow the motion event 10119c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka final int pointerIndex = ev.findPointerIndex(mActivePointerId); 10129c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka final float x = ev.getX(pointerIndex); 10139171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung final float deltaX = mLastMotionX - x; 10149171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung mLastMotionX = x; 1015f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen 1016f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen if (deltaX < 0) { 1017f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen if (mTouchX > 0) { 1018f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen mTouchX += Math.max(-mTouchX, deltaX); 10196b879f0a5885274a85333531e091283405d490ccAdam Lesinski mSmoothingTime = System.nanoTime() / NANOTIME_DIV; 10206b879f0a5885274a85333531e091283405d490ccAdam Lesinski invalidate(); 10216b879f0a5885274a85333531e091283405d490ccAdam Lesinski } 10226b879f0a5885274a85333531e091283405d490ccAdam Lesinski } else if (deltaX > 0) { 10236b879f0a5885274a85333531e091283405d490ccAdam Lesinski final float availableToScroll = getChildAt(getChildCount() - 1).getRight() - 10246b879f0a5885274a85333531e091283405d490ccAdam Lesinski mTouchX - getWidth(); 10256b879f0a5885274a85333531e091283405d490ccAdam Lesinski if (availableToScroll > 0) { 10266b879f0a5885274a85333531e091283405d490ccAdam Lesinski mTouchX += Math.min(availableToScroll, deltaX); 10276b879f0a5885274a85333531e091283405d490ccAdam Lesinski mSmoothingTime = System.nanoTime() / NANOTIME_DIV; 10286b879f0a5885274a85333531e091283405d490ccAdam Lesinski invalidate(); 10296b879f0a5885274a85333531e091283405d490ccAdam Lesinski } 10306b879f0a5885274a85333531e091283405d490ccAdam Lesinski } else { 10316b879f0a5885274a85333531e091283405d490ccAdam Lesinski awakenScrollBars(); 10326b879f0a5885274a85333531e091283405d490ccAdam Lesinski } 10336b879f0a5885274a85333531e091283405d490ccAdam Lesinski } 10346b879f0a5885274a85333531e091283405d490ccAdam Lesinski break; 10356b879f0a5885274a85333531e091283405d490ccAdam Lesinski case MotionEvent.ACTION_UP: 10366b879f0a5885274a85333531e091283405d490ccAdam Lesinski if (mTouchState == TOUCH_STATE_SCROLLING) { 10376b879f0a5885274a85333531e091283405d490ccAdam Lesinski final VelocityTracker velocityTracker = mVelocityTracker; 10386b879f0a5885274a85333531e091283405d490ccAdam Lesinski velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); 10396b879f0a5885274a85333531e091283405d490ccAdam Lesinski final int velocityX = (int) velocityTracker.getXVelocity(mActivePointerId); 10406b879f0a5885274a85333531e091283405d490ccAdam Lesinski 10416b879f0a5885274a85333531e091283405d490ccAdam Lesinski final int screenWidth = getWidth(); 10426b879f0a5885274a85333531e091283405d490ccAdam Lesinski final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth; 10436b879f0a5885274a85333531e091283405d490ccAdam Lesinski final float scrolledPos = (float) mScrollX / screenWidth; 104468d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen 104568d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) { 104668d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen // Fling hard enough to move left. 104768d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen // Don't fling across more than one screen at a time. 104868d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen final int bound = scrolledPos < whichScreen ? 104968d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen mCurrentScreen - 1 : mCurrentScreen; 105068d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen snapToScreen(Math.min(whichScreen, bound), velocityX, true); 105168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen } else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) { 105268d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen // Fling hard enough to move right 105368d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen // Don't fling across more than one screen at a time. 105468d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen final int bound = scrolledPos > whichScreen ? 105568d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen mCurrentScreen + 1 : mCurrentScreen; 105668d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen snapToScreen(Math.max(whichScreen, bound), velocityX, true); 1057e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen } else { 105868d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen snapToScreen(whichScreen, 0, true); 105968d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen } 106068d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen 106168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen if (mVelocityTracker != null) { 106268d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen mVelocityTracker.recycle(); 106368d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen mVelocityTracker = null; 106468d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen } 106568d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen } 106668d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen mTouchState = TOUCH_STATE_REST; 106768d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen mActivePointerId = INVALID_POINTER; 1068f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen break; 1069f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen case MotionEvent.ACTION_CANCEL: 107021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen mTouchState = TOUCH_STATE_REST; 107168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen mActivePointerId = INVALID_POINTER; 107221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen break; 10731b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen case MotionEvent.ACTION_POINTER_UP: 10741b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen onSecondaryPointerUp(ev); 1075d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka break; 107621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen } 107721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen 1078f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen return true; 1079ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen } 108021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen 108121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen void snapToScreen(int whichScreen) { 1082f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen snapToScreen(whichScreen, 0, false); 1083e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen } 1084e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen 1085e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen private void snapToScreen(int whichScreen, int velocity, boolean settle) { 1086e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen // if (!mScroller.isFinished()) return; 1087e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen 1088e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1)); 1089e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen 1090e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen clearVacantCache(); 1091e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen enableChildrenCache(mCurrentScreen, whichScreen); 1092e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen 1093e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen mNextScreen = whichScreen; 10941b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen 109521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen if (mPreviousIndicator != null) { 10966b879f0a5885274a85333531e091283405d490ccAdam Lesinski mPreviousIndicator.setLevel(mNextScreen); 10976b879f0a5885274a85333531e091283405d490ccAdam Lesinski mNextIndicator.setLevel(mNextScreen); 109868d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen } 10991b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen 1100f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen View focusedChild = getFocusedChild(); 1101f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen if (focusedChild != null && whichScreen != mCurrentScreen && 1102f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen focusedChild == getChildAt(mCurrentScreen)) { 1103f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen focusedChild.clearFocus(); 110400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 110500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 11069c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka final int screenDelta = Math.max(1, Math.abs(whichScreen - mCurrentScreen)); 1107956091ba7863bd72086275e61084864994dd6fa7Joe Onorato final int newX = whichScreen * getWidth(); 11089c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka final int delta = newX - mScrollX; 11099c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka int duration = (screenDelta + 1) * 100; 11109c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka 11119c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka if (!mScroller.isFinished()) { 11129c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka mScroller.abortAnimation(); 111300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato } 111400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato 111531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (settle) { 111628750fba6a2d141eb9a1e566718c17236030b815Michael Jurka mScrollInterpolator.setDistance(screenDelta); 1117c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } else { 1118c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka mScrollInterpolator.disableSettle(); 1119c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka } 11200142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 1121aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung velocity = Math.abs(velocity); 112279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka if (velocity > 0) { 112379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka duration += (duration / (velocity / BASELINE_FLING_VELOCITY)) 1124883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka * FLING_VELOCITY_INFLUENCE; 1125696a67969d657d38eff33996633f08da0e21841fAdam Cohen } else { 1126696a67969d657d38eff33996633f08da0e21841fAdam Cohen duration += 100; 1127696a67969d657d38eff33996633f08da0e21841fAdam Cohen } 1128696a67969d657d38eff33996633f08da0e21841fAdam Cohen 1129696a67969d657d38eff33996633f08da0e21841fAdam Cohen awakenScrollBars(duration); 1130696a67969d657d38eff33996633f08da0e21841fAdam Cohen mScroller.startScroll(mScrollX, 0, delta, 0, duration); 1131696a67969d657d38eff33996633f08da0e21841fAdam Cohen invalidate(); 1132696a67969d657d38eff33996633f08da0e21841fAdam Cohen } 113379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka 113479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka void startDrag(CellLayout.CellInfo cellInfo) { 1135aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung View child = cellInfo.cell; 1136aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung 1137aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung // Make sure the drag was started by a long press as opposed to a long click. 11380142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka if (!child.isInTouchMode()) { 1139aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung return; 114031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 114131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 114231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mDragInfo = cellInfo; 11439171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung mDragInfo.screen = mCurrentScreen; 1144ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 1145c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka CellLayout current = ((CellLayout) getChildAt(mCurrentScreen)); 11469171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung 11479c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka current.onDragChild(child); 11488d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung mDragController.startDrag(child, this, child.getTag(), DragController.DRAG_ACTION_MOVE); 11498d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung invalidate(); 115088127038178b3bbf0eb91103a31e682cc0615074Winson Chung } 115188127038178b3bbf0eb91103a31e682cc0615074Winson Chung 115288127038178b3bbf0eb91103a31e682cc0615074Winson Chung @Override 115388127038178b3bbf0eb91103a31e682cc0615074Winson Chung protected Parcelable onSaveInstanceState() { 115488127038178b3bbf0eb91103a31e682cc0615074Winson Chung final SavedState state = new SavedState(super.onSaveInstanceState()); 115588127038178b3bbf0eb91103a31e682cc0615074Winson Chung state.currentScreen = mCurrentScreen; 115688127038178b3bbf0eb91103a31e682cc0615074Winson Chung return state; 1157760e5375f003accf04f789e90a919ed476d4c335Winson Chung } 1158760e5375f003accf04f789e90a919ed476d4c335Winson Chung 1159760e5375f003accf04f789e90a919ed476d4c335Winson Chung @Override 1160760e5375f003accf04f789e90a919ed476d4c335Winson Chung protected void onRestoreInstanceState(Parcelable state) { 1161760e5375f003accf04f789e90a919ed476d4c335Winson Chung SavedState savedState = (SavedState) state; 1162760e5375f003accf04f789e90a919ed476d4c335Winson Chung super.onRestoreInstanceState(savedState.getSuperState()); 116388127038178b3bbf0eb91103a31e682cc0615074Winson Chung if (savedState.currentScreen != -1) { 116488127038178b3bbf0eb91103a31e682cc0615074Winson Chung mCurrentScreen = savedState.currentScreen; 116588127038178b3bbf0eb91103a31e682cc0615074Winson Chung Launcher.setScreen(mCurrentScreen); 1166ce93f7ebdb296846ba2f01b7eb3e69a3230f3025Winson Chung } 116788127038178b3bbf0eb91103a31e682cc0615074Winson Chung } 116888127038178b3bbf0eb91103a31e682cc0615074Winson Chung 116988127038178b3bbf0eb91103a31e682cc0615074Winson Chung void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo) { 1170ce93f7ebdb296846ba2f01b7eb3e69a3230f3025Winson Chung addApplicationShortcut(info, cellInfo, false); 1171ce93f7ebdb296846ba2f01b7eb3e69a3230f3025Winson Chung } 1172ce93f7ebdb296846ba2f01b7eb3e69a3230f3025Winson Chung 1173ce93f7ebdb296846ba2f01b7eb3e69a3230f3025Winson Chung void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo, 1174ce93f7ebdb296846ba2f01b7eb3e69a3230f3025Winson Chung boolean insertAtFirst) { 11758d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung final CellLayout layout = (CellLayout) getChildAt(cellInfo.screen); 11769171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung final int[] result = new int[2]; 11779171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung 11789171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung layout.cellToPoint(cellInfo.cellX, cellInfo.cellY, result); 11799171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung onDropExternal(result[0], result[1], info, layout, insertAtFirst); 11809171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung } 11810142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 1182c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset, 11830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka DragView dragView, Object dragInfo) { 11840142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka final CellLayout cellLayout = getCurrentDropLayout(); 11850142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka if (source != this) { 11860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka onDropExternal(x - xOffset, y - yOffset, dragInfo, cellLayout); 11870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka } else { 11882763be3150d429d338b9848286e9365b4052c100Michael Jurka // Move internally 11892763be3150d429d338b9848286e9365b4052c100Michael Jurka if (mDragInfo != null) { 11902763be3150d429d338b9848286e9365b4052c100Michael Jurka final View cell = mDragInfo.cell; 11910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka int index = mScroller.isFinished() ? mCurrentScreen : mNextScreen; 11920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka if (index != mDragInfo.screen) { 11930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen); 1194cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy originalCellLayout.removeView(cell); 11950207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy addInScreen(cell, index, mDragInfo.cellX, mDragInfo.cellY, 11960207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy mDragInfo.spanX, mDragInfo.spanY); 11970207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy } 11980207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy mTargetCell = estimateDropCell(x - xOffset, y - yOffset, 11990207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy mDragInfo.spanX, mDragInfo.spanY, cell, cellLayout, 12000207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy mTargetCell); 12010207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy cellLayout.onDropChild(cell); 12020207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy 12030207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy // update the item's position after drop 12040207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy final ItemInfo info = (ItemInfo) cell.getTag(); 12050207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell 12060207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy .getLayoutParams(); 12070207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy lp.cellX = mTargetCell[0]; 120833945b21544bc98381df17726a3537c292d8c985Michael Jurka lp.cellY = mTargetCell[1]; 12090207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy 12100207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy LauncherModel.moveItemInDatabase(mLauncher, info, 12110207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy LauncherSettings.Favorites.CONTAINER_DESKTOP, index, 121233945b21544bc98381df17726a3537c292d8c985Michael Jurka lp.cellX, lp.cellY); 12130207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy } 12140207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy } 12150207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy } 12160207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy 12170207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy public void onDragEnter(DragSource source, int x, int y, int xOffset, 12180207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy int yOffset, DragView dragView, Object dragInfo) { 1219cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy clearVacantCache(); 12208ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy } 12218ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy 1222cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset, 1223cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy DragView dragView, Object dragInfo) { 1224cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy 1225cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy ItemInfo item = (ItemInfo)dragInfo; 1226cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy 1227cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy CellLayout currentLayout = getCurrentDropLayout(); 1228cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy 122931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (dragInfo instanceof LauncherAppWidgetInfo) { 123031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo; 123131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 123231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (widgetInfo.spanX == -1) { 123331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project // Calculate the grid spans needed to fit this widget 1234678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato int[] spans = currentLayout.rectToCell(widgetInfo.minWidth, widgetInfo.minHeight); 123531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project item.spanX = spans[0]; 123631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project item.spanY = spans[1]; 123731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 123831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 12390142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka if (currentLayout != mDragTargetLayout) { 124031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (mDragTargetLayout != null) { 124131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mDragTargetLayout.onDragComplete(); 124231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 124331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mDragTargetLayout = currentLayout; 124431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 124531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 1246c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy // Find the top left corner of the item 1247678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato int originX = x - xOffset; 124831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int originY = y - yOffset; 12490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 125031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final View child = (mDragInfo == null) ? null : mDragInfo.cell; 12510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka currentLayout.visualizeDropLocation(child, originX, originY, item.spanX, item.spanY); 12520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka } 125331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 125431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public void onDragExit(DragSource source, int x, int y, int xOffset, 125531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int yOffset, DragView dragView, Object dragInfo) { 125631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project clearVacantCache(); 125731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (mDragTargetLayout != null) { 12587bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato mDragTargetLayout.onDragComplete(); 12597bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato mDragTargetLayout = null; 126054dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka } 126154dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka } 12626b4adbc0558fcebbd44998bd00dcd334ddbee32dJoe Onorato 12637bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato private void onDropExternal(int x, int y, Object dragInfo, 12647bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato CellLayout cellLayout) { 12657bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato onDropExternal(x, y, dragInfo, cellLayout, false); 12666b879f0a5885274a85333531e091283405d490ccAdam Lesinski } 12677bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato 12687bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato private void onDropExternal(int x, int y, Object dragInfo, 12697bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato CellLayout cellLayout, boolean insertAtFirst) { 12700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka // Drag from somewhere else 12710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka ItemInfo info = (ItemInfo) dragInfo; 12720142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 12730142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka View view = null; 12740142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 12753a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron switch (info.itemType) { 1276aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: 1277dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: 1278fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell if (info.container == NO_ID && info instanceof ApplicationInfo) { 12790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka // Came from all apps -- make a copy 12800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka info = new ShortcutInfo((ApplicationInfo) info); 1281fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell } 12820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka view = mLauncher.createShortcut(R.layout.application, cellLayout, 128331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project (ShortcutInfo) info); 128431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project break; 128531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER: 128631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, 128731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project (ViewGroup) getChildAt(mCurrentScreen), 128831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project ((UserFolderInfo) info)); 128931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project break; 1290dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: 1291dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka cellLayout.setTagToCellInfoForPoint(x, y); 129231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mLauncher.addAppWidgetFromDrop(((LauncherAppWidgetInfo)dragInfo).providerName, cellLayout.getTag()); 129331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project break; 129431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project default: 129531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project throw new IllegalStateException("Unknown item type: " 129631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project + info.itemType); 129731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 129831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 1299be9093426aec3a6d412811a12d2400e645613242Adam Cohen // If the view is null, it has already been added. 1300be9093426aec3a6d412811a12d2400e645613242Adam Cohen if (view == null) { 13016b879f0a5885274a85333531e091283405d490ccAdam Lesinski cellLayout.onDragComplete(); 1302be9093426aec3a6d412811a12d2400e645613242Adam Cohen } else { 1303be9093426aec3a6d412811a12d2400e645613242Adam Cohen mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell); 1304be9093426aec3a6d412811a12d2400e645613242Adam Cohen addInScreen(view, indexOfChild(cellLayout), mTargetCell[0], 1305be9093426aec3a6d412811a12d2400e645613242Adam Cohen mTargetCell[1], info.spanX, info.spanY, insertAtFirst); 13066b879f0a5885274a85333531e091283405d490ccAdam Lesinski cellLayout.onDropChild(view); 1307be9093426aec3a6d412811a12d2400e645613242Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams(); 1308be9093426aec3a6d412811a12d2400e645613242Adam Cohen 1309be9093426aec3a6d412811a12d2400e645613242Adam Cohen LauncherModel.addOrMoveItemInDatabase(mLauncher, info, 1310be9093426aec3a6d412811a12d2400e645613242Adam Cohen LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, 1311be9093426aec3a6d412811a12d2400e645613242Adam Cohen lp.cellX, lp.cellY); 131231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 1313be9093426aec3a6d412811a12d2400e645613242Adam Cohen } 1314be9093426aec3a6d412811a12d2400e645613242Adam Cohen 1315be9093426aec3a6d412811a12d2400e645613242Adam Cohen /** 1316be9093426aec3a6d412811a12d2400e645613242Adam Cohen * Return the current {@link CellLayout}, correctly picking the destination 1317be9093426aec3a6d412811a12d2400e645613242Adam Cohen * screen while a scroll is in progress. 1318be9093426aec3a6d412811a12d2400e645613242Adam Cohen */ 1319be9093426aec3a6d412811a12d2400e645613242Adam Cohen private CellLayout getCurrentDropLayout() { 1320be9093426aec3a6d412811a12d2400e645613242Adam Cohen int index = mScroller.isFinished() ? mCurrentScreen : mNextScreen; 1321be9093426aec3a6d412811a12d2400e645613242Adam Cohen return (CellLayout) getChildAt(index); 13220142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka } 132331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 1324aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung /** 1325ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka * {@inheritDoc} 1326ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka */ 1327a7f801fc5b5715223e868ed599da69c5edf436eeMichael Jurka public boolean acceptDrop(DragSource source, int x, int y, 1328ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka int xOffset, int yOffset, DragView dragView, Object dragInfo) { 1329ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka final CellLayout layout = getCurrentDropLayout(); 1330ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka final CellLayout.CellInfo cellInfo = mDragInfo; 1331ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka final int spanX = cellInfo == null ? 1 : cellInfo.spanX; 1332ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka final int spanY = cellInfo == null ? 1 : cellInfo.spanY; 1333ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka 1334ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka if (mVacantCache == null) { 1335ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka final View ignoreView = cellInfo == null ? null : cellInfo.cell; 1336ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka mVacantCache = layout.findAllVacantCells(null, ignoreView); 1337ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka } 1338ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka 1339ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka if (mVacantCache.findCellForSpan(mTempEstimate, spanX, spanY, false)) { 1340ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka return true; 1341ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka } else { 1342ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka Toast.makeText(getContext(), getContext().getString(R.string.out_of_space), Toast.LENGTH_SHORT).show(); 1343ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka return false; 13441d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown } 13451d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown } 13461d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown 13471d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown /** 13481d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown * {@inheritDoc} 13491d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown */ 13501d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown public Rect estimateDropLocation(DragSource source, int x, int y, 13511d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown int xOffset, int yOffset, DragView dragView, Object dragInfo, Rect recycle) { 13521d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown final CellLayout layout = getCurrentDropLayout(); 13531d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown 13541d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown final CellLayout.CellInfo cellInfo = mDragInfo; 13551d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown final int spanX = cellInfo == null ? 1 : cellInfo.spanX; 13561d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown final int spanY = cellInfo == null ? 1 : cellInfo.spanY; 13571d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown final View ignoreView = cellInfo == null ? null : cellInfo.cell; 13581d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown 135901f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka final Rect location = recycle != null ? recycle : new Rect(); 136001f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka 136101f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka // Find drop cell and convert into rectangle 136201f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka int[] dropCell = estimateDropCell(x - xOffset, y - yOffset, spanX, 1363a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen spanY, ignoreView, layout, mTempCell); 1364a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen 1365a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen if (dropCell == null) { 1366a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen return null; 1367a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen } 1368a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen 1369a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen layout.cellToPoint(dropCell[0], dropCell[1], mTempEstimate); 1370a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen location.left = mTempEstimate[0]; 1371a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen location.top = mTempEstimate[1]; 1372a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen 1373a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen layout.cellToPoint(dropCell[0] + spanX, dropCell[1] + spanY, mTempEstimate); 1374a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen location.right = mTempEstimate[0]; 1375af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka location.bottom = mTempEstimate[1]; 1376af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka 1377af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka return location; 13789171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung } 13793c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka 13803c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka /** 13813c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka * Calculate the nearest cell where the given object would be dropped. 13823c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka */ 13833c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka private int[] estimateDropCell(int pixelX, int pixelY, 13843c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) { 13853c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka 13863c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka final int[] cellXY = mTempCell; 13873c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka layout.estimateDropCell(pixelX, pixelY, spanX, spanY, cellXY); 13883c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka layout.cellToPoint(cellXY[0], cellXY[1], mTempEstimate); 13893c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka 13903c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka // Create vacant cell cache if none exists 13913c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka if (mVacantCache == null) { 1392af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka mVacantCache = layout.findAllVacantCells(null, ignoreView); 1393af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka } 13944c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka 13954c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka // Find the best target drop location 13964c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka return layout.findNearestVacantArea(mTempEstimate[0], mTempEstimate[1], spanX, spanY, mVacantCache, recycle); 13974c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka } 13984c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka 13994c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka void setLauncher(Launcher launcher) { 14004c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka mLauncher = launcher; 14014c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka } 1402883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka 1403883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka public void setDragController(DragController dragController) { 1404883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka mDragController = dragController; 1405883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka } 1406883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka 1407883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka public void onDropCompleted(View target, boolean success) { 1408af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka clearVacantCache(); 1409883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka 1410883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka if (success) { 14113e7c7634531302271270c8cf418abc959d621cbcMichael Jurka if (target != this && mDragInfo != null) { 1412a997ac26664befbd0d5b172e36ef9e8b2c63b435Michael Jurka final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen); 1413d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka cellLayout.removeView(mDragInfo.cell); 14140dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy if (mDragInfo.cell instanceof DropTarget) { 1415d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka mDragController.removeDropTarget((DropTarget)mDragInfo.cell); 14163e7c7634531302271270c8cf418abc959d621cbcMichael Jurka } 14171b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen // final Object tag = mDragInfo.cell.getTag(); 14180dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy } 14190dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy } else { 14200dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy if (mDragInfo != null) { 14210dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen); 14220dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy cellLayout.onDropAborted(mDragInfo.cell); 1423ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen } 1424ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen } 1425ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen 14261b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen mDragInfo = null; 14271b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen } 14280dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy 14290dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy public void scrollLeft() { 14300dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy clearVacantCache(); 14310dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy if (mScroller.isFinished()) { 14320dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy if (mCurrentScreen > 0) 14330dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy snapToScreen(mCurrentScreen - 1); 14340dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy } else { 14357247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy if (mNextScreen > 0) 1436dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka snapToScreen(mNextScreen - 1); 1437213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka } 14380142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka } 14390142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka 14400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka public void scrollRight() { 14410142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka clearVacantCache(); 14420142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka if (mScroller.isFinished()) { 14430142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka if (mCurrentScreen < getChildCount() - 1) 14440142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka snapToScreen(mCurrentScreen + 1); 1445a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen } else { 1446dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka if (mNextScreen < getChildCount() - 1) 1447dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka snapToScreen(mNextScreen + 1); 1448a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen } 1449213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka } 1450df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung 1451742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka public int getScreenForView(View v) { 1452ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung int result = -1; 1453ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung if (v != null) { 14543e7c7634531302271270c8cf418abc959d621cbcMichael Jurka ViewParent vp = v.getParent(); 14553e7c7634531302271270c8cf418abc959d621cbcMichael Jurka int count = getChildCount(); 1456f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen for (int i = 0; i < count; i++) { 1457af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka if (vp == getChildAt(i)) { 1458742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka return i; 1459af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka } 14603e7c7634531302271270c8cf418abc959d621cbcMichael Jurka } 14613e7c7634531302271270c8cf418abc959d621cbcMichael Jurka } 1462742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka return result; 14636b879f0a5885274a85333531e091283405d490ccAdam Lesinski } 1464af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka 1465742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka public Folder getFolderForTag(Object tag) { 1466b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung int screenCount = getChildCount(); 1467af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka for (int screen = 0; screen < screenCount; screen++) { 14683c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka CellLayout currentScreen = ((CellLayout) getChildAt(screen)); 1469213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka int count = currentScreen.getChildCount(); 1470dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka for (int i = 0; i < count; i++) { 1471f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen View child = currentScreen.getChildAt(i); 1472f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 1473f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) { 1474f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen Folder f = (Folder) child; 1475f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen if (f.getInfo() == tag && f.getInfo().opened) { 1476f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen return f; 1477f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen } 1478dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka } 1479dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka } 1480dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka } 1481dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka return null; 1482742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka } 1483a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen 1484a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen public View getViewForTag(Object tag) { 1485a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen int screenCount = getChildCount(); 1486742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka for (int screen = 0; screen < screenCount; screen++) { 1487742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka CellLayout currentScreen = ((CellLayout) getChildAt(screen)); 14883c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka int count = currentScreen.getChildCount(); 14893c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka for (int i = 0; i < count; i++) { 14903c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka View child = currentScreen.getChildAt(i); 14913c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka if (child.getTag() == tag) { 1492f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen return child; 14933c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka } 1494742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka } 1495742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka } 1496742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka return null; 1497742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka } 1498742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka 1499742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka /** 1500742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka * @return True is long presses are still allowed for the current touch 1501742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka */ 1502742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka public boolean allowLongPress() { 1503742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka return mAllowLongPress; 1504742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka } 1505742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka 1506742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka /** 1507742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka * Set true to allow long-press events to be triggered, usually checked by 1508742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka * {@link Launcher} to accept or block dpad-initiated long-presses. 1509742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka */ 1510dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka public void setAllowLongPress(boolean allowLongPress) { 1511f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen mAllowLongPress = allowLongPress; 1512a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen } 1513f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen 1514a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen void removeItems(final ArrayList<ApplicationInfo> apps) { 1515a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen final int count = getChildCount(); 1516a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen final PackageManager manager = getContext().getPackageManager(); 1517742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext()); 1518742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka 1519abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka final HashSet<String> packageNames = new HashSet<String>(); 1520abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka final int appCount = apps.size(); 1521abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka for (int i = 0; i < appCount; i++) { 1522abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka packageNames.add(apps.get(i).componentName.getPackageName()); 1523abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka } 15243e5ad58a6885273a60f8eb77aa9aee965eecdb2cMichael Jurka 1525742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka for (int i = 0; i < count; i++) { 1526742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka final CellLayout layout = (CellLayout) getChildAt(i); 1527742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka 1528742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka // Avoid ANRs by treating each screen separately 1529742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka post(new Runnable() { 1530742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka public void run() { 1531742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka final ArrayList<View> childrenToRemove = new ArrayList<View>(); 1532742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka childrenToRemove.clear(); 1533742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka 1534742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka int childCount = layout.getChildCount(); 1535742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka for (int j = 0; j < childCount; j++) { 1536742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka final View view = layout.getChildAt(j); 153779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka Object tag = view.getTag(); 1538742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka 1539742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka if (tag instanceof ShortcutInfo) { 1540883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka final ShortcutInfo info = (ShortcutInfo) tag; 1541883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka final Intent intent = info.intent; 1542883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka final ComponentName name = intent.getComponent(); 15433e7c7634531302271270c8cf418abc959d621cbcMichael Jurka 1544a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) { 15453e5ad58a6885273a60f8eb77aa9aee965eecdb2cMichael Jurka for (String packageName: packageNames) { 154679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka if (packageName.equals(name.getPackageName())) { 1547dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka // TODO: This should probably be done on a worker thread 1548742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka LauncherModel.deleteItemFromDatabase(mLauncher, info); 1549dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka childrenToRemove.add(view); 1550ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 1551ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 1552ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 1553ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } else if (tag instanceof UserFolderInfo) { 1554ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final UserFolderInfo info = (UserFolderInfo) tag; 1555ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final ArrayList<ShortcutInfo> contents = info.contents; 1556ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1); 1557ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka final int contentsCount = contents.size(); 1558ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka boolean removedFromFolder = false; 1559ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka 1560ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka for (int k = 0; k < contentsCount; k++) { 1561ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka final ShortcutInfo appInfo = contents.get(k); 1562ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka final Intent intent = appInfo.intent; 1563ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka final ComponentName name = intent.getComponent(); 1564ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 1565ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) { 1566ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka for (String packageName: packageNames) { 1567ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (packageName.equals(name.getPackageName())) { 1568ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka toRemove.add(appInfo); 1569ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka // TODO: This should probably be done on a worker thread 1570ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka LauncherModel.deleteItemFromDatabase( 1571ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka mLauncher, appInfo); 1572ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka removedFromFolder = true; 1573ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 1574ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka } 1575ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 1576ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 1577ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 1578742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka contents.removeAll(toRemove); 1579ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka if (removedFromFolder) { 1580ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka final Folder folder = getOpenFolder(); 1581ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka if (folder != null) 1582ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka folder.notifyDataSetChanged(); 1583ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } 1584ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka } else if (tag instanceof LiveFolderInfo) { 1585742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka final LiveFolderInfo info = (LiveFolderInfo) tag; 1586742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka final Uri uri = info.uri; 1587742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka final ProviderInfo providerInfo = manager.resolveContentProvider( 1588742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka uri.getAuthority(), 0); 1589742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka 1590742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka if (providerInfo != null) { 1591742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka for (String packageName: packageNames) { 1592742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka if (packageName.equals(providerInfo.packageName)) { 1593742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka // TODO: This should probably be done on a worker thread 1594742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka LauncherModel.deleteItemFromDatabase(mLauncher, info); 1595742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka childrenToRemove.add(view); 1596742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka } 1597c4e772e4b3f21bde342e475ebc49b5b76b8f74e8Michael Jurka } 1598c4e772e4b3f21bde342e475ebc49b5b76b8f74e8Michael Jurka } 1599c4e772e4b3f21bde342e475ebc49b5b76b8f74e8Michael Jurka } else if (tag instanceof LauncherAppWidgetInfo) { 1600c4e772e4b3f21bde342e475ebc49b5b76b8f74e8Michael Jurka final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag; 1601c4e772e4b3f21bde342e475ebc49b5b76b8f74e8Michael Jurka final AppWidgetProviderInfo provider = 1602742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka widgets.getAppWidgetInfo(info.appWidgetId); 1603742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka if (provider != null) { 1604742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka for (String packageName: packageNames) { 1605742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka if (packageName.equals(provider.provider.getPackageName())) { 1606742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka // TODO: This should probably be done on a worker thread 1607742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka LauncherModel.deleteItemFromDatabase(mLauncher, info); 1608742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka childrenToRemove.add(view); 1609742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka } 1610742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka } 1611742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka } 1612742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka } 1613742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka } 1614742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka 1615742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka childCount = childrenToRemove.size(); 1616742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka for (int j = 0; j < childCount; j++) { 1617742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka View child = childrenToRemove.get(j); 1618742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka layout.removeViewInLayout(child); 1619742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka if (child instanceof DropTarget) { 1620742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka mDragController.removeDropTarget((DropTarget)child); 1621bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka } 16223c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka } 1623ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka 1624ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka if (childCount > 0) { 1625ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka layout.requestLayout(); 1626ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka layout.invalidate(); 16273c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka } 1628dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka } 16298d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung }); 1630af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka } 16318d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung } 16328d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung 1633760e5375f003accf04f789e90a919ed476d4c335Winson Chung void updateShortcuts(ArrayList<ApplicationInfo> apps) { 16348d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung final PackageManager pm = mLauncher.getPackageManager(); 1635dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka 1636dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka final int count = getChildCount(); 163761033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen for (int i = 0; i < count; i++) { 163861033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen final CellLayout layout = (CellLayout) getChildAt(i); 163961033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen int childCount = layout.getChildCount(); 164061033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen for (int j = 0; j < childCount; j++) { 164161033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen final View view = layout.getChildAt(j); 164261033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen Object tag = view.getTag(); 164361033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen if (tag instanceof ShortcutInfo) { 164461033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen ShortcutInfo info = (ShortcutInfo)tag; 164561033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen // We need to check for ACTION_MAIN otherwise getComponent() might 164661033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen // return null for some shortcuts (for instance, for shortcuts to 164761033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen // web pages.) 164861033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen final Intent intent = info.intent; 164961033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen final ComponentName name = intent.getComponent(); 1650eed565d5126cb40b2a7ecdf5f6e8ac7a7464007bAdam Cohen if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION && 1651eed565d5126cb40b2a7ecdf5f6e8ac7a7464007bAdam Cohen Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) { 165261033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen final int appCount = apps.size(); 1653cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen for (int k = 0; k < appCount; k++) { 1654cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen ApplicationInfo app = apps.get(k); 1655cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen if (app.componentName.equals(name)) { 165661033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen info.setIcon(mIconCache.getIcon(info.intent)); 165761033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null, 165861033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen new FastBitmapDrawable(info.getIcon(mIconCache)), 165961033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen null, null); 166061033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen } 166161033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen } 166261033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen } 166361033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen } 1664cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen } 166561033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen } 1666cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen } 1667cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen 1668cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen void moveToDefaultScreen(boolean animate) { 166961033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen if (animate) { 167061033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen snapToScreen(mDefaultScreen); 167161033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen } else { 167261033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen setCurrentScreen(mDefaultScreen); 167361033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen } 1674ea57348cc8f4647f6bc35a42cd45662ddb828b92Michael Jurka getChildAt(mDefaultScreen).requestFocus(); 167561033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen } 167661033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen 167761033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen void setIndicators(Drawable previous, Drawable next) { 167861033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen mPreviousIndicator = previous; 167961033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen mNextIndicator = next; 168061033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen previous.setLevel(mCurrentScreen); 168161033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen next.setLevel(mCurrentScreen); 168261033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen } 168361033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen 168461033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen public static class SavedState extends BaseSavedState { 168561033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen int currentScreen = -1; 168661033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen 168761033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen SavedState(Parcelable superState) { 168861033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen super(superState); 168961033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen } 169061033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen 169161033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen private SavedState(Parcel in) { 169261033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen super(in); 169361033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen currentScreen = in.readInt(); 169461033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen } 16953e7c7634531302271270c8cf418abc959d621cbcMichael Jurka 1696af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka @Override 16973e7c7634531302271270c8cf418abc959d621cbcMichael Jurka public void writeToParcel(Parcel out, int flags) { 16983e7c7634531302271270c8cf418abc959d621cbcMichael Jurka super.writeToParcel(out, flags); 16993e7c7634531302271270c8cf418abc959d621cbcMichael Jurka out.writeInt(currentScreen); 1700af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka } 17013e7c7634531302271270c8cf418abc959d621cbcMichael Jurka 17023e7c7634531302271270c8cf418abc959d621cbcMichael Jurka public static final Parcelable.Creator<SavedState> CREATOR = 17033e7c7634531302271270c8cf418abc959d621cbcMichael Jurka new Parcelable.Creator<SavedState>() { 17043e7c7634531302271270c8cf418abc959d621cbcMichael Jurka public SavedState createFromParcel(Parcel in) { 1705af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka return new SavedState(in); 17063e7c7634531302271270c8cf418abc959d621cbcMichael Jurka } 17073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka 17083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka public SavedState[] newArray(int size) { 170933945b21544bc98381df17726a3537c292d8c985Michael Jurka return new SavedState[size]; 17103e7c7634531302271270c8cf418abc959d621cbcMichael Jurka } 1711af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka }; 171233945b21544bc98381df17726a3537c292d8c985Michael Jurka } 1713af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka} 1714af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka