blob: 3411f27236751d539a4f4ac75f519a0c064693a0 [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 Cohena9cf38f2011-05-02 15:36:58 -0700222 mInfo.addListener(this);
Adam Cohendf2cc412011-04-27 16:56:57 -0700223 }
224
225 /**
226 * Creates a new UserFolder, inflated from R.layout.user_folder.
227 *
228 * @param context The application's context.
229 *
230 * @return A new UserFolder.
231 */
232 static Folder fromXml(Context context) {
233 return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
234 }
235
236 /**
237 * This method is intended to make the UserFolder to be visually identical in size and position
238 * to its associated FolderIcon. This allows for a seamless transition into the expanded state.
239 */
240 private void positionAndSizeAsIcon() {
241 if (!(getParent() instanceof CellLayoutChildren)) return;
242
Adam Cohen2801caf2011-05-13 20:57:39 -0700243 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
Adam Cohendf2cc412011-04-27 16:56:57 -0700244 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
245
Adam Cohen2801caf2011-05-13 20:57:39 -0700246 if (mMode == PARTIAL_GROW) {
247 setScaleX(0.8f);
248 setScaleY(0.8f);
249 setAlpha(0f);
250 } else {
251 lp.width = iconLp.width;
252 lp.height = iconLp.height;
253 lp.x = iconLp.x;
254 lp.y = iconLp.y;
255 mContent.setAlpha(0);
256 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700257 mState = STATE_SMALL;
258 }
259
260 public void animateOpen() {
261 if (mState != STATE_SMALL) {
262 positionAndSizeAsIcon();
263 }
264 if (!(getParent() instanceof CellLayoutChildren)) return;
265
Adam Cohen2801caf2011-05-13 20:57:39 -0700266 ObjectAnimator oa;
Adam Cohendf2cc412011-04-27 16:56:57 -0700267 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
268
Adam Cohen2801caf2011-05-13 20:57:39 -0700269 centerAboutIcon();
270 if (mMode == PARTIAL_GROW) {
271 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
272 PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
273 PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
274 oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
275 } else {
276 PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", mNewSize.width());
277 PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", mNewSize.height());
278 PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", mNewSize.left);
279 PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", mNewSize.top);
280 oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
281 oa.addUpdateListener(new AnimatorUpdateListener() {
282 public void onAnimationUpdate(ValueAnimator animation) {
283 requestLayout();
284 }
285 });
Adam Cohendf2cc412011-04-27 16:56:57 -0700286
Adam Cohen2801caf2011-05-13 20:57:39 -0700287 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
288 ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
289 alphaOa.setDuration(mExpandDuration);
290 alphaOa.setInterpolator(new AccelerateInterpolator(2.0f));
291 alphaOa.start();
292 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700293
Adam Cohen2801caf2011-05-13 20:57:39 -0700294 oa.addListener(new AnimatorListenerAdapter() {
Adam Cohendf2cc412011-04-27 16:56:57 -0700295 @Override
296 public void onAnimationStart(Animator animation) {
297 mState = STATE_ANIMATING;
298 }
299 @Override
300 public void onAnimationEnd(Animator animation) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700301 mState = STATE_OPEN;
Adam Cohendf2cc412011-04-27 16:56:57 -0700302 }
303 });
Adam Cohen2801caf2011-05-13 20:57:39 -0700304 oa.setDuration(mExpandDuration);
305 oa.start();
Adam Cohendf2cc412011-04-27 16:56:57 -0700306 }
307
308 public void animateClosed() {
309 if (!(getParent() instanceof CellLayoutChildren)) return;
310
311 CellLayoutChildren clc = (CellLayoutChildren) getParent();
312 final CellLayout cellLayout = (CellLayout) clc.getParent();
Adam Cohen2801caf2011-05-13 20:57:39 -0700313 ObjectAnimator oa;
Adam Cohendf2cc412011-04-27 16:56:57 -0700314
Adam Cohen2801caf2011-05-13 20:57:39 -0700315 if (mMode == PARTIAL_GROW) {
316 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
317 PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
318 PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
319 oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
320 } else {
321 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
322 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
Adam Cohendf2cc412011-04-27 16:56:57 -0700323
Adam Cohen2801caf2011-05-13 20:57:39 -0700324 PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", iconLp.width);
325 PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", iconLp.height);
326 PropertyValuesHolder x = PropertyValuesHolder.ofInt("x",iconLp.x);
327 PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", iconLp.y);
328 oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
329 oa.addUpdateListener(new AnimatorUpdateListener() {
330 public void onAnimationUpdate(ValueAnimator animation) {
331 requestLayout();
332 }
333 });
Adam Cohendf2cc412011-04-27 16:56:57 -0700334
Adam Cohen2801caf2011-05-13 20:57:39 -0700335 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
336 ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
337 alphaOa.setDuration(mExpandDuration);
338 alphaOa.setInterpolator(new DecelerateInterpolator(2.0f));
339 alphaOa.start();
340 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700341
Adam Cohen2801caf2011-05-13 20:57:39 -0700342 oa.addListener(new AnimatorListenerAdapter() {
Adam Cohendf2cc412011-04-27 16:56:57 -0700343 @Override
344 public void onAnimationEnd(Animator animation) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700345 onCloseComplete();
Adam Cohendf2cc412011-04-27 16:56:57 -0700346 cellLayout.removeViewWithoutMarkingCells(Folder.this);
Adam Cohen2801caf2011-05-13 20:57:39 -0700347 mState = STATE_SMALL;
Adam Cohendf2cc412011-04-27 16:56:57 -0700348 }
349 @Override
350 public void onAnimationStart(Animator animation) {
351 mState = STATE_ANIMATING;
352 }
353 });
Adam Cohen2801caf2011-05-13 20:57:39 -0700354 oa.setDuration(mExpandDuration);
355 oa.start();
Adam Cohendf2cc412011-04-27 16:56:57 -0700356 }
357
358 void notifyDataSetChanged() {
359 // recreate all the children if the data set changes under us. We may want to do this more
360 // intelligently (ie just removing the views that should no longer exist)
361 mContent.removeAllViewsInLayout();
362 bind(mInfo);
363 }
364
365 public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
366 DragView dragView, Object dragInfo) {
367 final ItemInfo item = (ItemInfo) dragInfo;
368 final int itemType = item.itemType;
Adam Cohen2801caf2011-05-13 20:57:39 -0700369 return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
370 itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
371 !isFull());
Adam Cohendf2cc412011-04-27 16:56:57 -0700372 }
373
374 public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
375 DragView dragView, Object dragInfo) {
376 ShortcutInfo item;
377 if (dragInfo instanceof ApplicationInfo) {
378 // Came from all apps -- make a copy
379 item = ((ApplicationInfo)dragInfo).makeShortcut();
380 item.spanX = 1;
381 item.spanY = 1;
382 } else {
383 item = (ShortcutInfo)dragInfo;
384 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700385 mInfo.add(item);
Adam Cohendf2cc412011-04-27 16:56:57 -0700386 LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
387 }
388
389 protected boolean findAndSetEmptyCells(ShortcutInfo item) {
390 int[] emptyCell = new int[2];
391 if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
392 item.cellX = emptyCell[0];
393 item.cellY = emptyCell[1];
394 LauncherModel.addOrMoveItemInDatabase(
395 mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
396 return true;
397 } else {
398 return false;
399 }
400 }
401
402 protected void createAndAddShortcut(ShortcutInfo item) {
403 final TextView textView =
404 (TextView) mInflater.inflate(R.layout.application_boxed, this, false);
405 textView.setCompoundDrawablesWithIntrinsicBounds(null,
406 new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
407 textView.setText(item.title);
408 textView.setTag(item);
409
410 textView.setOnClickListener(this);
411 textView.setOnLongClickListener(this);
412
413 CellLayout.LayoutParams lp =
414 new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
415 boolean insert = false;
416 mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
417 }
418
419 public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
420 DragView dragView, Object dragInfo) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700421 mContent.onDragEnter();
Adam Cohendf2cc412011-04-27 16:56:57 -0700422 }
423
424 public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
425 DragView dragView, Object dragInfo) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700426 float[] r = mapPointFromScreenToContent(x, y, null);
427 mContent.visualizeDropLocation(null, null, (int) r[0], (int) r[1], 1, 1);
Adam Cohendf2cc412011-04-27 16:56:57 -0700428 }
429
430 public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
431 DragView dragView, Object dragInfo) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700432 mContent.onDragExit();
433 }
434
435 public float[] mapPointFromScreenToContent(int x, int y, float[] r) {
436 if (r == null) {
437 r = new float[2];
438 }
439
440 int[] screenLocation = new int[2];
441 mContent.getLocationOnScreen(screenLocation);
442
443 r[0] = x - screenLocation[0];
444 r[1] = y - screenLocation[1];
445 return r;
Adam Cohendf2cc412011-04-27 16:56:57 -0700446 }
447
448 public void onDropCompleted(View target, Object dragInfo, boolean success) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700449 }
450
451 public boolean isDropEnabled() {
452 return true;
453 }
454
455 public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
456 DragView dragView, Object dragInfo) {
457 return null;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800458 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700459
Adam Cohen2801caf2011-05-13 20:57:39 -0700460 private void setupContentDimension(int count) {
461 ArrayList<View> list = getItemsInReadingOrder();
462
463 int countX = mContent.getCountX();
464 int countY = mContent.getCountY();
Adam Cohen7c693212011-05-18 15:26:57 -0700465 boolean done = false;
Adam Cohen2801caf2011-05-13 20:57:39 -0700466
Adam Cohen7c693212011-05-18 15:26:57 -0700467 while (!done) {
468 int oldCountX = countX;
469 int oldCountY = countY;
470 if (countX * countY < count) {
471 // Current grid is too small, expand it
472 if (countX <= countY && countX < mMaxCountX) {
473 countX++;
474 } else if (countY < mMaxCountY) {
475 countY++;
476 }
477 if (countY == 0) countY++;
478 } else if ((countY - 1) * countX >= count && countY >= countX) {
479 countY = Math.max(0, countY - 1);
480 } else if ((countX - 1) * countY >= count) {
481 countX = Math.max(0, countX - 1);
Adam Cohen2801caf2011-05-13 20:57:39 -0700482 }
Adam Cohen7c693212011-05-18 15:26:57 -0700483 done = countX == oldCountX && countY == oldCountY;
Adam Cohen2801caf2011-05-13 20:57:39 -0700484 }
Adam Cohen7c693212011-05-18 15:26:57 -0700485 mContent.setGridSize(countX, countY);
Adam Cohen2801caf2011-05-13 20:57:39 -0700486 arrangeChildren(list);
487 }
488
489 public boolean isFull() {
490 return getItemCount() >= mMaxCountX * mMaxCountY;
491 }
492
493 private void centerAboutIcon() {
494 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
495 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
496
497 int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
498 int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight();
499
500 int centerX = iconLp.x + iconLp.width / 2;
501 int centerY = iconLp.y + iconLp.height / 2;
502 int centeredLeft = centerX - width / 2;
503 int centeredTop = centerY - height / 2;
504
505 CellLayoutChildren clc = (CellLayoutChildren) getParent();
506 int parentWidth = 0;
507 int parentHeight = 0;
508 if (clc != null) {
509 parentWidth = clc.getMeasuredWidth();
510 parentHeight = clc.getMeasuredHeight();
511 }
512
513 int left = Math.min(Math.max(0, centeredLeft), parentWidth - width);
514 int top = Math.min(Math.max(0, centeredTop), parentHeight - height);
515
516 int folderPivotX = width / 2 + (centeredLeft - left);
517 int folderPivotY = height / 2 + (centeredTop - top);
518 setPivotX(folderPivotX);
519 setPivotY(folderPivotY);
520 int folderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
521 (1.0f * folderPivotX / width));
522 int folderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
523 (1.0f * folderPivotY / height));
524 mFolderIcon.setPivotX(folderIconPivotX);
525 mFolderIcon.setPivotY(folderIconPivotY);
526
527 if (mMode == PARTIAL_GROW) {
528 lp.width = width;
529 lp.height = height;
530 lp.x = left;
531 lp.y = top;
532 } else {
533 mNewSize.set(left, top, left + width, top + height);
534 }
535 }
536
537 private void setupContentForNumItems(int count) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700538 setupContentDimension(count);
539
540 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
541 if (lp == null) {
542 lp = new CellLayout.LayoutParams(0, 0, -1, -1);
543 lp.isLockedToGrid = false;
544 setLayoutParams(lp);
545 }
546 centerAboutIcon();
547 }
548
549 private void arrangeChildren(ArrayList<View> list) {
550 int[] vacant = new int[2];
551 if (list == null) {
552 list = getItemsInReadingOrder();
553 }
554 mContent.removeAllViews();
555
556 for (int i = 0; i < list.size(); i++) {
557 View v = list.get(i);
558 mContent.getVacantCell(vacant, 1, 1);
559 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
560 lp.cellX = vacant[0];
561 lp.cellY = vacant[1];
562 ItemInfo info = (ItemInfo) v.getTag();
563 info.cellX = vacant[0];
564 info.cellY = vacant[1];
565 boolean insert = false;
566 mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true);
Adam Cohen7c693212011-05-18 15:26:57 -0700567 LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0,
568 info.cellX, info.cellY);
Adam Cohen2801caf2011-05-13 20:57:39 -0700569 }
Adam Cohen7c693212011-05-18 15:26:57 -0700570 mItemsInvalidated = true;
Adam Cohen2801caf2011-05-13 20:57:39 -0700571 }
572
Adam Cohena9cf38f2011-05-02 15:36:58 -0700573 public void onAdd(ShortcutInfo item) {
Adam Cohen7c693212011-05-18 15:26:57 -0700574 mItemsInvalidated = true;
Adam Cohen2801caf2011-05-13 20:57:39 -0700575 if (!findAndSetEmptyCells(item)) {
576 // The current layout is full, can we expand it?
577 setupContentForNumItems(getItemCount() + 1);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700578 findAndSetEmptyCells(item);
579 }
580 createAndAddShortcut(item);
581 }
582
583 public int getItemCount() {
584 return mContent.getChildrenLayout().getChildCount();
585 }
586
587 public View getItemAt(int index) {
588 return mContent.getChildrenLayout().getChildAt(index);
589 }
590
Adam Cohen2801caf2011-05-13 20:57:39 -0700591 private void onCloseComplete() {
592 if (mRearrangeOnClose) {
593 setupContentForNumItems(getItemCount());
594 mRearrangeOnClose = false;
595 }
596 }
597
Adam Cohena9cf38f2011-05-02 15:36:58 -0700598 public void onRemove(ShortcutInfo item) {
Adam Cohen7c693212011-05-18 15:26:57 -0700599 mItemsInvalidated = true;
Adam Cohena9cf38f2011-05-02 15:36:58 -0700600 View v = mContent.getChildAt(mDragItemPosition[0], mDragItemPosition[1]);
601 mContent.removeView(v);
Adam Cohen2801caf2011-05-13 20:57:39 -0700602 if (mState == STATE_ANIMATING) {
603 mRearrangeOnClose = true;
604 } else {
605 setupContentForNumItems(getItemCount());
606 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700607 }
Adam Cohen7c693212011-05-18 15:26:57 -0700608
609 public ArrayList<View> getItemsInReadingOrder() {
610 if (mItemsInvalidated) {
611 mItemsInReadingOrder.clear();
612 for (int j = 0; j < mContent.getCountY(); j++) {
613 for (int i = 0; i < mContent.getCountX(); i++) {
614 View v = mContent.getChildAt(i, j);
615 if (v != null) {
616 mItemsInReadingOrder.add(v);
617 }
618 }
619 }
620 mItemsInvalidated = false;
621 }
622 return mItemsInReadingOrder;
623 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800624}