blob: 47e172f71e082e89ff3385213da6cd11d1d8e03b [file] [log] [blame]
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Joe Onoratoa5902522009-07-30 13:37:37 -070017package com.android.launcher2;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080018
Michael Jurkaaf442092010-06-10 17:01:57 -070019import com.android.launcher.R;
Adam Powell495f2892010-04-16 16:40:55 -070020
Michael Jurka0280c3b2010-09-17 15:00:07 -070021import android.animation.Animator;
Patrick Dubroyde7658b2010-09-27 11:15:43 -070022import android.animation.Animator.AnimatorListener;
Chet Haaseb1254a62010-09-07 13:35:00 -070023import android.animation.AnimatorSet;
Michael Jurka0280c3b2010-09-17 15:00:07 -070024import android.animation.ObjectAnimator;
25import android.animation.PropertyValuesHolder;
Dianne Hackborn8f573952009-08-10 23:21:09 -070026import android.app.WallpaperManager;
Romain Guy629de3e2010-01-13 12:20:59 -080027import android.appwidget.AppWidgetManager;
28import android.appwidget.AppWidgetProviderInfo;
Adam Powell495f2892010-04-16 16:40:55 -070029import android.content.ComponentName;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080030import android.content.Context;
31import android.content.Intent;
Adam Powell495f2892010-04-16 16:40:55 -070032import android.content.pm.PackageManager;
Romain Guy5c16f3e2010-01-12 17:24:58 -080033import android.content.pm.ProviderInfo;
Patrick Dubroy7247f632010-08-04 16:02:59 -070034import android.content.res.Resources;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080035import android.content.res.TypedArray;
Adam Cohenf34bab52010-09-30 14:11:56 -070036import android.graphics.Camera;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080037import android.graphics.Canvas;
Adam Cohenf34bab52010-09-30 14:11:56 -070038import android.graphics.Color;
Michael Jurkaa63c4522010-08-19 13:52:27 -070039import android.graphics.Matrix;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080040import android.graphics.Rect;
The Android Open Source Projectf96811c2009-03-18 17:39:48 -070041import android.graphics.drawable.Drawable;
Romain Guy5c16f3e2010-01-12 17:24:58 -080042import android.net.Uri;
Joe Onorato956091b2010-02-19 12:47:40 -080043import android.os.IBinder;
Adam Powell495f2892010-04-16 16:40:55 -070044import android.os.Parcelable;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080045import android.util.AttributeSet;
Daniel Sandler291ad122010-05-24 16:03:53 -040046import android.util.Log;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080047import android.view.MotionEvent;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080048import android.view.View;
The Android Open Source Projectf96811c2009-03-18 17:39:48 -070049import android.widget.TextView;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080050
Michael Jurkaaf442092010-06-10 17:01:57 -070051import java.util.ArrayList;
52import java.util.HashSet;
Romain Guyedcce092010-03-04 13:03:17 -080053
The Android Open Source Project31dd5032009-03-03 19:32:27 -080054/**
Michael Jurka0142d492010-08-25 17:46:15 -070055 * The workspace is a wide area with a wallpaper and a finite number of pages.
56 * Each page contains a number of icons, folders or widgets the user can
Winson Chungaafa03c2010-06-11 17:34:16 -070057 * interact with. A workspace is meant to be used with a fixed width only.
The Android Open Source Project31dd5032009-03-03 19:32:27 -080058 */
Michael Jurka0142d492010-08-25 17:46:15 -070059public class Workspace extends SmoothPagedView
Michael Jurkadee05892010-07-27 10:01:56 -070060 implements DropTarget, DragSource, DragScroller, View.OnTouchListener {
Romain Guye47f55c2009-11-11 19:21:22 -080061 @SuppressWarnings({"UnusedDeclaration"})
Joe Onorato3a8820b2009-11-10 15:06:42 -080062 private static final String TAG = "Launcher.Workspace";
Michael Jurka0142d492010-08-25 17:46:15 -070063
Michael Jurkadee05892010-07-27 10:01:56 -070064 // This is how much the workspace shrinks when we enter all apps or
65 // customization mode
66 private static final float SHRINK_FACTOR = 0.16f;
Adam Cohena985e592010-09-09 11:23:48 -070067
Adam Cohenf34bab52010-09-30 14:11:56 -070068 // Y rotation to apply to the workspace screens
69 private static final float WORKSPACE_ROTATION = 12.5f;
Adam Cohena985e592010-09-09 11:23:48 -070070
71 // These are extra scale factors to apply to the mini home screens
72 // so as to achieve the desired transform
73 private static final float EXTRA_SCALE_FACTOR_0 = 0.97f;
74 private static final float EXTRA_SCALE_FACTOR_1 = 1.0f;
Adam Cohene54cec82010-09-13 18:19:55 -070075 private static final float EXTRA_SCALE_FACTOR_2 = 1.08f;
Adam Cohena985e592010-09-09 11:23:48 -070076
Adam Cohenf34bab52010-09-30 14:11:56 -070077 private static final int BACKGROUND_FADE_OUT_DELAY = 300;
78 private static final int BACKGROUND_FADE_OUT_DURATION = 300;
79 private static final int BACKGROUND_FADE_IN_DURATION = 100;
80
81 static final int SCROLL_RIGHT = 0;
82 static final int SCROLL_LEFT = 1;
83
84 // These animators are used to fade the
85 private ObjectAnimator<Float> mBackgroundFadeIn;
86 private ObjectAnimator<Float> mBackgroundFadeOut;
87 private float mBackgroundAlpha = 0;
88
Michael Jurka0142d492010-08-25 17:46:15 -070089 private enum ShrinkPosition { SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM };
The Android Open Source Project31dd5032009-03-03 19:32:27 -080090
Dianne Hackborn8f573952009-08-10 23:21:09 -070091 private final WallpaperManager mWallpaperManager;
Winson Chungaafa03c2010-06-11 17:34:16 -070092
Michael Jurka0142d492010-08-25 17:46:15 -070093 private int mDefaultPage;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080094
Michael Jurka79212d82010-07-30 16:36:20 -070095 private boolean mWaitingToShrinkToBottom = false;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080096
The Android Open Source Project31dd5032009-03-03 19:32:27 -080097 /**
98 * CellInfo for the cell that is currently being dragged
99 */
100 private CellLayout.CellInfo mDragInfo;
Winson Chungaafa03c2010-06-11 17:34:16 -0700101
Jeff Sharkey70864282009-04-07 21:08:40 -0700102 /**
103 * Target drop area calculated during last acceptDrop call.
104 */
105 private int[] mTargetCell = null;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800106
Patrick Dubroy6569f2c2010-07-12 14:25:18 -0700107 /**
108 * The CellLayout that is currently being dragged over
109 */
110 private CellLayout mDragTargetLayout = null;
111
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800112 private Launcher mLauncher;
Joe Onorato0589f0f2010-02-08 13:44:00 -0800113 private IconCache mIconCache;
Joe Onorato00acb122009-08-04 16:04:30 -0400114 private DragController mDragController;
Winson Chungaafa03c2010-06-11 17:34:16 -0700115
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800116 private int[] mTempCell = new int[2];
Jeff Sharkey70864282009-04-07 21:08:40 -0700117 private int[] mTempEstimate = new int[2];
Michael Jurka0280c3b2010-09-17 15:00:07 -0700118 private float[] mTempOriginXY = new float[2];
Michael Jurkaa63c4522010-08-19 13:52:27 -0700119 private float[] mTempDragCoordinates = new float[2];
120 private float[] mTempDragBottomRightCoordinates = new float[2];
Michael Jurka0280c3b2010-09-17 15:00:07 -0700121 private Matrix mTempInverseMatrix = new Matrix();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800122
Adam Cohend22015c2010-07-26 22:02:18 -0700123 private static final int DEFAULT_CELL_COUNT_X = 4;
124 private static final int DEFAULT_CELL_COUNT_Y = 4;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800125
Romain Guy8a73c512009-11-09 19:19:59 -0800126 private Drawable mPreviousIndicator;
127 private Drawable mNextIndicator;
Winson Chungaafa03c2010-06-11 17:34:16 -0700128
Michael Jurka0142d492010-08-25 17:46:15 -0700129 // State variable that indicated whether the pages are small (ie when you're
Michael Jurkadee05892010-07-27 10:01:56 -0700130 // in all apps or customize mode)
131 private boolean mIsSmall;
Chet Haaseb1254a62010-09-07 13:35:00 -0700132 private AnimatorListener mUnshrinkAnimationListener;
Michael Jurkadee05892010-07-27 10:01:56 -0700133
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800134 /**
135 * Used to inflate the Workspace from XML.
136 *
137 * @param context The application's context.
Michael Jurka0142d492010-08-25 17:46:15 -0700138 * @param attrs The attributes set containing the Workspace's customization values.
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800139 */
140 public Workspace(Context context, AttributeSet attrs) {
141 this(context, attrs, 0);
142 }
143
144 /**
145 * Used to inflate the Workspace from XML.
146 *
147 * @param context The application's context.
Michael Jurka0142d492010-08-25 17:46:15 -0700148 * @param attrs The attributes set containing the Workspace's customization values.
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800149 * @param defStyle Unused.
150 */
151 public Workspace(Context context, AttributeSet attrs, int defStyle) {
152 super(context, attrs, defStyle);
Michael Jurka0142d492010-08-25 17:46:15 -0700153 mContentIsRefreshable = false;
Michael Jurka5f1c5092010-09-03 14:15:02 -0700154
155 if (!LauncherApplication.isScreenXLarge()) {
156 mFadeInAdjacentScreens = false;
157 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800158
Dianne Hackborn8f573952009-08-10 23:21:09 -0700159 mWallpaperManager = WallpaperManager.getInstance(context);
Winson Chungaafa03c2010-06-11 17:34:16 -0700160
161 TypedArray a = context.obtainStyledAttributes(attrs,
162 R.styleable.Workspace, defStyle, 0);
Adam Cohend22015c2010-07-26 22:02:18 -0700163 int cellCountX = a.getInt(R.styleable.Workspace_cellCountX, DEFAULT_CELL_COUNT_X);
164 int cellCountY = a.getInt(R.styleable.Workspace_cellCountY, DEFAULT_CELL_COUNT_Y);
Michael Jurka0142d492010-08-25 17:46:15 -0700165 mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800166 a.recycle();
167
Adam Cohend22015c2010-07-26 22:02:18 -0700168 LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
Joe Onorato0d44e942009-11-16 18:20:51 -0800169 setHapticFeedbackEnabled(false);
Michael Jurka0142d492010-08-25 17:46:15 -0700170
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800171 initWorkspace();
172 }
173
174 /**
175 * Initializes various states for this workspace.
176 */
Michael Jurka0142d492010-08-25 17:46:15 -0700177 protected void initWorkspace() {
Joe Onorato0589f0f2010-02-08 13:44:00 -0800178 Context context = getContext();
Michael Jurka0142d492010-08-25 17:46:15 -0700179 mCurrentPage = mDefaultPage;
180 Launcher.setScreen(mCurrentPage);
Joe Onorato0589f0f2010-02-08 13:44:00 -0800181 LauncherApplication app = (LauncherApplication)context.getApplicationContext();
182 mIconCache = app.getIconCache();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800183
Chet Haaseb1254a62010-09-07 13:35:00 -0700184 mUnshrinkAnimationListener = new AnimatorListener() {
185 public void onAnimationStart(Animator animation) {}
186 public void onAnimationEnd(Animator animation) {
Michael Jurkadee05892010-07-27 10:01:56 -0700187 mIsSmall = false;
188 }
Chet Haaseb1254a62010-09-07 13:35:00 -0700189 public void onAnimationCancel(Animator animation) {}
190 public void onAnimationRepeat(Animator animation) {}
Michael Jurkadee05892010-07-27 10:01:56 -0700191 };
Michael Jurka0142d492010-08-25 17:46:15 -0700192
193 mSnapVelocity = 600;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800194 }
195
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800196 @Override
Adam Cohenf34bab52010-09-30 14:11:56 -0700197 protected int getScrollMode() {
198 if (LauncherApplication.isScreenXLarge()) {
199 return SmoothPagedView.QUINTIC_MODE;
200 } else {
201 return SmoothPagedView.OVERSHOOT_MODE;
202 }
203 }
204
205 @Override
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800206 public void addView(View child, int index, LayoutParams params) {
207 if (!(child instanceof CellLayout)) {
208 throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
209 }
210 super.addView(child, index, params);
211 }
212
213 @Override
214 public void addView(View child) {
215 if (!(child instanceof CellLayout)) {
216 throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
217 }
218 super.addView(child);
219 }
220
221 @Override
222 public void addView(View child, int index) {
223 if (!(child instanceof CellLayout)) {
224 throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
225 }
226 super.addView(child, index);
227 }
228
229 @Override
230 public void addView(View child, int width, int height) {
231 if (!(child instanceof CellLayout)) {
232 throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
233 }
234 super.addView(child, width, height);
235 }
236
237 @Override
238 public void addView(View child, LayoutParams params) {
239 if (!(child instanceof CellLayout)) {
240 throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
241 }
242 super.addView(child, params);
243 }
244
245 /**
246 * @return The open folder on the current screen, or null if there is none
247 */
248 Folder getOpenFolder() {
Michael Jurka0142d492010-08-25 17:46:15 -0700249 CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
250 int count = currentPage.getChildCount();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800251 for (int i = 0; i < count; i++) {
Michael Jurka0142d492010-08-25 17:46:15 -0700252 View child = currentPage.getChildAt(i);
Winson Chungaafa03c2010-06-11 17:34:16 -0700253 if (child instanceof Folder) {
254 Folder folder = (Folder) child;
255 if (folder.getInfo().opened)
256 return folder;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800257 }
258 }
259 return null;
260 }
261
262 ArrayList<Folder> getOpenFolders() {
Michael Jurkadee05892010-07-27 10:01:56 -0700263 final int screenCount = getChildCount();
264 ArrayList<Folder> folders = new ArrayList<Folder>(screenCount);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800265
Michael Jurkadee05892010-07-27 10:01:56 -0700266 for (int screen = 0; screen < screenCount; screen++) {
Michael Jurka0142d492010-08-25 17:46:15 -0700267 CellLayout currentPage = (CellLayout) getChildAt(screen);
268 int count = currentPage.getChildCount();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800269 for (int i = 0; i < count; i++) {
Michael Jurka0142d492010-08-25 17:46:15 -0700270 View child = currentPage.getChildAt(i);
Winson Chungaafa03c2010-06-11 17:34:16 -0700271 if (child instanceof Folder) {
272 Folder folder = (Folder) child;
273 if (folder.getInfo().opened)
274 folders.add(folder);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800275 break;
276 }
277 }
278 }
279
280 return folders;
281 }
282
Michael Jurka0142d492010-08-25 17:46:15 -0700283 boolean isDefaultPageShowing() {
284 return mCurrentPage == mDefaultPage;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800285 }
286
287 /**
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800288 * Sets the current screen.
289 *
Michael Jurka0142d492010-08-25 17:46:15 -0700290 * @param currentPage
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800291 */
Michael Jurka0142d492010-08-25 17:46:15 -0700292 @Override
293 void setCurrentPage(int currentPage) {
294 super.setCurrentPage(currentPage);
295 updateWallpaperOffset(mScrollX);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800296 }
297
298 /**
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800299 * Adds the specified child in the specified screen. The position and dimension of
300 * the child are defined by x, y, spanX and spanY.
301 *
302 * @param child The child to add in one of the workspace's screens.
303 * @param screen The screen in which to add the child.
304 * @param x The X position of the child in the screen's grid.
305 * @param y The Y position of the child in the screen's grid.
306 * @param spanX The number of cells spanned horizontally by the child.
307 * @param spanY The number of cells spanned vertically by the child.
308 */
309 void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
310 addInScreen(child, screen, x, y, spanX, spanY, false);
311 }
312
Winson Chungaafa03c2010-06-11 17:34:16 -0700313 void addInFullScreen(View child, int screen) {
314 addInScreen(child, screen, 0, 0, -1, -1);
315 }
316
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800317 /**
318 * Adds the specified child in the specified screen. The position and dimension of
319 * the child are defined by x, y, spanX and spanY.
320 *
321 * @param child The child to add in one of the workspace's screens.
322 * @param screen The screen in which to add the child.
323 * @param x The X position of the child in the screen's grid.
324 * @param y The Y position of the child in the screen's grid.
325 * @param spanX The number of cells spanned horizontally by the child.
326 * @param spanY The number of cells spanned vertically by the child.
327 * @param insert When true, the child is inserted at the beginning of the children list.
328 */
329 void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
330 if (screen < 0 || screen >= getChildCount()) {
Daniel Sandler291ad122010-05-24 16:03:53 -0400331 Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
332 + " (was " + screen + "); skipping child");
333 return;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800334 }
335
336 final CellLayout group = (CellLayout) getChildAt(screen);
337 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
338 if (lp == null) {
339 lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
340 } else {
341 lp.cellX = x;
342 lp.cellY = y;
343 lp.cellHSpan = spanX;
344 lp.cellVSpan = spanY;
345 }
Winson Chungaafa03c2010-06-11 17:34:16 -0700346
Patrick Dubroy6569f2c2010-07-12 14:25:18 -0700347 // Get the canonical child id to uniquely represent this view in this screen
Michael Jurka845ba3b2010-09-28 17:09:46 -0700348 int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
Winson Chungaafa03c2010-06-11 17:34:16 -0700349 if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp)) {
350 // TODO: This branch occurs when the workspace is adding views
351 // outside of the defined grid
Patrick Dubroy6569f2c2010-07-12 14:25:18 -0700352 // maybe we should be deleting these items from the LauncherModel?
Winson Chungaafa03c2010-06-11 17:34:16 -0700353 Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
354 }
355
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800356 if (!(child instanceof Folder)) {
Joe Onorato0d44e942009-11-16 18:20:51 -0800357 child.setHapticFeedbackEnabled(false);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800358 child.setOnLongClickListener(mLongClickListener);
359 }
Joe Onorato00acb122009-08-04 16:04:30 -0400360 if (child instanceof DropTarget) {
Winson Chungaafa03c2010-06-11 17:34:16 -0700361 mDragController.addDropTarget((DropTarget) child);
Joe Onorato00acb122009-08-04 16:04:30 -0400362 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800363 }
364
Michael Jurkadee05892010-07-27 10:01:56 -0700365 public boolean onTouch(View v, MotionEvent event) {
366 // this is an intercepted event being forwarded from a cell layout
367 if (mIsSmall) {
Patrick Dubroy2b9ff372010-09-07 17:49:27 -0700368 mLauncher.onWorkspaceClick((CellLayout) v);
Michael Jurka96226222010-08-20 00:54:40 -0700369 return true;
Michael Jurkadee05892010-07-27 10:01:56 -0700370 }
371 return false;
Michael Jurka0e260592010-06-30 17:07:39 -0700372 }
373
Michael Jurka5f1c5092010-09-03 14:15:02 -0700374 @Override
375 public boolean dispatchUnhandledMove(View focused, int direction) {
376 if (mIsSmall) {
377 // when the home screens are shrunken, shouldn't allow side-scrolling
378 return false;
379 }
380 return super.dispatchUnhandledMove(focused, direction);
381 }
382
383 @Override
384 public boolean onInterceptTouchEvent(MotionEvent ev) {
385 if (mIsSmall) {
386 // when the home screens are shrunken, shouldn't allow side-scrolling
387 return false;
388 }
389 return super.onInterceptTouchEvent(ev);
390 }
391
Michael Jurka0142d492010-08-25 17:46:15 -0700392 protected void pageBeginMoving() {
393 if (mNextPage != INVALID_PAGE) {
394 // we're snapping to a particular screen
Michael Jurka16fed412010-10-01 16:12:03 -0700395 enableChildrenCache(mCurrentPage, mNextPage);
Michael Jurka0142d492010-08-25 17:46:15 -0700396 } else {
397 // this is when user is actively dragging a particular screen, they might
398 // swipe it either left or right (but we won't advance by more than one screen)
Michael Jurka16fed412010-10-01 16:12:03 -0700399 enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800400 }
Adam Cohenf34bab52010-09-30 14:11:56 -0700401 showOutlines();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800402 }
403
Michael Jurka0142d492010-08-25 17:46:15 -0700404 protected void pageEndMoving() {
Michael Jurka16fed412010-10-01 16:12:03 -0700405 clearChildrenCache();
Adam Cohenf34bab52010-09-30 14:11:56 -0700406 hideOutlines();
Michael Jurka0142d492010-08-25 17:46:15 -0700407 }
408
409 @Override
410 protected void notifyPageSwitchListener() {
411 super.notifyPageSwitchListener();
412
413 if (mPreviousIndicator != null) {
414 // if we know the next page, we show the indication for it right away; it looks
415 // weird if the indicators are lagging
416 int page = mNextPage;
417 if (page == INVALID_PAGE) {
418 page = mCurrentPage;
419 }
420 mPreviousIndicator.setLevel(page);
421 mNextIndicator.setLevel(page);
422 }
423 Launcher.setScreen(mCurrentPage);
424 };
425
Dianne Hackborn8f573952009-08-10 23:21:09 -0700426 private void updateWallpaperOffset() {
Romain Guy798300c2009-08-11 14:43:29 -0700427 updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
428 }
429
430 private void updateWallpaperOffset(int scrollRange) {
Winson Chung86f77532010-08-24 11:08:22 -0700431 final boolean isStaticWallpaper = (mWallpaperManager != null) &&
432 (mWallpaperManager.getWallpaperInfo() == null);
433 if (LauncherApplication.isScreenXLarge() && !isStaticWallpaper) {
434 IBinder token = getWindowToken();
435 if (token != null) {
436 mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
437 mWallpaperManager.setWallpaperOffsets(getWindowToken(),
438 Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
439 }
Joe Onorato956091b2010-02-19 12:47:40 -0800440 }
Dianne Hackborn8f573952009-08-10 23:21:09 -0700441 }
Winson Chungaafa03c2010-06-11 17:34:16 -0700442
Adam Cohenf34bab52010-09-30 14:11:56 -0700443 private float getScaleXForRotation(float degrees) {
444 return (float) (1.0f / Math.cos(Math.PI * degrees / 180.0f));
445 }
446
447 public void showOutlines() {
448 if (mBackgroundFadeOut != null) mBackgroundFadeOut.cancel();
449 if (mBackgroundFadeIn != null) mBackgroundFadeIn.cancel();
450 mBackgroundFadeIn = new ObjectAnimator<Float>(BACKGROUND_FADE_IN_DURATION, this,
451 new PropertyValuesHolder<Float>("backgroundAlpha", 1.0f));
452 mBackgroundFadeIn.start();
453 }
454
455 public void hideOutlines() {
456 if (mBackgroundFadeIn != null) mBackgroundFadeIn.cancel();
457 if (mBackgroundFadeOut != null) mBackgroundFadeOut.cancel();
458 mBackgroundFadeOut = new ObjectAnimator<Float>(BACKGROUND_FADE_OUT_DURATION, this,
459 new PropertyValuesHolder<Float>("backgroundAlpha", 0.0f));
460 mBackgroundFadeOut.setStartDelay(BACKGROUND_FADE_OUT_DELAY);
461 mBackgroundFadeOut.start();
462 }
463
464 public void setBackgroundAlpha(float alpha) {
465 mBackgroundAlpha = alpha;
466 for (int i = 0; i < getChildCount(); i++) {
467 CellLayout cl = (CellLayout) getChildAt(i);
468 cl.setBackgroundAlpha(alpha);
469 }
470 }
471
472 public float getBackgroundAlpha() {
473 return mBackgroundAlpha;
474 }
475
476 @Override
477 protected void screenScrolled(int screenCenter) {
Adam Cohen9c4949e2010-10-05 12:27:22 -0700478 CellLayout cur = (CellLayout) getChildAt(mCurrentPage);
479 CellLayout toRight = (CellLayout) getChildAt(mCurrentPage + 1);
480 CellLayout toLeft = (CellLayout) getChildAt(mCurrentPage - 1);
Adam Cohenf34bab52010-09-30 14:11:56 -0700481
482 for (int i = 0; i < mCurrentPage - 1; i++) {
483 View v = getChildAt(i);
484 if (v != null) {
485 v.setRotationY(WORKSPACE_ROTATION);
486 v.setScaleX(getScaleXForRotation(WORKSPACE_ROTATION));
487 }
488 }
489 for (int i = mCurrentPage + 1; i < getChildCount(); i++) {
490 View v = getChildAt(i);
491 if (v != null) {
492 v.setRotationY(-WORKSPACE_ROTATION);
493 v.setScaleX(getScaleXForRotation(-WORKSPACE_ROTATION));
494 }
495 }
496
Adam Cohen9c4949e2010-10-05 12:27:22 -0700497 int halfScreenSize = getMeasuredWidth() / 2;
Adam Cohenf34bab52010-09-30 14:11:56 -0700498 int pageWidth = cur.getMeasuredWidth();
Adam Cohen9c4949e2010-10-05 12:27:22 -0700499 int delta = screenCenter - (getChildOffset(mCurrentPage) -
500 getRelativeChildOffset(mCurrentPage) + halfScreenSize);
Adam Cohenf34bab52010-09-30 14:11:56 -0700501
Adam Cohen9c4949e2010-10-05 12:27:22 -0700502 float scrollProgress = Math.abs(delta/(pageWidth*1.0f + mPageSpacing));
Adam Cohenf34bab52010-09-30 14:11:56 -0700503 int scrollDirection = delta > 0 ? SCROLL_LEFT : SCROLL_RIGHT;
504
505 float rotation;
506
507 if (scrollDirection == SCROLL_RIGHT) {
508 rotation = -scrollProgress * WORKSPACE_ROTATION;
509 cur.setRotationY(rotation);
510 cur.setScaleX(getScaleXForRotation(rotation));
Adam Cohen9c4949e2010-10-05 12:27:22 -0700511
Adam Cohenf34bab52010-09-30 14:11:56 -0700512 if (toLeft != null) {
513 rotation = WORKSPACE_ROTATION * (1 - scrollProgress);
514 toLeft.setRotationY(rotation);
515 toLeft.setScaleX(getScaleXForRotation(rotation));
516 }
517 if (toRight != null) {
518 toRight.setRotationY(-WORKSPACE_ROTATION);
519 toRight.setScaleX(getScaleXForRotation(WORKSPACE_ROTATION));
520 }
521 } else {
522 rotation = scrollProgress * WORKSPACE_ROTATION;
523 cur.setRotationY(rotation);
524 cur.setScaleX(getScaleXForRotation(rotation));
525
526 if (toRight != null) {
527 rotation = -WORKSPACE_ROTATION * (1 - scrollProgress);
528 toRight.setRotationY(rotation);
529 toRight.setScaleX(getScaleXForRotation(rotation));
530 }
531 if (toLeft != null) {
532 toLeft.setRotationY(WORKSPACE_ROTATION);
533 toLeft.setScaleX(getScaleXForRotation(WORKSPACE_ROTATION));
534 }
535 }
536 }
537
Joe Onorato00acb122009-08-04 16:04:30 -0400538 protected void onAttachedToWindow() {
539 super.onAttachedToWindow();
Joe Onorato956091b2010-02-19 12:47:40 -0800540 computeScroll();
Joe Onorato00acb122009-08-04 16:04:30 -0400541 mDragController.setWindowToken(getWindowToken());
542 }
543
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800544 @Override
Michael Jurka28750fb2010-09-24 17:43:49 -0700545 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Michael Jurka0142d492010-08-25 17:46:15 -0700546 super.onLayout(changed, left, top, right, bottom);
Winson Chungaafa03c2010-06-11 17:34:16 -0700547
Michael Jurka79212d82010-07-30 16:36:20 -0700548 // if shrinkToBottom() is called on initialization, it has to be deferred
549 // until after the first call to onLayout so that it has the correct width
550 if (mWaitingToShrinkToBottom) {
551 shrinkToBottom(false);
552 mWaitingToShrinkToBottom = false;
553 }
554
Winson Chungaafa03c2010-06-11 17:34:16 -0700555 if (LauncherApplication.isInPlaceRotationEnabled()) {
556 // When the device is rotated, the scroll position of the current screen
557 // needs to be refreshed
Michael Jurka0142d492010-08-25 17:46:15 -0700558 setCurrentPage(getCurrentPage());
Winson Chungaafa03c2010-06-11 17:34:16 -0700559 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800560 }
561
562 @Override
Michael Jurka0142d492010-08-25 17:46:15 -0700563 protected void dispatchDraw(Canvas canvas) {
564 if (mIsSmall) {
565 // Draw all the workspaces if we're small
566 final int pageCount = getChildCount();
567 final long drawingTime = getDrawingTime();
568 for (int i = 0; i < pageCount; i++) {
569 final View page = (View) getChildAt(i);
570
Michael Jurka0142d492010-08-25 17:46:15 -0700571 drawChild(canvas, page, drawingTime);
572 }
573 } else {
574 super.dispatchDraw(canvas);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800575 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800576 }
577
578 @Override
579 protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
Joe Onorato67886212009-09-14 19:05:05 -0400580 if (!mLauncher.isAllAppsVisible()) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800581 final Folder openFolder = getOpenFolder();
582 if (openFolder != null) {
583 return openFolder.requestFocus(direction, previouslyFocusedRect);
584 } else {
Michael Jurka0142d492010-08-25 17:46:15 -0700585 return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800586 }
587 }
588 return false;
589 }
590
591 @Override
Romain Guyc2e24c02009-06-01 16:11:41 -0700592 public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
Joe Onorato67886212009-09-14 19:05:05 -0400593 if (!mLauncher.isAllAppsVisible()) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800594 final Folder openFolder = getOpenFolder();
Michael Jurka0142d492010-08-25 17:46:15 -0700595 if (openFolder != null) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800596 openFolder.addFocusables(views, direction);
Michael Jurka0142d492010-08-25 17:46:15 -0700597 } else {
598 super.addFocusables(views, direction, focusableMode);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800599 }
600 }
601 }
602
603 @Override
Joe Onorato7bb17492009-09-24 17:51:01 -0700604 public boolean dispatchTouchEvent(MotionEvent ev) {
605 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
Michael Jurka54dd7542010-07-30 14:47:52 -0700606 // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
607 // ie when you click on a mini-screen, it zooms back to that screen)
Joe Onorato6b4adbc2010-09-01 12:13:25 -0700608 if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
Joe Onorato7bb17492009-09-24 17:51:01 -0700609 return false;
610 }
611 }
612 return super.dispatchTouchEvent(ev);
613 }
614
Michael Jurka0142d492010-08-25 17:46:15 -0700615 void enableChildrenCache(int fromPage, int toPage) {
616 if (fromPage > toPage) {
617 final int temp = fromPage;
618 fromPage = toPage;
619 toPage = temp;
Mike Cleron3a2b3f22009-11-05 17:17:42 -0800620 }
Winson Chungaafa03c2010-06-11 17:34:16 -0700621
Michael Jurkadee05892010-07-27 10:01:56 -0700622 final int screenCount = getChildCount();
Adam Powellfea5d022010-04-29 11:42:45 -0700623
Michael Jurka0142d492010-08-25 17:46:15 -0700624 fromPage = Math.max(fromPage, 0);
625 toPage = Math.min(toPage, screenCount - 1);
Adam Powellfea5d022010-04-29 11:42:45 -0700626
Michael Jurka0142d492010-08-25 17:46:15 -0700627 for (int i = fromPage; i <= toPage; i++) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800628 final CellLayout layout = (CellLayout) getChildAt(i);
629 layout.setChildrenDrawnWithCacheEnabled(true);
630 layout.setChildrenDrawingCacheEnabled(true);
631 }
632 }
633
634 void clearChildrenCache() {
Michael Jurkadee05892010-07-27 10:01:56 -0700635 final int screenCount = getChildCount();
636 for (int i = 0; i < screenCount; i++) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800637 final CellLayout layout = (CellLayout) getChildAt(i);
638 layout.setChildrenDrawnWithCacheEnabled(false);
639 }
640 }
641
642 @Override
643 public boolean onTouchEvent(MotionEvent ev) {
Joe Onorato2bc6b7c2009-10-01 14:08:30 -0700644 if (mLauncher.isAllAppsVisible()) {
645 // Cancel any scrolling that is in progress.
646 if (!mScroller.isFinished()) {
647 mScroller.abortAnimation();
648 }
Michael Jurka0142d492010-08-25 17:46:15 -0700649 snapToPage(mCurrentPage);
Joe Onorato7c312c12009-08-13 21:36:53 -0700650 return false; // We don't want the events. Let them fall through to the all apps view.
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800651 }
652
Michael Jurka0142d492010-08-25 17:46:15 -0700653 return super.onTouchEvent(ev);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800654 }
Winson Chungaafa03c2010-06-11 17:34:16 -0700655
Michael Jurka01f0ed42010-08-20 00:41:17 -0700656 public boolean isSmall() {
657 return mIsSmall;
658 }
659
Patrick Dubroy6b509c12010-08-23 15:08:16 -0700660 void shrinkToTop(boolean animated) {
Michael Jurka0142d492010-08-25 17:46:15 -0700661 shrink(ShrinkPosition.SHRINK_TO_TOP, animated);
Michael Jurka01f0ed42010-08-20 00:41:17 -0700662 }
663
664 void shrinkToMiddle() {
Michael Jurka0142d492010-08-25 17:46:15 -0700665 shrink(ShrinkPosition.SHRINK_TO_MIDDLE, true);
Michael Jurka213d9632010-07-28 11:29:25 -0700666 }
667
668 void shrinkToBottom() {
Michael Jurka79212d82010-07-30 16:36:20 -0700669 shrinkToBottom(true);
670 }
671
672 void shrinkToBottom(boolean animated) {
673 if (mFirstLayout) {
674 // (mFirstLayout == "first layout has not happened yet")
675 // if we get a call to shrink() as part of our initialization (for example, if
676 // Launcher is started in All Apps mode) then we need to wait for a layout call
677 // to get our width so we can layout the mini-screen views correctly
678 mWaitingToShrinkToBottom = true;
679 } else {
Michael Jurka0142d492010-08-25 17:46:15 -0700680 shrink(ShrinkPosition.SHRINK_TO_BOTTOM, animated);
Michael Jurka79212d82010-07-30 16:36:20 -0700681 }
Michael Jurka213d9632010-07-28 11:29:25 -0700682 }
683
Adam Cohena985e592010-09-09 11:23:48 -0700684 private float getYScaleForScreen(int screen) {
685 int x = Math.abs(screen - 2);
686
687 // TODO: This should be generalized for use with arbitrary rotation angles.
688 switch(x) {
689 case 0: return EXTRA_SCALE_FACTOR_0;
690 case 1: return EXTRA_SCALE_FACTOR_1;
691 case 2: return EXTRA_SCALE_FACTOR_2;
692 }
693 return 1.0f;
694 }
695
Michael Jurkadee05892010-07-27 10:01:56 -0700696 // we use this to shrink the workspace for the all apps view and the customize view
Michael Jurka0142d492010-08-25 17:46:15 -0700697 private void shrink(ShrinkPosition shrinkPosition, boolean animated) {
Michael Jurkadee05892010-07-27 10:01:56 -0700698 mIsSmall = true;
Michael Jurka5f1c5092010-09-03 14:15:02 -0700699 // we intercept and reject all touch events when we're small, so be sure to reset the state
700 mTouchState = TOUCH_STATE_REST;
701 mActivePointerId = INVALID_POINTER;
702
Patrick Dubroy7247f632010-08-04 16:02:59 -0700703 final Resources res = getResources();
Michael Jurkadee05892010-07-27 10:01:56 -0700704 final int screenWidth = getWidth();
Michael Jurka213d9632010-07-28 11:29:25 -0700705 final int screenHeight = getHeight();
Michael Jurka0142d492010-08-25 17:46:15 -0700706
707 // Making the assumption that all pages have the same width as the 0th
708 final int pageWidth = getChildAt(0).getMeasuredWidth();
709 final int pageHeight = getChildAt(0).getMeasuredHeight();
710
711 final int scaledPageWidth = (int) (SHRINK_FACTOR * pageWidth);
712 final int scaledPageHeight = (int) (SHRINK_FACTOR * pageHeight);
Adam Cohena985e592010-09-09 11:23:48 -0700713 final float extraScaledSpacing = res.getDimension(R.dimen.smallScreenExtraSpacing);
Michael Jurkadee05892010-07-27 10:01:56 -0700714
715 final int screenCount = getChildCount();
Adam Cohena985e592010-09-09 11:23:48 -0700716 float totalWidth = screenCount * scaledPageWidth + (screenCount - 1) * extraScaledSpacing;
Michael Jurka213d9632010-07-28 11:29:25 -0700717
718 float newY = getResources().getDimension(R.dimen.smallScreenVerticalMargin);
Michael Jurka0142d492010-08-25 17:46:15 -0700719 if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM) {
720 newY = screenHeight - newY - scaledPageHeight;
721 } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_MIDDLE) {
722 newY = screenHeight / 2 - scaledPageHeight / 2;
Michael Jurka213d9632010-07-28 11:29:25 -0700723 }
Michael Jurkadee05892010-07-27 10:01:56 -0700724
725 // We animate all the screens to the centered position in workspace
726 // At the same time, the screens become greyed/dimmed
727
728 // newX is initialized to the left-most position of the centered screens
Michael Jurka0142d492010-08-25 17:46:15 -0700729 float newX = mScroller.getFinalX() + screenWidth / 2 - totalWidth / 2;
Adam Cohena985e592010-09-09 11:23:48 -0700730
731 // We are going to scale about the center of the view, so we need to adjust the positions
732 // of the views accordingly
733 newX -= (pageWidth - scaledPageWidth) / 2.0f;
734 newY -= (pageHeight - scaledPageHeight) / 2.0f;
Michael Jurkadee05892010-07-27 10:01:56 -0700735 for (int i = 0; i < screenCount; i++) {
736 CellLayout cl = (CellLayout) getChildAt(i);
Adam Cohena985e592010-09-09 11:23:48 -0700737
Adam Cohenf34bab52010-09-30 14:11:56 -0700738 float rotation = (-i + 2) * WORKSPACE_ROTATION;
Adam Cohena985e592010-09-09 11:23:48 -0700739 float rotationScaleX = (float) (1.0f / Math.cos(Math.PI * rotation / 180.0f));
740 float rotationScaleY = getYScaleForScreen(i);
741
Michael Jurka79212d82010-07-30 16:36:20 -0700742 if (animated) {
Patrick Dubroy7247f632010-08-04 16:02:59 -0700743 final int duration = res.getInteger(R.integer.config_workspaceShrinkTime);
Michael Jurka5f1c5092010-09-03 14:15:02 -0700744 new ObjectAnimator<Float>(duration, cl,
745 new PropertyValuesHolder<Float>("x", newX),
746 new PropertyValuesHolder<Float>("y", newY),
Adam Cohene54cec82010-09-13 18:19:55 -0700747 new PropertyValuesHolder<Float>("scaleX", SHRINK_FACTOR * rotationScaleX),
748 new PropertyValuesHolder<Float>("scaleY", SHRINK_FACTOR * rotationScaleY),
Michael Jurka5f1c5092010-09-03 14:15:02 -0700749 new PropertyValuesHolder<Float>("backgroundAlpha", 1.0f),
Michael Jurka16fed412010-10-01 16:12:03 -0700750 new PropertyValuesHolder<Float>("alpha", 1.0f),
Michael Jurka5f1c5092010-09-03 14:15:02 -0700751 new PropertyValuesHolder<Float>("rotationY", rotation)).start();
Michael Jurka79212d82010-07-30 16:36:20 -0700752 } else {
753 cl.setX((int)newX);
754 cl.setY((int)newY);
Adam Cohenf34bab52010-09-30 14:11:56 -0700755 cl.setScaleX(SHRINK_FACTOR * rotationScaleX);
756 cl.setScaleY(SHRINK_FACTOR * rotationScaleY);
Michael Jurka5f1c5092010-09-03 14:15:02 -0700757 cl.setBackgroundAlpha(1.0f);
758 cl.setAlpha(0.0f);
Adam Cohena985e592010-09-09 11:23:48 -0700759 cl.setRotationY(rotation);
Michael Jurka79212d82010-07-30 16:36:20 -0700760 }
Michael Jurkadee05892010-07-27 10:01:56 -0700761 // increment newX for the next screen
Adam Cohena985e592010-09-09 11:23:48 -0700762 newX += scaledPageWidth + extraScaledSpacing;
Michael Jurkadee05892010-07-27 10:01:56 -0700763 cl.setOnInterceptTouchListener(this);
764 }
765 setChildrenDrawnWithCacheEnabled(true);
Michael Jurkadee05892010-07-27 10:01:56 -0700766 }
767
768 // We call this when we trigger an unshrink by clicking on the CellLayout cl
Patrick Dubroy2b9ff372010-09-07 17:49:27 -0700769 public void unshrink(CellLayout clThatWasClicked) {
Michael Jurka0142d492010-08-25 17:46:15 -0700770 int newCurrentPage = mCurrentPage;
Michael Jurka4cb37242010-08-09 21:05:32 -0700771 final int screenCount = getChildCount();
772 for (int i = 0; i < screenCount; i++) {
773 if (getChildAt(i) == clThatWasClicked) {
Michael Jurka0142d492010-08-25 17:46:15 -0700774 newCurrentPage = i;
Michael Jurkadee05892010-07-27 10:01:56 -0700775 }
Michael Jurka4cb37242010-08-09 21:05:32 -0700776 }
Michael Jurka0142d492010-08-25 17:46:15 -0700777 unshrink(newCurrentPage);
Michael Jurka4cb37242010-08-09 21:05:32 -0700778 }
779
Michael Jurka0142d492010-08-25 17:46:15 -0700780 private void unshrink(int newCurrentPage) {
Michael Jurka4cb37242010-08-09 21:05:32 -0700781 if (mIsSmall) {
Michael Jurka5f1c5092010-09-03 14:15:02 -0700782 int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
783 int delta = newX - mScrollX;
Michael Jurka4cb37242010-08-09 21:05:32 -0700784
785 final int screenCount = getChildCount();
Michael Jurkab0f28bd2010-07-30 11:58:59 -0700786 for (int i = 0; i < screenCount; i++) {
787 CellLayout cl = (CellLayout) getChildAt(i);
788 cl.setX(cl.getX() + delta);
789 }
Michael Jurka0142d492010-08-25 17:46:15 -0700790 snapToPage(newCurrentPage);
Michael Jurkab0f28bd2010-07-30 11:58:59 -0700791 unshrink();
Michael Jurka0142d492010-08-25 17:46:15 -0700792
793 setCurrentPage(newCurrentPage);
Michael Jurkab0f28bd2010-07-30 11:58:59 -0700794 }
Michael Jurkadee05892010-07-27 10:01:56 -0700795 }
796
Michael Jurka4cb37242010-08-09 21:05:32 -0700797 void unshrink() {
798 unshrink(true);
799 }
800
801 void unshrink(boolean animated) {
Michael Jurkab0f28bd2010-07-30 11:58:59 -0700802 if (mIsSmall) {
Chet Haaseb1254a62010-09-07 13:35:00 -0700803 AnimatorSet s = new AnimatorSet();
Michael Jurkab0f28bd2010-07-30 11:58:59 -0700804 final int screenCount = getChildCount();
Michael Jurka4cb37242010-08-09 21:05:32 -0700805
806 final int duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
Michael Jurkab0f28bd2010-07-30 11:58:59 -0700807 for (int i = 0; i < screenCount; i++) {
Patrick Dubroy7247f632010-08-04 16:02:59 -0700808 final CellLayout cl = (CellLayout)getChildAt(i);
Michael Jurka5f1c5092010-09-03 14:15:02 -0700809 float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
Adam Cohenf34bab52010-09-30 14:11:56 -0700810 float rotation = 0.0f;
811
812 if (i < mCurrentPage) {
813 rotation = WORKSPACE_ROTATION;
814 } else if (i > mCurrentPage) {
815 rotation = -WORKSPACE_ROTATION;
816 }
817
Michael Jurka4cb37242010-08-09 21:05:32 -0700818 if (animated) {
819 s.playTogether(
Chet Haaseb1254a62010-09-07 13:35:00 -0700820 new ObjectAnimator<Float>(duration, cl, "translationX", 0.0f),
821 new ObjectAnimator<Float>(duration, cl, "translationY", 0.0f),
822 new ObjectAnimator<Float>(duration, cl, "scaleX", 1.0f),
823 new ObjectAnimator<Float>(duration, cl, "scaleY", 1.0f),
Michael Jurka5f1c5092010-09-03 14:15:02 -0700824 new ObjectAnimator<Float>(duration, cl, "backgroundAlpha", 0.0f),
825 new ObjectAnimator<Float>(duration, cl, "alpha", finalAlphaValue),
Adam Cohenf34bab52010-09-30 14:11:56 -0700826 new ObjectAnimator<Float>(duration, cl, "rotationY", rotation));
Michael Jurka4cb37242010-08-09 21:05:32 -0700827 } else {
828 cl.setTranslationX(0.0f);
829 cl.setTranslationY(0.0f);
830 cl.setScaleX(1.0f);
831 cl.setScaleY(1.0f);
Michael Jurka5f1c5092010-09-03 14:15:02 -0700832 cl.setBackgroundAlpha(0.0f);
Adam Cohenf34bab52010-09-30 14:11:56 -0700833 cl.setAlpha(finalAlphaValue);
834 cl.setRotationY(rotation);
Michael Jurka4cb37242010-08-09 21:05:32 -0700835 }
Michael Jurkab0f28bd2010-07-30 11:58:59 -0700836 }
837 s.addListener(mUnshrinkAnimationListener);
838 s.start();
Michael Jurkadee05892010-07-27 10:01:56 -0700839 }
Michael Jurkadee05892010-07-27 10:01:56 -0700840 }
841
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800842 void startDrag(CellLayout.CellInfo cellInfo) {
843 View child = cellInfo.cell;
Winson Chungaafa03c2010-06-11 17:34:16 -0700844
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800845 // Make sure the drag was started by a long press as opposed to a long click.
Bjorn Bringert7984c942009-12-09 15:38:25 +0000846 if (!child.isInTouchMode()) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800847 return;
848 }
Winson Chungaafa03c2010-06-11 17:34:16 -0700849
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800850 mDragInfo = cellInfo;
Michael Jurka0142d492010-08-25 17:46:15 -0700851 mDragInfo.screen = mCurrentPage;
Winson Chungaafa03c2010-06-11 17:34:16 -0700852
Michael Jurka0142d492010-08-25 17:46:15 -0700853 CellLayout current = ((CellLayout) getChildAt(mCurrentPage));
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800854
855 current.onDragChild(child);
Joe Onorato00acb122009-08-04 16:04:30 -0400856 mDragController.startDrag(child, this, child.getTag(), DragController.DRAG_ACTION_MOVE);
Patrick Dubroyde7658b2010-09-27 11:15:43 -0700857 current.onDragEnter(child);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800858 invalidate();
859 }
860
Michael Jurka0280c3b2010-09-17 15:00:07 -0700861 void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
862 boolean insertAtFirst, int intersectX, int intersectY) {
863 final CellLayout cellLayout = (CellLayout) getChildAt(screen);
864 View view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info);
865
866 final int[] cellXY = new int[2];
867 cellLayout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
868 addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
869 LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
870 LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
871 cellXY[0], cellXY[1]);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800872 }
873
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800874
Joe Onorato00acb122009-08-04 16:04:30 -0400875 public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
876 DragView dragView, Object dragInfo) {
Michael Jurka0280c3b2010-09-17 15:00:07 -0700877 CellLayout cellLayout;
Michael Jurkaa63c4522010-08-19 13:52:27 -0700878 int originX = x - xOffset;
879 int originY = y - yOffset;
880 if (mIsSmall) {
Michael Jurka0280c3b2010-09-17 15:00:07 -0700881 cellLayout = findMatchingPageForDragOver(dragView, originX, originY);
Michael Jurkaa63c4522010-08-19 13:52:27 -0700882 if (cellLayout == null) {
883 // cancel the drag if we're not over a mini-screen at time of drop
884 // TODO: maybe add a nice fade here?
885 return;
886 }
Michael Jurka0280c3b2010-09-17 15:00:07 -0700887 // get originX and originY in the local coordinate system of the screen
888 mTempOriginXY[0] = originX;
889 mTempOriginXY[1] = originY;
890 mapPointGlobalToLocal(cellLayout, mTempOriginXY);
891 originX = (int)mTempOriginXY[0];
892 originY = (int)mTempOriginXY[1];
893 } else {
894 cellLayout = getCurrentDropLayout();
Michael Jurkaa63c4522010-08-19 13:52:27 -0700895 }
Michael Jurkac6ee42e2010-09-30 12:04:50 -0700896
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800897 if (source != this) {
Michael Jurkaa63c4522010-08-19 13:52:27 -0700898 onDropExternal(originX, originY, dragInfo, cellLayout);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800899 } else {
900 // Move internally
901 if (mDragInfo != null) {
902 final View cell = mDragInfo.cell;
Michael Jurkaa63c4522010-08-19 13:52:27 -0700903
Michael Jurka6a1435d2010-09-27 17:35:12 -0700904 mTargetCell = findNearestVacantArea(originX, originY,
Winson Chungaafa03c2010-06-11 17:34:16 -0700905 mDragInfo.spanX, mDragInfo.spanY, cell, cellLayout,
906 mTargetCell);
Michael Jurkac6ee42e2010-09-30 12:04:50 -0700907
908 int screen = indexOfChild(cellLayout);
909 if (screen != mDragInfo.screen) {
910 final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
911 originalCellLayout.removeView(cell);
912 addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
913 mDragInfo.spanX, mDragInfo.spanY);
914 }
Winson Chungaafa03c2010-06-11 17:34:16 -0700915 cellLayout.onDropChild(cell);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800916
Winson Chungaafa03c2010-06-11 17:34:16 -0700917 // update the item's position after drop
Romain Guy84f296c2009-11-04 15:00:44 -0800918 final ItemInfo info = (ItemInfo) cell.getTag();
Michael Jurka0280c3b2010-09-17 15:00:07 -0700919 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
920 cellLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
Winson Chungaafa03c2010-06-11 17:34:16 -0700921 lp.cellX = mTargetCell[0];
922 lp.cellY = mTargetCell[1];
Michael Jurka60587ef2010-09-30 11:06:13 -0700923 cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
Michael Jurka845ba3b2010-09-28 17:09:46 -0700924 mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
Winson Chungaafa03c2010-06-11 17:34:16 -0700925
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800926 LauncherModel.moveItemInDatabase(mLauncher, info,
Michael Jurkac6ee42e2010-09-30 12:04:50 -0700927 LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
Winson Chungaafa03c2010-06-11 17:34:16 -0700928 lp.cellX, lp.cellY);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800929 }
930 }
931 }
932
Winson Chungaafa03c2010-06-11 17:34:16 -0700933 public void onDragEnter(DragSource source, int x, int y, int xOffset,
934 int yOffset, DragView dragView, Object dragInfo) {
Patrick Dubroyde7658b2010-09-27 11:15:43 -0700935 getCurrentDropLayout().onDragEnter(dragView);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800936 }
937
Patrick Dubroy440c3602010-07-13 17:50:32 -0700938 public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
939 DragView dragView, Object dragInfo) {
940
Michael Jurka0280c3b2010-09-17 15:00:07 -0700941 if (mIsSmall) {
942 // If we're shrunken, don't let anyone drag on folders/etc that are on the mini-screens
943 return null;
944 }
Patrick Dubroy440c3602010-07-13 17:50:32 -0700945 // We may need to delegate the drag to a child view. If a 1x1 item
946 // would land in a cell occupied by a DragTarget (e.g. a Folder),
947 // then drag events should be handled by that child.
948
949 ItemInfo item = (ItemInfo)dragInfo;
950 CellLayout currentLayout = getCurrentDropLayout();
951
952 int dragPointX, dragPointY;
953 if (item.spanX == 1 && item.spanY == 1) {
954 // For a 1x1, calculate the drop cell exactly as in onDragOver
955 dragPointX = x - xOffset;
956 dragPointY = y - yOffset;
957 } else {
958 // Otherwise, use the exact drag coordinates
959 dragPointX = x;
960 dragPointY = y;
961 }
Michael Jurka0280c3b2010-09-17 15:00:07 -0700962 dragPointX += mScrollX - currentLayout.getLeft();
963 dragPointY += mScrollY - currentLayout.getTop();
Patrick Dubroy440c3602010-07-13 17:50:32 -0700964
965 // If we are dragging over a cell that contains a DropTarget that will
966 // accept the drop, delegate to that DropTarget.
967 final int[] cellXY = mTempCell;
968 currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY);
969 View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
970 if (child instanceof DropTarget) {
971 DropTarget target = (DropTarget)child;
972 if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
973 return target;
974 }
975 }
976 return null;
977 }
978
Michael Jurka0280c3b2010-09-17 15:00:07 -0700979 private void mapPointGlobalToLocal(View v, float[] xy) {
980 xy[0] = xy[0] + mScrollX - v.getLeft();
981 xy[1] = xy[1] + mScrollY - v.getTop();
982 v.getMatrix().invert(mTempInverseMatrix);
983 mTempInverseMatrix.mapPoints(xy);
984 }
985
Michael Jurkaa63c4522010-08-19 13:52:27 -0700986 // xy = upper left corner of item being dragged
987 // bottomRightXy = lower right corner of item being dragged
988 // This method will see which mini-screen is most overlapped by the item being dragged, and
989 // return it. It will also transform the parameters xy and bottomRightXy into the local
990 // coordinate space of the returned screen
Michael Jurka0280c3b2010-09-17 15:00:07 -0700991 private CellLayout findMatchingPageForDragOver(DragView dragView, int originX, int originY) {
992 float x = originX + dragView.getScaledDragRegionXOffset();
993 float y = originY + dragView.getScaledDragRegionYOffset();
994 float right = x + dragView.getScaledDragRegionWidth();
995 float bottom = y + dragView.getScaledDragRegionHeight();
Michael Jurkaa63c4522010-08-19 13:52:27 -0700996
997 // We loop through all the screens (ie CellLayouts) and see which one overlaps the most
998 // with the item being dragged.
999 final int screenCount = getChildCount();
1000 CellLayout bestMatchingScreen = null;
Michael Jurka0280c3b2010-09-17 15:00:07 -07001001 float smallestDistSoFar = Float.MAX_VALUE;
1002 final float[] xy = mTempDragCoordinates;
1003 final float[] bottomRightXy = mTempDragBottomRightCoordinates;
Michael Jurkaa63c4522010-08-19 13:52:27 -07001004 for (int i = 0; i < screenCount; i++) {
1005 CellLayout cl = (CellLayout)getChildAt(i);
1006 // Transform the coordinates of the item being dragged to the CellLayout's coordinates
1007 float left = cl.getLeft();
1008 float top = cl.getTop();
1009 xy[0] = x + mScrollX - left;
1010 xy[1] = y + mScrollY - top;
Michael Jurkaa63c4522010-08-19 13:52:27 -07001011
1012 bottomRightXy[0] = right + mScrollX - left;
1013 bottomRightXy[1] = bottom + mScrollY - top;
1014
Michael Jurka0280c3b2010-09-17 15:00:07 -07001015 cl.getMatrix().invert(mTempInverseMatrix);
1016 mTempInverseMatrix.mapPoints(xy);
1017 mTempInverseMatrix.mapPoints(bottomRightXy);
Michael Jurkaa63c4522010-08-19 13:52:27 -07001018
1019 float dragRegionX = xy[0];
1020 float dragRegionY = xy[1];
1021 float dragRegionRight = bottomRightXy[0];
1022 float dragRegionBottom = bottomRightXy[1];
Michael Jurka0280c3b2010-09-17 15:00:07 -07001023 float dragRegionCenterX = (dragRegionX + dragRegionRight) / 2.0f;
1024 float dragRegionCenterY = (dragRegionY + dragRegionBottom) / 2.0f;
Michael Jurkaa63c4522010-08-19 13:52:27 -07001025
1026 // Find the overlapping region
1027 float overlapLeft = Math.max(0f, dragRegionX);
1028 float overlapTop = Math.max(0f, dragRegionY);
1029 float overlapBottom = Math.min(cl.getHeight(), dragRegionBottom);
1030 float overlapRight = Math.min(cl.getWidth(), dragRegionRight);
Michael Jurkaa63c4522010-08-19 13:52:27 -07001031 if (overlapRight >= 0 && overlapLeft <= cl.getWidth() &&
Michael Jurka0280c3b2010-09-17 15:00:07 -07001032 (overlapTop >= 0 && overlapBottom <= cl.getHeight())) {
1033 // Calculate the distance between the two centers
1034 float distX = dragRegionCenterX - cl.getWidth()/2;
1035 float distY = dragRegionCenterY - cl.getHeight()/2;
1036 float dist = distX * distX + distY * distY;
1037
Michael Jurkaa63c4522010-08-19 13:52:27 -07001038 float overlap = (overlapRight - overlapLeft) * (overlapBottom - overlapTop);
Michael Jurka0280c3b2010-09-17 15:00:07 -07001039
1040 // Calculate the closest overlapping region
1041 if (overlap > 0 && dist < smallestDistSoFar) {
1042 smallestDistSoFar = dist;
Michael Jurkaa63c4522010-08-19 13:52:27 -07001043 bestMatchingScreen = cl;
Michael Jurkaa63c4522010-08-19 13:52:27 -07001044 }
1045 }
1046 }
Michael Jurka0280c3b2010-09-17 15:00:07 -07001047
1048 if (bestMatchingScreen != mDragTargetLayout) {
Michael Jurkaa63c4522010-08-19 13:52:27 -07001049 if (mDragTargetLayout != null) {
Michael Jurka0280c3b2010-09-17 15:00:07 -07001050 mDragTargetLayout.onDragExit();
Michael Jurkaa63c4522010-08-19 13:52:27 -07001051 }
1052 mDragTargetLayout = bestMatchingScreen;
1053 }
Michael Jurkaa63c4522010-08-19 13:52:27 -07001054 return bestMatchingScreen;
1055 }
1056
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001057 public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
1058 DragView dragView, Object dragInfo) {
Michael Jurka0280c3b2010-09-17 15:00:07 -07001059 CellLayout currentLayout;
1060 int originX = x - xOffset;
1061 int originY = y - yOffset;
1062 if (mIsSmall) {
1063 currentLayout = findMatchingPageForDragOver(dragView, originX, originY);
1064
1065 if (currentLayout == null) {
1066 return;
1067 }
1068
1069 currentLayout.setHover(true);
1070 // get originX and originY in the local coordinate system of the screen
1071 mTempOriginXY[0] = originX;
1072 mTempOriginXY[1] = originY;
1073 mapPointGlobalToLocal(currentLayout, mTempOriginXY);
1074 originX = (int)mTempOriginXY[0];
1075 originY = (int)mTempOriginXY[1];
1076 } else {
1077 currentLayout = getCurrentDropLayout();
1078 }
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001079
Patrick Dubroy976ebec2010-08-04 20:03:37 -07001080 final ItemInfo item = (ItemInfo)dragInfo;
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001081
1082 if (dragInfo instanceof LauncherAppWidgetInfo) {
1083 LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
1084
1085 if (widgetInfo.spanX == -1) {
1086 // Calculate the grid spans needed to fit this widget
Patrick Dubroy8f86ddc2010-07-16 13:55:32 -07001087 int[] spans = currentLayout.rectToCell(widgetInfo.minWidth, widgetInfo.minHeight, null);
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001088 item.spanX = spans[0];
1089 item.spanY = spans[1];
1090 }
1091 }
Michael Jurkaa63c4522010-08-19 13:52:27 -07001092
1093 if (source != this) {
1094 // This is a hack to fix the point used to determine which cell an icon from the all
1095 // apps screen is over
1096 if (item != null && item.spanX == 1 && currentLayout != null) {
1097 int dragRegionLeft = (dragView.getWidth() - currentLayout.getCellWidth()) / 2;
1098
1099 originX += dragRegionLeft - dragView.getDragRegionLeft();
1100 if (dragView.getDragRegionWidth() != currentLayout.getCellWidth()) {
1101 dragView.setDragRegion(dragView.getDragRegionLeft(), dragView.getDragRegionTop(),
1102 currentLayout.getCellWidth(), dragView.getDragRegionHeight());
1103 }
1104 }
1105 }
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001106 if (currentLayout != mDragTargetLayout) {
1107 if (mDragTargetLayout != null) {
Michael Jurka0280c3b2010-09-17 15:00:07 -07001108 mDragTargetLayout.onDragExit();
Patrick Dubroyde7658b2010-09-27 11:15:43 -07001109 currentLayout.onDragEnter(dragView);
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001110 }
1111 mDragTargetLayout = currentLayout;
1112 }
1113
Michael Jurkaa63c4522010-08-19 13:52:27 -07001114 // only visualize the drop locations for moving icons within the home screen on tablet
1115 // on phone, we also visualize icons dragged in from All Apps
1116 if ((!LauncherApplication.isScreenXLarge() || source == this)
1117 && mDragTargetLayout != null) {
1118 final View child = (mDragInfo == null) ? null : mDragInfo.cell;
Michael Jurka5f1c5092010-09-03 14:15:02 -07001119 int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
1120 int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
Michael Jurkaa63c4522010-08-19 13:52:27 -07001121 mDragTargetLayout.visualizeDropLocation(
Patrick Dubroyde7658b2010-09-27 11:15:43 -07001122 child, localOriginX, localOriginY, item.spanX, item.spanY);
Patrick Dubroy976ebec2010-08-04 20:03:37 -07001123 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001124 }
1125
Winson Chungaafa03c2010-06-11 17:34:16 -07001126 public void onDragExit(DragSource source, int x, int y, int xOffset,
1127 int yOffset, DragView dragView, Object dragInfo) {
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001128 if (mDragTargetLayout != null) {
Michael Jurka0280c3b2010-09-17 15:00:07 -07001129 mDragTargetLayout.onDragExit();
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001130 mDragTargetLayout = null;
1131 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001132 }
1133
Winson Chungaafa03c2010-06-11 17:34:16 -07001134 private void onDropExternal(int x, int y, Object dragInfo,
1135 CellLayout cellLayout) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001136 onDropExternal(x, y, dragInfo, cellLayout, false);
1137 }
Winson Chungaafa03c2010-06-11 17:34:16 -07001138
Patrick Dubroy2b9ff372010-09-07 17:49:27 -07001139 /**
1140 * Add the item specified by dragInfo to the given layout.
1141 * This is basically the equivalent of onDropExternal, except it's not initiated
1142 * by drag and drop.
1143 * @return true if successful
1144 */
1145 public boolean addExternalItemToScreen(Object dragInfo, View layout) {
1146 CellLayout cl = (CellLayout) layout;
1147 ItemInfo info = (ItemInfo) dragInfo;
1148
Michael Jurka0280c3b2010-09-17 15:00:07 -07001149 if (cl.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
Patrick Dubroy2b9ff372010-09-07 17:49:27 -07001150 onDropExternal(0, 0, dragInfo, cl, false);
1151 return true;
1152 }
Michael Jurka0280c3b2010-09-17 15:00:07 -07001153 mLauncher.showOutOfSpaceMessage();
Patrick Dubroy2b9ff372010-09-07 17:49:27 -07001154 return false;
1155 }
1156
Michael Jurka0280c3b2010-09-17 15:00:07 -07001157 // Drag from somewhere else
Winson Chungaafa03c2010-06-11 17:34:16 -07001158 private void onDropExternal(int x, int y, Object dragInfo,
1159 CellLayout cellLayout, boolean insertAtFirst) {
Michael Jurka0280c3b2010-09-17 15:00:07 -07001160 int screen = indexOfChild(cellLayout);
1161 if (dragInfo instanceof PendingAddItemInfo) {
1162 PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
1163 // When dragging and dropping from customization tray, we deal with creating
1164 // widgets/shortcuts/folders in a slightly different way
1165 int[] touchXY = new int[2];
1166 touchXY[0] = x;
1167 touchXY[1] = y;
1168 switch (info.itemType) {
1169 case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
1170 mLauncher.addAppWidgetFromDrop(info.componentName, screen, touchXY);
1171 break;
1172 case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
1173 mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
1174 break;
1175 case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1176 mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
1177 break;
1178 default:
1179 throw new IllegalStateException("Unknown item type: " + info.itemType);
1180 }
1181 cellLayout.onDragExit();
1182 return;
1183 }
1184
1185 // This is for other drag/drop cases, like dragging from All Apps
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001186 ItemInfo info = (ItemInfo) dragInfo;
1187
Michael Jurkaaf442092010-06-10 17:01:57 -07001188 View view = null;
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001189
1190 switch (info.itemType) {
1191 case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
1192 case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
Joe Onoratoe48e7c12010-02-19 13:10:40 -08001193 if (info.container == NO_ID && info instanceof ApplicationInfo) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001194 // Came from all apps -- make a copy
Winson Chungaafa03c2010-06-11 17:34:16 -07001195 info = new ShortcutInfo((ApplicationInfo) info);
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001196 }
Winson Chungaafa03c2010-06-11 17:34:16 -07001197 view = mLauncher.createShortcut(R.layout.application, cellLayout,
1198 (ShortcutInfo) info);
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001199 break;
1200 case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
1201 view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
Michael Jurka0280c3b2010-09-17 15:00:07 -07001202 cellLayout, ((UserFolderInfo) info));
Michael Jurkaaf442092010-06-10 17:01:57 -07001203 break;
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001204 default:
Michael Jurka0280c3b2010-09-17 15:00:07 -07001205 throw new IllegalStateException("Unknown item type: " + info.itemType);
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001206 }
1207
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001208 // If the view is null, it has already been added.
1209 if (view == null) {
Michael Jurka0280c3b2010-09-17 15:00:07 -07001210 cellLayout.onDragExit();
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001211 } else {
Michael Jurka7ded67c2010-09-28 13:57:39 -07001212 mTargetCell = findNearestVacantArea(x, y, 1, 1, null, cellLayout, mTargetCell);
Winson Chungaafa03c2010-06-11 17:34:16 -07001213 addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
1214 mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
1215 cellLayout.onDropChild(view);
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001216 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
Michael Jurkaaf442092010-06-10 17:01:57 -07001217
1218 LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
Michael Jurka0280c3b2010-09-17 15:00:07 -07001219 LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
Winson Chungaafa03c2010-06-11 17:34:16 -07001220 lp.cellX, lp.cellY);
Joe Onorato00acb122009-08-04 16:04:30 -04001221 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001222 }
Winson Chungaafa03c2010-06-11 17:34:16 -07001223
Jeff Sharkey70864282009-04-07 21:08:40 -07001224 /**
1225 * Return the current {@link CellLayout}, correctly picking the destination
1226 * screen while a scroll is in progress.
1227 */
1228 private CellLayout getCurrentDropLayout() {
Michael Jurka0142d492010-08-25 17:46:15 -07001229 int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
Jeff Sharkey70864282009-04-07 21:08:40 -07001230 return (CellLayout) getChildAt(index);
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001231 }
1232
Jeff Sharkey70864282009-04-07 21:08:40 -07001233 /**
Michael Jurka0280c3b2010-09-17 15:00:07 -07001234 * Return the current CellInfo describing our current drag; this method exists
1235 * so that Launcher can sync this object with the correct info when the activity is created/
1236 * destroyed
1237 *
1238 */
1239 public CellLayout.CellInfo getDragInfo() {
1240 return mDragInfo;
1241 }
1242
1243 /**
Jeff Sharkey70864282009-04-07 21:08:40 -07001244 * {@inheritDoc}
1245 */
1246 public boolean acceptDrop(DragSource source, int x, int y,
Joe Onorato00acb122009-08-04 16:04:30 -04001247 int xOffset, int yOffset, DragView dragView, Object dragInfo) {
Michael Jurka0280c3b2010-09-17 15:00:07 -07001248 CellLayout layout;
1249 if (mIsSmall) {
1250 layout = findMatchingPageForDragOver(dragView, x - xOffset, y - yOffset);
1251 if (layout == null) {
1252 // cancel the drag if we're not over a mini-screen at time of drop
1253 return false;
1254 }
1255 } else {
1256 layout = getCurrentDropLayout();
1257 }
Michael Jurkac28de512010-08-13 11:27:44 -07001258 final CellLayout.CellInfo dragCellInfo = mDragInfo;
1259 final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
1260 final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
Romain Guy4c58c482009-05-12 17:35:41 -07001261
Michael Jurkac28de512010-08-13 11:27:44 -07001262 final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
Romain Guy4c58c482009-05-12 17:35:41 -07001263
Michael Jurka0280c3b2010-09-17 15:00:07 -07001264 if (layout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
Michael Jurka0e260592010-06-30 17:07:39 -07001265 return true;
1266 } else {
Michael Jurka0280c3b2010-09-17 15:00:07 -07001267 mLauncher.showOutOfSpaceMessage();
Michael Jurka0e260592010-06-30 17:07:39 -07001268 return false;
1269 }
Jeff Sharkey70864282009-04-07 21:08:40 -07001270 }
Winson Chungaafa03c2010-06-11 17:34:16 -07001271
Jeff Sharkey70864282009-04-07 21:08:40 -07001272 /**
Jeff Sharkey70864282009-04-07 21:08:40 -07001273 * Calculate the nearest cell where the given object would be dropped.
1274 */
Michael Jurka6a1435d2010-09-27 17:35:12 -07001275 private int[] findNearestVacantArea(int pixelX, int pixelY,
Jeff Sharkey70864282009-04-07 21:08:40 -07001276 int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001277
Michael Jurka5f1c5092010-09-03 14:15:02 -07001278 int localPixelX = pixelX - (layout.getLeft() - mScrollX);
1279 int localPixelY = pixelY - (layout.getTop() - mScrollY);
Patrick Dubroy6569f2c2010-07-12 14:25:18 -07001280
Jeff Sharkey70864282009-04-07 21:08:40 -07001281 // Find the best target drop location
Michael Jurka0280c3b2010-09-17 15:00:07 -07001282 return layout.findNearestVacantArea(
Michael Jurkafc9f07d2010-09-30 13:22:31 -07001283 localPixelX, localPixelY, spanX, spanY, ignoreView, recycle);
Jeff Sharkey70864282009-04-07 21:08:40 -07001284 }
Winson Chungaafa03c2010-06-11 17:34:16 -07001285
Patrick Dubroy8f86ddc2010-07-16 13:55:32 -07001286 /**
1287 * Estimate the size that a child with the given dimensions will take in the current screen.
1288 */
1289 void estimateChildSize(int minWidth, int minHeight, int[] result) {
Michael Jurka0142d492010-08-25 17:46:15 -07001290 ((CellLayout)getChildAt(mCurrentPage)).estimateChildSize(minWidth, minHeight, result);
Patrick Dubroy8f86ddc2010-07-16 13:55:32 -07001291 }
1292
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001293 void setLauncher(Launcher launcher) {
1294 mLauncher = launcher;
1295 }
1296
Joe Onorato00acb122009-08-04 16:04:30 -04001297 public void setDragController(DragController dragController) {
1298 mDragController = dragController;
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001299 }
1300
1301 public void onDropCompleted(View target, boolean success) {
Winson Chungaafa03c2010-06-11 17:34:16 -07001302 if (success) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001303 if (target != this && mDragInfo != null) {
1304 final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
1305 cellLayout.removeView(mDragInfo.cell);
Joe Onorato00acb122009-08-04 16:04:30 -04001306 if (mDragInfo.cell instanceof DropTarget) {
1307 mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
1308 }
Winson Chungaafa03c2010-06-11 17:34:16 -07001309 // final Object tag = mDragInfo.cell.getTag();
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001310 }
1311 } else {
1312 if (mDragInfo != null) {
1313 final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
1314 cellLayout.onDropAborted(mDragInfo.cell);
1315 }
1316 }
1317
1318 mDragInfo = null;
1319 }
1320
Michael Jurka0280c3b2010-09-17 15:00:07 -07001321 public boolean isDropEnabled() {
1322 return true;
1323 }
1324
Michael Jurka0142d492010-08-25 17:46:15 -07001325 @Override
1326 protected void onRestoreInstanceState(Parcelable state) {
1327 super.onRestoreInstanceState(state);
1328 Launcher.setScreen(mCurrentPage);
1329 }
1330
1331 @Override
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001332 public void scrollLeft() {
Michael Jurka7f0f4f32010-08-23 11:33:38 -07001333 if (!mIsSmall) {
Michael Jurka0142d492010-08-25 17:46:15 -07001334 super.scrollLeft();
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001335 }
1336 }
1337
Michael Jurka0142d492010-08-25 17:46:15 -07001338 @Override
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001339 public void scrollRight() {
Michael Jurka7f0f4f32010-08-23 11:33:38 -07001340 if (!mIsSmall) {
Michael Jurka0142d492010-08-25 17:46:15 -07001341 super.scrollRight();
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001342 }
1343 }
1344
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001345 public Folder getFolderForTag(Object tag) {
Michael Jurkadee05892010-07-27 10:01:56 -07001346 final int screenCount = getChildCount();
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001347 for (int screen = 0; screen < screenCount; screen++) {
1348 CellLayout currentScreen = ((CellLayout) getChildAt(screen));
1349 int count = currentScreen.getChildCount();
1350 for (int i = 0; i < count; i++) {
1351 View child = currentScreen.getChildAt(i);
1352 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
1353 if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
1354 Folder f = (Folder) child;
Winson Chungaafa03c2010-06-11 17:34:16 -07001355 if (f.getInfo() == tag && f.getInfo().opened) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001356 return f;
1357 }
1358 }
1359 }
1360 }
1361 return null;
1362 }
1363
1364 public View getViewForTag(Object tag) {
1365 int screenCount = getChildCount();
1366 for (int screen = 0; screen < screenCount; screen++) {
1367 CellLayout currentScreen = ((CellLayout) getChildAt(screen));
1368 int count = currentScreen.getChildCount();
1369 for (int i = 0; i < count; i++) {
1370 View child = currentScreen.getChildAt(i);
1371 if (child.getTag() == tag) {
1372 return child;
1373 }
1374 }
1375 }
1376 return null;
1377 }
1378
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001379
Joe Onorato64e6be72010-03-05 15:05:52 -05001380 void removeItems(final ArrayList<ApplicationInfo> apps) {
Michael Jurkadee05892010-07-27 10:01:56 -07001381 final int screenCount = getChildCount();
Romain Guy5c16f3e2010-01-12 17:24:58 -08001382 final PackageManager manager = getContext().getPackageManager();
Romain Guy629de3e2010-01-13 12:20:59 -08001383 final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
Romain Guy574d20e2009-06-01 15:34:04 -07001384
Joe Onorato64e6be72010-03-05 15:05:52 -05001385 final HashSet<String> packageNames = new HashSet<String>();
1386 final int appCount = apps.size();
1387 for (int i = 0; i < appCount; i++) {
1388 packageNames.add(apps.get(i).componentName.getPackageName());
1389 }
1390
Michael Jurkadee05892010-07-27 10:01:56 -07001391 for (int i = 0; i < screenCount; i++) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001392 final CellLayout layout = (CellLayout) getChildAt(i);
Romain Guy574d20e2009-06-01 15:34:04 -07001393
Romain Guy629de3e2010-01-13 12:20:59 -08001394 // Avoid ANRs by treating each screen separately
1395 post(new Runnable() {
1396 public void run() {
1397 final ArrayList<View> childrenToRemove = new ArrayList<View>();
1398 childrenToRemove.clear();
Winson Chungaafa03c2010-06-11 17:34:16 -07001399
Romain Guy629de3e2010-01-13 12:20:59 -08001400 int childCount = layout.getChildCount();
1401 for (int j = 0; j < childCount; j++) {
1402 final View view = layout.getChildAt(j);
1403 Object tag = view.getTag();
Winson Chungaafa03c2010-06-11 17:34:16 -07001404
Joe Onorato0589f0f2010-02-08 13:44:00 -08001405 if (tag instanceof ShortcutInfo) {
1406 final ShortcutInfo info = (ShortcutInfo) tag;
Romain Guy629de3e2010-01-13 12:20:59 -08001407 final Intent intent = info.intent;
1408 final ComponentName name = intent.getComponent();
Winson Chungaafa03c2010-06-11 17:34:16 -07001409
Joe Onorato64e6be72010-03-05 15:05:52 -05001410 if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
1411 for (String packageName: packageNames) {
1412 if (packageName.equals(name.getPackageName())) {
Joe Onorato64e6be72010-03-05 15:05:52 -05001413 LauncherModel.deleteItemFromDatabase(mLauncher, info);
1414 childrenToRemove.add(view);
1415 }
1416 }
Romain Guy629de3e2010-01-13 12:20:59 -08001417 }
1418 } else if (tag instanceof UserFolderInfo) {
1419 final UserFolderInfo info = (UserFolderInfo) tag;
Joe Onorato0589f0f2010-02-08 13:44:00 -08001420 final ArrayList<ShortcutInfo> contents = info.contents;
1421 final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
Romain Guy629de3e2010-01-13 12:20:59 -08001422 final int contentsCount = contents.size();
1423 boolean removedFromFolder = false;
Winson Chungaafa03c2010-06-11 17:34:16 -07001424
Romain Guy629de3e2010-01-13 12:20:59 -08001425 for (int k = 0; k < contentsCount; k++) {
Joe Onorato0589f0f2010-02-08 13:44:00 -08001426 final ShortcutInfo appInfo = contents.get(k);
Romain Guy629de3e2010-01-13 12:20:59 -08001427 final Intent intent = appInfo.intent;
1428 final ComponentName name = intent.getComponent();
Winson Chungaafa03c2010-06-11 17:34:16 -07001429
Joe Onorato64e6be72010-03-05 15:05:52 -05001430 if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
1431 for (String packageName: packageNames) {
1432 if (packageName.equals(name.getPackageName())) {
1433 toRemove.add(appInfo);
Brad Fitzpatrick73013bf2010-09-14 12:15:32 -07001434 LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
Joe Onorato64e6be72010-03-05 15:05:52 -05001435 removedFromFolder = true;
1436 }
1437 }
Romain Guy629de3e2010-01-13 12:20:59 -08001438 }
1439 }
Winson Chungaafa03c2010-06-11 17:34:16 -07001440
Romain Guy629de3e2010-01-13 12:20:59 -08001441 contents.removeAll(toRemove);
1442 if (removedFromFolder) {
1443 final Folder folder = getOpenFolder();
Winson Chungaafa03c2010-06-11 17:34:16 -07001444 if (folder != null)
1445 folder.notifyDataSetChanged();
Romain Guy629de3e2010-01-13 12:20:59 -08001446 }
1447 } else if (tag instanceof LiveFolderInfo) {
1448 final LiveFolderInfo info = (LiveFolderInfo) tag;
1449 final Uri uri = info.uri;
1450 final ProviderInfo providerInfo = manager.resolveContentProvider(
1451 uri.getAuthority(), 0);
Romain Guy574d20e2009-06-01 15:34:04 -07001452
Joe Onoratof11079b2010-04-15 11:47:28 -07001453 if (providerInfo != null) {
Joe Onorato64e6be72010-03-05 15:05:52 -05001454 for (String packageName: packageNames) {
1455 if (packageName.equals(providerInfo.packageName)) {
Joe Onorato64e6be72010-03-05 15:05:52 -05001456 LauncherModel.deleteItemFromDatabase(mLauncher, info);
Winson Chungaafa03c2010-06-11 17:34:16 -07001457 childrenToRemove.add(view);
Joe Onorato64e6be72010-03-05 15:05:52 -05001458 }
1459 }
Romain Guy629de3e2010-01-13 12:20:59 -08001460 }
1461 } else if (tag instanceof LauncherAppWidgetInfo) {
1462 final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
1463 final AppWidgetProviderInfo provider =
1464 widgets.getAppWidgetInfo(info.appWidgetId);
Daniel Sandlere1cc6c32010-05-07 11:49:29 -04001465 if (provider != null) {
Joe Onorato64e6be72010-03-05 15:05:52 -05001466 for (String packageName: packageNames) {
1467 if (packageName.equals(provider.provider.getPackageName())) {
Joe Onorato64e6be72010-03-05 15:05:52 -05001468 LauncherModel.deleteItemFromDatabase(mLauncher, info);
Winson Chungaafa03c2010-06-11 17:34:16 -07001469 childrenToRemove.add(view);
Joe Onorato64e6be72010-03-05 15:05:52 -05001470 }
1471 }
Romain Guy629de3e2010-01-13 12:20:59 -08001472 }
Romain Guy574d20e2009-06-01 15:34:04 -07001473 }
1474 }
Winson Chungaafa03c2010-06-11 17:34:16 -07001475
Romain Guy629de3e2010-01-13 12:20:59 -08001476 childCount = childrenToRemove.size();
1477 for (int j = 0; j < childCount; j++) {
1478 View child = childrenToRemove.get(j);
1479 layout.removeViewInLayout(child);
1480 if (child instanceof DropTarget) {
1481 mDragController.removeDropTarget((DropTarget)child);
1482 }
Romain Guy574d20e2009-06-01 15:34:04 -07001483 }
Winson Chungaafa03c2010-06-11 17:34:16 -07001484
Romain Guy629de3e2010-01-13 12:20:59 -08001485 if (childCount > 0) {
1486 layout.requestLayout();
1487 layout.invalidate();
Romain Guy5c16f3e2010-01-12 17:24:58 -08001488 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001489 }
Romain Guy629de3e2010-01-13 12:20:59 -08001490 });
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001491 }
1492 }
The Android Open Source Projectf96811c2009-03-18 17:39:48 -07001493
Joe Onorato64e6be72010-03-05 15:05:52 -05001494 void updateShortcuts(ArrayList<ApplicationInfo> apps) {
Michael Jurkadee05892010-07-27 10:01:56 -07001495 final int screenCount = getChildCount();
1496 for (int i = 0; i < screenCount; i++) {
The Android Open Source Projectf96811c2009-03-18 17:39:48 -07001497 final CellLayout layout = (CellLayout) getChildAt(i);
1498 int childCount = layout.getChildCount();
1499 for (int j = 0; j < childCount; j++) {
1500 final View view = layout.getChildAt(j);
1501 Object tag = view.getTag();
Joe Onorato0589f0f2010-02-08 13:44:00 -08001502 if (tag instanceof ShortcutInfo) {
1503 ShortcutInfo info = (ShortcutInfo)tag;
The Android Open Source Projectf96811c2009-03-18 17:39:48 -07001504 // We need to check for ACTION_MAIN otherwise getComponent() might
1505 // return null for some shortcuts (for instance, for shortcuts to
1506 // web pages.)
1507 final Intent intent = info.intent;
1508 final ComponentName name = intent.getComponent();
1509 if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
Joe Onorato64e6be72010-03-05 15:05:52 -05001510 Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
1511 final int appCount = apps.size();
Winson Chungaafa03c2010-06-11 17:34:16 -07001512 for (int k = 0; k < appCount; k++) {
Joe Onorato64e6be72010-03-05 15:05:52 -05001513 ApplicationInfo app = apps.get(k);
1514 if (app.componentName.equals(name)) {
1515 info.setIcon(mIconCache.getIcon(info.intent));
1516 ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null,
1517 new FastBitmapDrawable(info.getIcon(mIconCache)),
1518 null, null);
1519 }
1520 }
The Android Open Source Projectf96811c2009-03-18 17:39:48 -07001521 }
1522 }
1523 }
1524 }
1525 }
1526
Joe Onorato14f122b2009-11-19 14:06:36 -08001527 void moveToDefaultScreen(boolean animate) {
Joe Onoratoc45b1682010-01-11 18:48:40 -05001528 if (animate) {
Michael Jurka4cb37242010-08-09 21:05:32 -07001529 if (mIsSmall) {
Michael Jurka0142d492010-08-25 17:46:15 -07001530 unshrink(mDefaultPage);
Michael Jurka4cb37242010-08-09 21:05:32 -07001531 } else {
Michael Jurka0142d492010-08-25 17:46:15 -07001532 snapToPage(mDefaultPage);
Michael Jurka4cb37242010-08-09 21:05:32 -07001533 }
Joe Onoratoc45b1682010-01-11 18:48:40 -05001534 } else {
Michael Jurka0142d492010-08-25 17:46:15 -07001535 setCurrentPage(mDefaultPage);
Joe Onoratoc45b1682010-01-11 18:48:40 -05001536 }
Michael Jurka0142d492010-08-25 17:46:15 -07001537 getChildAt(mDefaultPage).requestFocus();
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001538 }
1539
Romain Guy8a73c512009-11-09 19:19:59 -08001540 void setIndicators(Drawable previous, Drawable next) {
1541 mPreviousIndicator = previous;
1542 mNextIndicator = next;
Michael Jurka0142d492010-08-25 17:46:15 -07001543 previous.setLevel(mCurrentPage);
1544 next.setLevel(mCurrentPage);
Romain Guy8a73c512009-11-09 19:19:59 -08001545 }
1546
Michael Jurka0142d492010-08-25 17:46:15 -07001547 @Override
1548 public void syncPages() {
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001549 }
Michael Jurka0142d492010-08-25 17:46:15 -07001550
1551 @Override
1552 public void syncPageItems(int page) {
1553 }
1554
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001555}