blob: 0470e41f5a5104270cdc905c79478a2731205756 [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
Adam Cohendf2cc412011-04-27 16:56:57 -070019import java.util.ArrayList;
20
21import android.animation.Animator;
22import android.animation.AnimatorListenerAdapter;
Adam Cohendf2cc412011-04-27 16:56:57 -070023import android.animation.ObjectAnimator;
24import android.animation.PropertyValuesHolder;
25import android.animation.ValueAnimator;
26import android.animation.ValueAnimator.AnimatorUpdateListener;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080027import android.content.Context;
Romain Guyfb5411e2010-02-24 10:04:17 -080028import android.graphics.Rect;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080029import android.util.AttributeSet;
Adam Cohendf2cc412011-04-27 16:56:57 -070030import android.view.LayoutInflater;
Adam Cohen0c872ba2011-05-05 10:34:16 -070031import android.view.MotionEvent;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080032import android.view.View;
33import android.view.View.OnClickListener;
Adam Cohen2801caf2011-05-13 20:57:39 -070034import android.view.animation.AccelerateInterpolator;
35import android.view.animation.DecelerateInterpolator;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080036import android.widget.AdapterView;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080037import android.widget.LinearLayout;
Adam Cohendf2cc412011-04-27 16:56:57 -070038import android.widget.TextView;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080039import android.widget.AdapterView.OnItemClickListener;
40import android.widget.AdapterView.OnItemLongClickListener;
41
Romain Guyedcce092010-03-04 13:03:17 -080042import com.android.launcher.R;
Adam Cohena9cf38f2011-05-02 15:36:58 -070043import com.android.launcher2.FolderInfo.FolderListener;
Romain Guyedcce092010-03-04 13:03:17 -080044
The Android Open Source Project31dd5032009-03-03 19:32:27 -080045/**
46 * Represents a set of icons chosen by the user or generated by the system.
47 */
48public class Folder extends LinearLayout implements DragSource, OnItemLongClickListener,
Adam Cohena9cf38f2011-05-02 15:36:58 -070049 OnItemClickListener, OnClickListener, View.OnLongClickListener, DropTarget, FolderListener {
The Android Open Source Project31dd5032009-03-03 19:32:27 -080050
Joe Onorato00acb122009-08-04 16:04:30 -040051 protected DragController mDragController;
Adam Cohendf2cc412011-04-27 16:56:57 -070052
The Android Open Source Project31dd5032009-03-03 19:32:27 -080053 protected Launcher mLauncher;
54
The Android Open Source Project31dd5032009-03-03 19:32:27 -080055 protected FolderInfo mInfo;
56
57 /**
58 * Which item is being dragged
59 */
Joe Onorato0589f0f2010-02-08 13:44:00 -080060 protected ShortcutInfo mDragItem;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080061
Adam Cohendf2cc412011-04-27 16:56:57 -070062 private static final String TAG = "Launcher.Folder";
63
64 static final int STATE_NONE = -1;
65 static final int STATE_SMALL = 0;
66 static final int STATE_ANIMATING = 1;
67 static final int STATE_OPEN = 2;
68
69 private int mExpandDuration;
70 protected CellLayout mContent;
71 private final LayoutInflater mInflater;
72 private final IconCache mIconCache;
73 private int mState = STATE_NONE;
Adam Cohena9cf38f2011-05-02 15:36:58 -070074 private int[] mDragItemPosition = new int[2];
Adam Cohen2801caf2011-05-13 20:57:39 -070075 private static final int FULL_GROW = 0;
76 private static final int PARTIAL_GROW = 1;
77 private int mMode = PARTIAL_GROW;
78 private boolean mRearrangeOnClose = false;
79 private FolderIcon mFolderIcon;
80 private int mMaxCountX;
81 private int mMaxCountY;
82 private Rect mNewSize = new Rect();
Adam Cohen7c693212011-05-18 15:26:57 -070083 private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
84 boolean mItemsInvalidated = false;
Adam Cohendf2cc412011-04-27 16:56:57 -070085
The Android Open Source Project31dd5032009-03-03 19:32:27 -080086 /**
87 * Used to inflate the Workspace from XML.
88 *
89 * @param context The application's context.
90 * @param attrs The attribtues set containing the Workspace's customization values.
91 */
92 public Folder(Context context, AttributeSet attrs) {
93 super(context, attrs);
94 setAlwaysDrawnWithCacheEnabled(false);
Adam Cohendf2cc412011-04-27 16:56:57 -070095 mInflater = LayoutInflater.from(context);
96 mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
97 mExpandDuration = getResources().getInteger(R.integer.config_folderAnimDuration);
Adam Cohen2801caf2011-05-13 20:57:39 -070098
99 mMaxCountX = LauncherModel.getCellCountX() - 1;
100 mMaxCountY = LauncherModel.getCellCountY() - 1;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800101 }
102
103 @Override
104 protected void onFinishInflate() {
105 super.onFinishInflate();
Adam Cohendf2cc412011-04-27 16:56:57 -0700106 mContent = (CellLayout) findViewById(R.id.folder_content);
Adam Cohen2801caf2011-05-13 20:57:39 -0700107 mContent.setGridSize(0, 0);
108 mContent.enableHardwareLayers();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800109 }
Adam Cohen2801caf2011-05-13 20:57:39 -0700110
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800111 public void onItemClick(AdapterView parent, View v, int position, long id) {
Joe Onorato0589f0f2010-02-08 13:44:00 -0800112 ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
Romain Guyfb5411e2010-02-24 10:04:17 -0800113 int[] pos = new int[2];
114 v.getLocationOnScreen(pos);
115 app.intent.setSourceBounds(new Rect(pos[0], pos[1],
116 pos[0] + v.getWidth(), pos[1] + v.getHeight()));
Joe Onoratof984e852010-03-25 09:47:45 -0700117 mLauncher.startActivitySafely(app.intent, app);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800118 }
119
120 public void onClick(View v) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700121 Object tag = v.getTag();
122 if (tag instanceof ShortcutInfo) {
123 // refactor this code from Folder
124 ShortcutInfo item = (ShortcutInfo) tag;
125 int[] pos = new int[2];
126 v.getLocationOnScreen(pos);
127 item.intent.setSourceBounds(new Rect(pos[0], pos[1],
128 pos[0] + v.getWidth(), pos[1] + v.getHeight()));
129 mLauncher.startActivitySafely(item.intent, item);
Adam Cohendf2cc412011-04-27 16:56:57 -0700130 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800131 }
132
133 public boolean onLongClick(View v) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700134 Object tag = v.getTag();
135 if (tag instanceof ShortcutInfo) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700136 mLauncher.closeFolder(this);
137
Adam Cohendf2cc412011-04-27 16:56:57 -0700138 ShortcutInfo item = (ShortcutInfo) tag;
139 if (!v.isInTouchMode()) {
140 return false;
141 }
142
143 mLauncher.getWorkspace().onDragStartedWithItem(v);
144 mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700145 mDragItemPosition[0] = item.cellX;
146 mDragItemPosition[1] = item.cellY;
Adam Cohen2801caf2011-05-13 20:57:39 -0700147 mInfo.remove(item);
148
Adam Cohendf2cc412011-04-27 16:56:57 -0700149 mDragItem = item;
150 } else {
151 mLauncher.closeFolder(this);
152 mLauncher.showRenameDialog(mInfo);
153 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800154 return true;
155 }
156
Adam Cohen0c872ba2011-05-05 10:34:16 -0700157 /**
158 * We need to handle touch events to prevent them from falling through to the workspace below.
159 */
160 @Override
161 public boolean onTouchEvent(MotionEvent ev) {
162 return true;
163 }
164
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800165 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
166 if (!view.isInTouchMode()) {
167 return false;
168 }
169
Joe Onorato0589f0f2010-02-08 13:44:00 -0800170 ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800171
Joe Onorato00acb122009-08-04 16:04:30 -0400172 mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800173 mLauncher.closeFolder(this);
174 mDragItem = app;
175
176 return true;
177 }
178
Joe Onorato00acb122009-08-04 16:04:30 -0400179 public void setDragController(DragController dragController) {
180 mDragController = dragController;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800181 }
182
Patrick Dubroya669d792010-11-23 14:40:33 -0800183 public void onDragViewVisible() {
184 }
185
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800186 void setLauncher(Launcher launcher) {
187 mLauncher = launcher;
188 }
Adam Cohen2801caf2011-05-13 20:57:39 -0700189
190 void setFolderIcon(FolderIcon icon) {
191 mFolderIcon = icon;
192 }
193
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800194 /**
195 * @return the FolderInfo object associated with this folder
196 */
197 FolderInfo getInfo() {
198 return mInfo;
199 }
200
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800201 void onOpen() {
Adam Cohendf2cc412011-04-27 16:56:57 -0700202 // When the folder opens, we need to refresh the GridView's selection by
203 // forcing a layout
204 // TODO: find out if this is still necessary
205 mContent.requestLayout();
206 requestFocus();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800207 }
208
209 void onClose() {
210 final Workspace workspace = mLauncher.getWorkspace();
Michael Jurka0142d492010-08-25 17:46:15 -0700211 workspace.getChildAt(workspace.getCurrentPage()).requestFocus();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800212 }
213
214 void bind(FolderInfo info) {
215 mInfo = info;
Adam Cohendf2cc412011-04-27 16:56:57 -0700216 ArrayList<ShortcutInfo> children = info.contents;
Adam Cohen7c693212011-05-18 15:26:57 -0700217 setupContentForNumItems(children.size());
Adam Cohendf2cc412011-04-27 16:56:57 -0700218 for (int i = 0; i < children.size(); i++) {
219 ShortcutInfo child = (ShortcutInfo) children.get(i);
Adam Cohen7c693212011-05-18 15:26:57 -0700220 createAndAddShortcut(child);
Adam Cohendf2cc412011-04-27 16:56:57 -0700221 }
Adam Cohen4dbe6d92011-05-18 17:14:15 -0700222 mItemsInvalidated = true;
Adam Cohena9cf38f2011-05-02 15:36:58 -0700223 mInfo.addListener(this);
Adam Cohendf2cc412011-04-27 16:56:57 -0700224 }
225
226 /**
227 * Creates a new UserFolder, inflated from R.layout.user_folder.
228 *
229 * @param context The application's context.
230 *
231 * @return A new UserFolder.
232 */
233 static Folder fromXml(Context context) {
234 return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
235 }
236
237 /**
238 * This method is intended to make the UserFolder to be visually identical in size and position
239 * to its associated FolderIcon. This allows for a seamless transition into the expanded state.
240 */
241 private void positionAndSizeAsIcon() {
242 if (!(getParent() instanceof CellLayoutChildren)) return;
243
Adam Cohen2801caf2011-05-13 20:57:39 -0700244 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
Adam Cohendf2cc412011-04-27 16:56:57 -0700245 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
246
Adam Cohen2801caf2011-05-13 20:57:39 -0700247 if (mMode == PARTIAL_GROW) {
248 setScaleX(0.8f);
249 setScaleY(0.8f);
250 setAlpha(0f);
251 } else {
252 lp.width = iconLp.width;
253 lp.height = iconLp.height;
254 lp.x = iconLp.x;
255 lp.y = iconLp.y;
256 mContent.setAlpha(0);
257 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700258 mState = STATE_SMALL;
259 }
260
261 public void animateOpen() {
262 if (mState != STATE_SMALL) {
263 positionAndSizeAsIcon();
264 }
265 if (!(getParent() instanceof CellLayoutChildren)) return;
266
Adam Cohen2801caf2011-05-13 20:57:39 -0700267 ObjectAnimator oa;
Adam Cohendf2cc412011-04-27 16:56:57 -0700268 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
269
Adam Cohen2801caf2011-05-13 20:57:39 -0700270 centerAboutIcon();
271 if (mMode == PARTIAL_GROW) {
272 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
273 PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
274 PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
275 oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
276 } else {
277 PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", mNewSize.width());
278 PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", mNewSize.height());
279 PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", mNewSize.left);
280 PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", mNewSize.top);
281 oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
282 oa.addUpdateListener(new AnimatorUpdateListener() {
283 public void onAnimationUpdate(ValueAnimator animation) {
284 requestLayout();
285 }
286 });
Adam Cohendf2cc412011-04-27 16:56:57 -0700287
Adam Cohen2801caf2011-05-13 20:57:39 -0700288 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
289 ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
290 alphaOa.setDuration(mExpandDuration);
291 alphaOa.setInterpolator(new AccelerateInterpolator(2.0f));
292 alphaOa.start();
293 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700294
Adam Cohen2801caf2011-05-13 20:57:39 -0700295 oa.addListener(new AnimatorListenerAdapter() {
Adam Cohendf2cc412011-04-27 16:56:57 -0700296 @Override
297 public void onAnimationStart(Animator animation) {
298 mState = STATE_ANIMATING;
299 }
300 @Override
301 public void onAnimationEnd(Animator animation) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700302 mState = STATE_OPEN;
Adam Cohendf2cc412011-04-27 16:56:57 -0700303 }
304 });
Adam Cohen2801caf2011-05-13 20:57:39 -0700305 oa.setDuration(mExpandDuration);
306 oa.start();
Adam Cohendf2cc412011-04-27 16:56:57 -0700307 }
308
309 public void animateClosed() {
310 if (!(getParent() instanceof CellLayoutChildren)) return;
311
312 CellLayoutChildren clc = (CellLayoutChildren) getParent();
313 final CellLayout cellLayout = (CellLayout) clc.getParent();
Adam Cohen2801caf2011-05-13 20:57:39 -0700314 ObjectAnimator oa;
Adam Cohendf2cc412011-04-27 16:56:57 -0700315
Adam Cohen2801caf2011-05-13 20:57:39 -0700316 if (mMode == PARTIAL_GROW) {
317 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
318 PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
319 PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
320 oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
321 } else {
322 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
323 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
Adam Cohendf2cc412011-04-27 16:56:57 -0700324
Adam Cohen2801caf2011-05-13 20:57:39 -0700325 PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", iconLp.width);
326 PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", iconLp.height);
327 PropertyValuesHolder x = PropertyValuesHolder.ofInt("x",iconLp.x);
328 PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", iconLp.y);
329 oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
330 oa.addUpdateListener(new AnimatorUpdateListener() {
331 public void onAnimationUpdate(ValueAnimator animation) {
332 requestLayout();
333 }
334 });
Adam Cohendf2cc412011-04-27 16:56:57 -0700335
Adam Cohen2801caf2011-05-13 20:57:39 -0700336 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
337 ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
338 alphaOa.setDuration(mExpandDuration);
339 alphaOa.setInterpolator(new DecelerateInterpolator(2.0f));
340 alphaOa.start();
341 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700342
Adam Cohen2801caf2011-05-13 20:57:39 -0700343 oa.addListener(new AnimatorListenerAdapter() {
Adam Cohendf2cc412011-04-27 16:56:57 -0700344 @Override
345 public void onAnimationEnd(Animator animation) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700346 onCloseComplete();
Adam Cohendf2cc412011-04-27 16:56:57 -0700347 cellLayout.removeViewWithoutMarkingCells(Folder.this);
Adam Cohen2801caf2011-05-13 20:57:39 -0700348 mState = STATE_SMALL;
Adam Cohendf2cc412011-04-27 16:56:57 -0700349 }
350 @Override
351 public void onAnimationStart(Animator animation) {
352 mState = STATE_ANIMATING;
353 }
354 });
Adam Cohen2801caf2011-05-13 20:57:39 -0700355 oa.setDuration(mExpandDuration);
356 oa.start();
Adam Cohendf2cc412011-04-27 16:56:57 -0700357 }
358
359 void notifyDataSetChanged() {
360 // recreate all the children if the data set changes under us. We may want to do this more
361 // intelligently (ie just removing the views that should no longer exist)
362 mContent.removeAllViewsInLayout();
363 bind(mInfo);
364 }
365
366 public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
367 DragView dragView, Object dragInfo) {
368 final ItemInfo item = (ItemInfo) dragInfo;
369 final int itemType = item.itemType;
Adam Cohen2801caf2011-05-13 20:57:39 -0700370 return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
371 itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
372 !isFull());
Adam Cohendf2cc412011-04-27 16:56:57 -0700373 }
374
375 public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
376 DragView dragView, Object dragInfo) {
377 ShortcutInfo item;
378 if (dragInfo instanceof ApplicationInfo) {
379 // Came from all apps -- make a copy
380 item = ((ApplicationInfo)dragInfo).makeShortcut();
381 item.spanX = 1;
382 item.spanY = 1;
383 } else {
384 item = (ShortcutInfo)dragInfo;
385 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700386 mInfo.add(item);
Adam Cohendf2cc412011-04-27 16:56:57 -0700387 LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
388 }
389
390 protected boolean findAndSetEmptyCells(ShortcutInfo item) {
391 int[] emptyCell = new int[2];
392 if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
393 item.cellX = emptyCell[0];
394 item.cellY = emptyCell[1];
395 LauncherModel.addOrMoveItemInDatabase(
396 mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
397 return true;
398 } else {
399 return false;
400 }
401 }
402
403 protected void createAndAddShortcut(ShortcutInfo item) {
404 final TextView textView =
405 (TextView) mInflater.inflate(R.layout.application_boxed, this, false);
406 textView.setCompoundDrawablesWithIntrinsicBounds(null,
407 new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
408 textView.setText(item.title);
409 textView.setTag(item);
410
411 textView.setOnClickListener(this);
412 textView.setOnLongClickListener(this);
413
414 CellLayout.LayoutParams lp =
415 new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
416 boolean insert = false;
417 mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
418 }
419
420 public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
421 DragView dragView, Object dragInfo) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700422 mContent.onDragEnter();
Adam Cohendf2cc412011-04-27 16:56:57 -0700423 }
424
425 public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
426 DragView dragView, Object dragInfo) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700427 float[] r = mapPointFromScreenToContent(x, y, null);
428 mContent.visualizeDropLocation(null, null, (int) r[0], (int) r[1], 1, 1);
Adam Cohendf2cc412011-04-27 16:56:57 -0700429 }
430
431 public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
432 DragView dragView, Object dragInfo) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700433 mContent.onDragExit();
434 }
435
436 public float[] mapPointFromScreenToContent(int x, int y, float[] r) {
437 if (r == null) {
438 r = new float[2];
439 }
440
441 int[] screenLocation = new int[2];
442 mContent.getLocationOnScreen(screenLocation);
443
444 r[0] = x - screenLocation[0];
445 r[1] = y - screenLocation[1];
446 return r;
Adam Cohendf2cc412011-04-27 16:56:57 -0700447 }
448
449 public void onDropCompleted(View target, Object dragInfo, boolean success) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700450 }
451
452 public boolean isDropEnabled() {
453 return true;
454 }
455
456 public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
457 DragView dragView, Object dragInfo) {
458 return null;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800459 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700460
Adam Cohen2801caf2011-05-13 20:57:39 -0700461 private void setupContentDimension(int count) {
462 ArrayList<View> list = getItemsInReadingOrder();
463
464 int countX = mContent.getCountX();
465 int countY = mContent.getCountY();
Adam Cohen7c693212011-05-18 15:26:57 -0700466 boolean done = false;
Adam Cohen2801caf2011-05-13 20:57:39 -0700467
Adam Cohen7c693212011-05-18 15:26:57 -0700468 while (!done) {
469 int oldCountX = countX;
470 int oldCountY = countY;
471 if (countX * countY < count) {
472 // Current grid is too small, expand it
473 if (countX <= countY && countX < mMaxCountX) {
474 countX++;
475 } else if (countY < mMaxCountY) {
476 countY++;
477 }
478 if (countY == 0) countY++;
479 } else if ((countY - 1) * countX >= count && countY >= countX) {
480 countY = Math.max(0, countY - 1);
481 } else if ((countX - 1) * countY >= count) {
482 countX = Math.max(0, countX - 1);
Adam Cohen2801caf2011-05-13 20:57:39 -0700483 }
Adam Cohen7c693212011-05-18 15:26:57 -0700484 done = countX == oldCountX && countY == oldCountY;
Adam Cohen2801caf2011-05-13 20:57:39 -0700485 }
Adam Cohen7c693212011-05-18 15:26:57 -0700486 mContent.setGridSize(countX, countY);
Adam Cohen2801caf2011-05-13 20:57:39 -0700487 arrangeChildren(list);
488 }
489
490 public boolean isFull() {
491 return getItemCount() >= mMaxCountX * mMaxCountY;
492 }
493
494 private void centerAboutIcon() {
495 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
496 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
497
498 int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
499 int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight();
500
501 int centerX = iconLp.x + iconLp.width / 2;
502 int centerY = iconLp.y + iconLp.height / 2;
503 int centeredLeft = centerX - width / 2;
504 int centeredTop = centerY - height / 2;
505
506 CellLayoutChildren clc = (CellLayoutChildren) getParent();
507 int parentWidth = 0;
508 int parentHeight = 0;
509 if (clc != null) {
510 parentWidth = clc.getMeasuredWidth();
511 parentHeight = clc.getMeasuredHeight();
512 }
513
514 int left = Math.min(Math.max(0, centeredLeft), parentWidth - width);
515 int top = Math.min(Math.max(0, centeredTop), parentHeight - height);
516
517 int folderPivotX = width / 2 + (centeredLeft - left);
518 int folderPivotY = height / 2 + (centeredTop - top);
519 setPivotX(folderPivotX);
520 setPivotY(folderPivotY);
521 int folderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
522 (1.0f * folderPivotX / width));
523 int folderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
524 (1.0f * folderPivotY / height));
525 mFolderIcon.setPivotX(folderIconPivotX);
526 mFolderIcon.setPivotY(folderIconPivotY);
527
528 if (mMode == PARTIAL_GROW) {
529 lp.width = width;
530 lp.height = height;
531 lp.x = left;
532 lp.y = top;
533 } else {
534 mNewSize.set(left, top, left + width, top + height);
535 }
536 }
537
538 private void setupContentForNumItems(int count) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700539 setupContentDimension(count);
540
541 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
542 if (lp == null) {
543 lp = new CellLayout.LayoutParams(0, 0, -1, -1);
544 lp.isLockedToGrid = false;
545 setLayoutParams(lp);
546 }
547 centerAboutIcon();
548 }
549
550 private void arrangeChildren(ArrayList<View> list) {
551 int[] vacant = new int[2];
552 if (list == null) {
553 list = getItemsInReadingOrder();
554 }
555 mContent.removeAllViews();
556
557 for (int i = 0; i < list.size(); i++) {
558 View v = list.get(i);
559 mContent.getVacantCell(vacant, 1, 1);
560 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
561 lp.cellX = vacant[0];
562 lp.cellY = vacant[1];
563 ItemInfo info = (ItemInfo) v.getTag();
564 info.cellX = vacant[0];
565 info.cellY = vacant[1];
566 boolean insert = false;
567 mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true);
Adam Cohen7c693212011-05-18 15:26:57 -0700568 LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0,
569 info.cellX, info.cellY);
Adam Cohen2801caf2011-05-13 20:57:39 -0700570 }
Adam Cohen7c693212011-05-18 15:26:57 -0700571 mItemsInvalidated = true;
Adam Cohen2801caf2011-05-13 20:57:39 -0700572 }
573
Adam Cohena9cf38f2011-05-02 15:36:58 -0700574 public void onAdd(ShortcutInfo item) {
Adam Cohen7c693212011-05-18 15:26:57 -0700575 mItemsInvalidated = true;
Adam Cohen2801caf2011-05-13 20:57:39 -0700576 if (!findAndSetEmptyCells(item)) {
577 // The current layout is full, can we expand it?
578 setupContentForNumItems(getItemCount() + 1);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700579 findAndSetEmptyCells(item);
580 }
581 createAndAddShortcut(item);
582 }
583
584 public int getItemCount() {
585 return mContent.getChildrenLayout().getChildCount();
586 }
587
588 public View getItemAt(int index) {
589 return mContent.getChildrenLayout().getChildAt(index);
590 }
591
Adam Cohen2801caf2011-05-13 20:57:39 -0700592 private void onCloseComplete() {
593 if (mRearrangeOnClose) {
594 setupContentForNumItems(getItemCount());
595 mRearrangeOnClose = false;
596 }
597 }
598
Adam Cohena9cf38f2011-05-02 15:36:58 -0700599 public void onRemove(ShortcutInfo item) {
Adam Cohen7c693212011-05-18 15:26:57 -0700600 mItemsInvalidated = true;
Adam Cohena9cf38f2011-05-02 15:36:58 -0700601 View v = mContent.getChildAt(mDragItemPosition[0], mDragItemPosition[1]);
602 mContent.removeView(v);
Adam Cohen2801caf2011-05-13 20:57:39 -0700603 if (mState == STATE_ANIMATING) {
604 mRearrangeOnClose = true;
605 } else {
606 setupContentForNumItems(getItemCount());
607 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700608 }
Adam Cohen7c693212011-05-18 15:26:57 -0700609
610 public ArrayList<View> getItemsInReadingOrder() {
611 if (mItemsInvalidated) {
612 mItemsInReadingOrder.clear();
613 for (int j = 0; j < mContent.getCountY(); j++) {
614 for (int i = 0; i < mContent.getCountX(); i++) {
615 View v = mContent.getChildAt(i, j);
616 if (v != null) {
617 mItemsInReadingOrder.add(v);
618 }
619 }
620 }
621 mItemsInvalidated = false;
622 }
623 return mItemsInReadingOrder;
624 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800625}