blob: a4aeec40717dc29e6f3e6c601c34f58e634266de [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;
Adam Cohen2801caf2011-05-13 20:57:39 -070028import android.graphics.Matrix;
Romain Guyfb5411e2010-02-24 10:04:17 -080029import android.graphics.Rect;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080030import android.util.AttributeSet;
Adam Cohendf2cc412011-04-27 16:56:57 -070031import android.view.LayoutInflater;
Adam Cohen0c872ba2011-05-05 10:34:16 -070032import android.view.MotionEvent;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080033import android.view.View;
34import android.view.View.OnClickListener;
Adam Cohen2801caf2011-05-13 20:57:39 -070035import android.view.animation.AccelerateInterpolator;
36import android.view.animation.DecelerateInterpolator;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080037import android.widget.AdapterView;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080038import android.widget.LinearLayout;
Adam Cohendf2cc412011-04-27 16:56:57 -070039import android.widget.TextView;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080040import android.widget.AdapterView.OnItemClickListener;
41import android.widget.AdapterView.OnItemLongClickListener;
42
Romain Guyedcce092010-03-04 13:03:17 -080043import com.android.launcher.R;
Adam Cohena9cf38f2011-05-02 15:36:58 -070044import com.android.launcher2.FolderInfo.FolderListener;
Romain Guyedcce092010-03-04 13:03:17 -080045
The Android Open Source Project31dd5032009-03-03 19:32:27 -080046/**
47 * Represents a set of icons chosen by the user or generated by the system.
48 */
49public class Folder extends LinearLayout implements DragSource, OnItemLongClickListener,
Adam Cohena9cf38f2011-05-02 15:36:58 -070050 OnItemClickListener, OnClickListener, View.OnLongClickListener, DropTarget, FolderListener {
The Android Open Source Project31dd5032009-03-03 19:32:27 -080051
Joe Onorato00acb122009-08-04 16:04:30 -040052 protected DragController mDragController;
Adam Cohendf2cc412011-04-27 16:56:57 -070053
The Android Open Source Project31dd5032009-03-03 19:32:27 -080054 protected Launcher mLauncher;
55
The Android Open Source Project31dd5032009-03-03 19:32:27 -080056 protected FolderInfo mInfo;
57
58 /**
59 * Which item is being dragged
60 */
Joe Onorato0589f0f2010-02-08 13:44:00 -080061 protected ShortcutInfo mDragItem;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080062
Adam Cohendf2cc412011-04-27 16:56:57 -070063 private static final String TAG = "Launcher.Folder";
64
65 static final int STATE_NONE = -1;
66 static final int STATE_SMALL = 0;
67 static final int STATE_ANIMATING = 1;
68 static final int STATE_OPEN = 2;
69
70 private int mExpandDuration;
71 protected CellLayout mContent;
72 private final LayoutInflater mInflater;
73 private final IconCache mIconCache;
74 private int mState = STATE_NONE;
Adam Cohena9cf38f2011-05-02 15:36:58 -070075 private int[] mDragItemPosition = new int[2];
Adam Cohen2801caf2011-05-13 20:57:39 -070076 private static final int FULL_GROW = 0;
77 private static final int PARTIAL_GROW = 1;
78 private int mMode = PARTIAL_GROW;
79 private boolean mRearrangeOnClose = false;
80 private FolderIcon mFolderIcon;
81 private int mMaxCountX;
82 private int mMaxCountY;
83 private Rect mNewSize = new Rect();
Adam Cohendf2cc412011-04-27 16:56:57 -070084
The Android Open Source Project31dd5032009-03-03 19:32:27 -080085 /**
86 * Used to inflate the Workspace from XML.
87 *
88 * @param context The application's context.
89 * @param attrs The attribtues set containing the Workspace's customization values.
90 */
91 public Folder(Context context, AttributeSet attrs) {
92 super(context, attrs);
93 setAlwaysDrawnWithCacheEnabled(false);
Adam Cohendf2cc412011-04-27 16:56:57 -070094 mInflater = LayoutInflater.from(context);
95 mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
96 mExpandDuration = getResources().getInteger(R.integer.config_folderAnimDuration);
Adam Cohen2801caf2011-05-13 20:57:39 -070097
98 mMaxCountX = LauncherModel.getCellCountX() - 1;
99 mMaxCountY = LauncherModel.getCellCountY() - 1;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800100 }
101
102 @Override
103 protected void onFinishInflate() {
104 super.onFinishInflate();
Adam Cohendf2cc412011-04-27 16:56:57 -0700105 mContent = (CellLayout) findViewById(R.id.folder_content);
Adam Cohen2801caf2011-05-13 20:57:39 -0700106 mContent.setGridSize(0, 0);
107 mContent.enableHardwareLayers();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800108 }
Adam Cohen2801caf2011-05-13 20:57:39 -0700109
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800110 public void onItemClick(AdapterView parent, View v, int position, long id) {
Joe Onorato0589f0f2010-02-08 13:44:00 -0800111 ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
Romain Guyfb5411e2010-02-24 10:04:17 -0800112 int[] pos = new int[2];
113 v.getLocationOnScreen(pos);
114 app.intent.setSourceBounds(new Rect(pos[0], pos[1],
115 pos[0] + v.getWidth(), pos[1] + v.getHeight()));
Joe Onoratof984e852010-03-25 09:47:45 -0700116 mLauncher.startActivitySafely(app.intent, app);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800117 }
118
119 public void onClick(View v) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700120 Object tag = v.getTag();
121 if (tag instanceof ShortcutInfo) {
122 // refactor this code from Folder
123 ShortcutInfo item = (ShortcutInfo) tag;
124 int[] pos = new int[2];
125 v.getLocationOnScreen(pos);
126 item.intent.setSourceBounds(new Rect(pos[0], pos[1],
127 pos[0] + v.getWidth(), pos[1] + v.getHeight()));
128 mLauncher.startActivitySafely(item.intent, item);
Adam Cohendf2cc412011-04-27 16:56:57 -0700129 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800130 }
131
132 public boolean onLongClick(View v) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700133 Object tag = v.getTag();
134 if (tag instanceof ShortcutInfo) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700135 mLauncher.closeFolder(this);
136
Adam Cohendf2cc412011-04-27 16:56:57 -0700137 ShortcutInfo item = (ShortcutInfo) tag;
138 if (!v.isInTouchMode()) {
139 return false;
140 }
141
142 mLauncher.getWorkspace().onDragStartedWithItem(v);
143 mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700144 mDragItemPosition[0] = item.cellX;
145 mDragItemPosition[1] = item.cellY;
Adam Cohen2801caf2011-05-13 20:57:39 -0700146 mInfo.remove(item);
147
Adam Cohendf2cc412011-04-27 16:56:57 -0700148 mDragItem = item;
149 } else {
150 mLauncher.closeFolder(this);
151 mLauncher.showRenameDialog(mInfo);
152 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800153 return true;
154 }
155
Adam Cohen0c872ba2011-05-05 10:34:16 -0700156 /**
157 * We need to handle touch events to prevent them from falling through to the workspace below.
158 */
159 @Override
160 public boolean onTouchEvent(MotionEvent ev) {
161 return true;
162 }
163
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800164 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
165 if (!view.isInTouchMode()) {
166 return false;
167 }
168
Joe Onorato0589f0f2010-02-08 13:44:00 -0800169 ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800170
Joe Onorato00acb122009-08-04 16:04:30 -0400171 mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800172 mLauncher.closeFolder(this);
173 mDragItem = app;
174
175 return true;
176 }
177
Joe Onorato00acb122009-08-04 16:04:30 -0400178 public void setDragController(DragController dragController) {
179 mDragController = dragController;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800180 }
181
Patrick Dubroya669d792010-11-23 14:40:33 -0800182 public void onDragViewVisible() {
183 }
184
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800185 void setLauncher(Launcher launcher) {
186 mLauncher = launcher;
187 }
Adam Cohen2801caf2011-05-13 20:57:39 -0700188
189 void setFolderIcon(FolderIcon icon) {
190 mFolderIcon = icon;
191 }
192
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800193 /**
194 * @return the FolderInfo object associated with this folder
195 */
196 FolderInfo getInfo() {
197 return mInfo;
198 }
199
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800200 void onOpen() {
Adam Cohendf2cc412011-04-27 16:56:57 -0700201 // When the folder opens, we need to refresh the GridView's selection by
202 // forcing a layout
203 // TODO: find out if this is still necessary
204 mContent.requestLayout();
205 requestFocus();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800206 }
207
208 void onClose() {
209 final Workspace workspace = mLauncher.getWorkspace();
Michael Jurka0142d492010-08-25 17:46:15 -0700210 workspace.getChildAt(workspace.getCurrentPage()).requestFocus();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800211 }
212
213 void bind(FolderInfo info) {
214 mInfo = info;
Adam Cohendf2cc412011-04-27 16:56:57 -0700215 ArrayList<ShortcutInfo> children = info.contents;
216 for (int i = 0; i < children.size(); i++) {
217 ShortcutInfo child = (ShortcutInfo) children.get(i);
Adam Cohen2801caf2011-05-13 20:57:39 -0700218 onAdd(child);
Adam Cohendf2cc412011-04-27 16:56:57 -0700219 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700220 mInfo.addListener(this);
Adam Cohendf2cc412011-04-27 16:56:57 -0700221 }
222
223 /**
224 * Creates a new UserFolder, inflated from R.layout.user_folder.
225 *
226 * @param context The application's context.
227 *
228 * @return A new UserFolder.
229 */
230 static Folder fromXml(Context context) {
231 return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
232 }
233
234 /**
235 * This method is intended to make the UserFolder to be visually identical in size and position
236 * to its associated FolderIcon. This allows for a seamless transition into the expanded state.
237 */
238 private void positionAndSizeAsIcon() {
239 if (!(getParent() instanceof CellLayoutChildren)) return;
240
Adam Cohen2801caf2011-05-13 20:57:39 -0700241 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
Adam Cohendf2cc412011-04-27 16:56:57 -0700242 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
243
Adam Cohen2801caf2011-05-13 20:57:39 -0700244 if (mMode == PARTIAL_GROW) {
245 setScaleX(0.8f);
246 setScaleY(0.8f);
247 setAlpha(0f);
248 } else {
249 lp.width = iconLp.width;
250 lp.height = iconLp.height;
251 lp.x = iconLp.x;
252 lp.y = iconLp.y;
253 mContent.setAlpha(0);
254 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700255 mState = STATE_SMALL;
256 }
257
258 public void animateOpen() {
259 if (mState != STATE_SMALL) {
260 positionAndSizeAsIcon();
261 }
262 if (!(getParent() instanceof CellLayoutChildren)) return;
263
Adam Cohen2801caf2011-05-13 20:57:39 -0700264 ObjectAnimator oa;
Adam Cohendf2cc412011-04-27 16:56:57 -0700265 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
266
Adam Cohen2801caf2011-05-13 20:57:39 -0700267 centerAboutIcon();
268 if (mMode == PARTIAL_GROW) {
269 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
270 PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
271 PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
272 oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
273 } else {
274 PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", mNewSize.width());
275 PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", mNewSize.height());
276 PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", mNewSize.left);
277 PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", mNewSize.top);
278 oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
279 oa.addUpdateListener(new AnimatorUpdateListener() {
280 public void onAnimationUpdate(ValueAnimator animation) {
281 requestLayout();
282 }
283 });
Adam Cohendf2cc412011-04-27 16:56:57 -0700284
Adam Cohen2801caf2011-05-13 20:57:39 -0700285 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
286 ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
287 alphaOa.setDuration(mExpandDuration);
288 alphaOa.setInterpolator(new AccelerateInterpolator(2.0f));
289 alphaOa.start();
290 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700291
Adam Cohen2801caf2011-05-13 20:57:39 -0700292 oa.addListener(new AnimatorListenerAdapter() {
Adam Cohendf2cc412011-04-27 16:56:57 -0700293 @Override
294 public void onAnimationStart(Animator animation) {
295 mState = STATE_ANIMATING;
296 }
297 @Override
298 public void onAnimationEnd(Animator animation) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700299 mState = STATE_OPEN;
Adam Cohendf2cc412011-04-27 16:56:57 -0700300 }
301 });
Adam Cohen2801caf2011-05-13 20:57:39 -0700302 oa.setDuration(mExpandDuration);
303 oa.start();
Adam Cohendf2cc412011-04-27 16:56:57 -0700304 }
305
306 public void animateClosed() {
307 if (!(getParent() instanceof CellLayoutChildren)) return;
308
309 CellLayoutChildren clc = (CellLayoutChildren) getParent();
310 final CellLayout cellLayout = (CellLayout) clc.getParent();
Adam Cohen2801caf2011-05-13 20:57:39 -0700311 ObjectAnimator oa;
Adam Cohendf2cc412011-04-27 16:56:57 -0700312
Adam Cohen2801caf2011-05-13 20:57:39 -0700313 if (mMode == PARTIAL_GROW) {
314 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
315 PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
316 PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
317 oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
318 } else {
319 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
320 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
Adam Cohendf2cc412011-04-27 16:56:57 -0700321
Adam Cohen2801caf2011-05-13 20:57:39 -0700322 PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", iconLp.width);
323 PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", iconLp.height);
324 PropertyValuesHolder x = PropertyValuesHolder.ofInt("x",iconLp.x);
325 PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", iconLp.y);
326 oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
327 oa.addUpdateListener(new AnimatorUpdateListener() {
328 public void onAnimationUpdate(ValueAnimator animation) {
329 requestLayout();
330 }
331 });
Adam Cohendf2cc412011-04-27 16:56:57 -0700332
Adam Cohen2801caf2011-05-13 20:57:39 -0700333 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
334 ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
335 alphaOa.setDuration(mExpandDuration);
336 alphaOa.setInterpolator(new DecelerateInterpolator(2.0f));
337 alphaOa.start();
338 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700339
Adam Cohen2801caf2011-05-13 20:57:39 -0700340 oa.addListener(new AnimatorListenerAdapter() {
Adam Cohendf2cc412011-04-27 16:56:57 -0700341 @Override
342 public void onAnimationEnd(Animator animation) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700343 onCloseComplete();
Adam Cohendf2cc412011-04-27 16:56:57 -0700344 cellLayout.removeViewWithoutMarkingCells(Folder.this);
Adam Cohen2801caf2011-05-13 20:57:39 -0700345 mState = STATE_SMALL;
Adam Cohendf2cc412011-04-27 16:56:57 -0700346 }
347 @Override
348 public void onAnimationStart(Animator animation) {
349 mState = STATE_ANIMATING;
350 }
351 });
Adam Cohen2801caf2011-05-13 20:57:39 -0700352 oa.setDuration(mExpandDuration);
353 oa.start();
Adam Cohendf2cc412011-04-27 16:56:57 -0700354 }
355
356 void notifyDataSetChanged() {
357 // recreate all the children if the data set changes under us. We may want to do this more
358 // intelligently (ie just removing the views that should no longer exist)
359 mContent.removeAllViewsInLayout();
360 bind(mInfo);
361 }
362
363 public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
364 DragView dragView, Object dragInfo) {
365 final ItemInfo item = (ItemInfo) dragInfo;
366 final int itemType = item.itemType;
Adam Cohen2801caf2011-05-13 20:57:39 -0700367 return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
368 itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
369 !isFull());
Adam Cohendf2cc412011-04-27 16:56:57 -0700370 }
371
372 public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
373 DragView dragView, Object dragInfo) {
374 ShortcutInfo item;
375 if (dragInfo instanceof ApplicationInfo) {
376 // Came from all apps -- make a copy
377 item = ((ApplicationInfo)dragInfo).makeShortcut();
378 item.spanX = 1;
379 item.spanY = 1;
380 } else {
381 item = (ShortcutInfo)dragInfo;
382 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700383 mInfo.add(item);
Adam Cohendf2cc412011-04-27 16:56:57 -0700384 LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
385 }
386
387 protected boolean findAndSetEmptyCells(ShortcutInfo item) {
388 int[] emptyCell = new int[2];
389 if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
390 item.cellX = emptyCell[0];
391 item.cellY = emptyCell[1];
392 LauncherModel.addOrMoveItemInDatabase(
393 mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
394 return true;
395 } else {
396 return false;
397 }
398 }
399
400 protected void createAndAddShortcut(ShortcutInfo item) {
401 final TextView textView =
402 (TextView) mInflater.inflate(R.layout.application_boxed, this, false);
403 textView.setCompoundDrawablesWithIntrinsicBounds(null,
404 new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
405 textView.setText(item.title);
406 textView.setTag(item);
407
408 textView.setOnClickListener(this);
409 textView.setOnLongClickListener(this);
410
411 CellLayout.LayoutParams lp =
412 new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
413 boolean insert = false;
414 mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
415 }
416
417 public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
418 DragView dragView, Object dragInfo) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700419 mContent.onDragEnter();
Adam Cohendf2cc412011-04-27 16:56:57 -0700420 }
421
422 public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
423 DragView dragView, Object dragInfo) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700424 float[] r = mapPointFromScreenToContent(x, y, null);
425 mContent.visualizeDropLocation(null, null, (int) r[0], (int) r[1], 1, 1);
Adam Cohendf2cc412011-04-27 16:56:57 -0700426 }
427
428 public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
429 DragView dragView, Object dragInfo) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700430 mContent.onDragExit();
431 }
432
433 public float[] mapPointFromScreenToContent(int x, int y, float[] r) {
434 if (r == null) {
435 r = new float[2];
436 }
437
438 int[] screenLocation = new int[2];
439 mContent.getLocationOnScreen(screenLocation);
440
441 r[0] = x - screenLocation[0];
442 r[1] = y - screenLocation[1];
443 return r;
Adam Cohendf2cc412011-04-27 16:56:57 -0700444 }
445
446 public void onDropCompleted(View target, Object dragInfo, boolean success) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700447 }
448
449 public boolean isDropEnabled() {
450 return true;
451 }
452
453 public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
454 DragView dragView, Object dragInfo) {
455 return null;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800456 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700457
Adam Cohen2801caf2011-05-13 20:57:39 -0700458 private void setupContentDimension(int count) {
459 ArrayList<View> list = getItemsInReadingOrder();
460
461 int countX = mContent.getCountX();
462 int countY = mContent.getCountY();
463 if (countX * countY < count) {
464 // Current grid is too small, expand it
465 if (countX <= countY && countX < mMaxCountX) {
466 countX++;
467 } else if (countY < mMaxCountY) {
468 countY++;
469 }
470 if (countY == 0) countY++;
471
472 mContent.setGridSize(countX, countY);
473 } else if ((countX - 1) * countY >= count || (countY - 1) * countX >= count) {
474 // Current grid is too big, shrink it
475 if (countX <= countY) {
476 countY--;
477 } else {
478 countX--;
479 }
480 mContent.setGridSize(countX, countY);
481 }
482 arrangeChildren(list);
483 }
484
485 public boolean isFull() {
486 return getItemCount() >= mMaxCountX * mMaxCountY;
487 }
488
489 private void centerAboutIcon() {
490 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
491 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
492
493 int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
494 int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight();
495
496 int centerX = iconLp.x + iconLp.width / 2;
497 int centerY = iconLp.y + iconLp.height / 2;
498 int centeredLeft = centerX - width / 2;
499 int centeredTop = centerY - height / 2;
500
501 CellLayoutChildren clc = (CellLayoutChildren) getParent();
502 int parentWidth = 0;
503 int parentHeight = 0;
504 if (clc != null) {
505 parentWidth = clc.getMeasuredWidth();
506 parentHeight = clc.getMeasuredHeight();
507 }
508
509 int left = Math.min(Math.max(0, centeredLeft), parentWidth - width);
510 int top = Math.min(Math.max(0, centeredTop), parentHeight - height);
511
512 int folderPivotX = width / 2 + (centeredLeft - left);
513 int folderPivotY = height / 2 + (centeredTop - top);
514 setPivotX(folderPivotX);
515 setPivotY(folderPivotY);
516 int folderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
517 (1.0f * folderPivotX / width));
518 int folderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
519 (1.0f * folderPivotY / height));
520 mFolderIcon.setPivotX(folderIconPivotX);
521 mFolderIcon.setPivotY(folderIconPivotY);
522
523 if (mMode == PARTIAL_GROW) {
524 lp.width = width;
525 lp.height = height;
526 lp.x = left;
527 lp.y = top;
528 } else {
529 mNewSize.set(left, top, left + width, top + height);
530 }
531 }
532
533 private void setupContentForNumItems(int count) {
534
535 setupContentDimension(count);
536
537 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
538 if (lp == null) {
539 lp = new CellLayout.LayoutParams(0, 0, -1, -1);
540 lp.isLockedToGrid = false;
541 setLayoutParams(lp);
542 }
543 centerAboutIcon();
544 }
545
546 private void arrangeChildren(ArrayList<View> list) {
547 int[] vacant = new int[2];
548 if (list == null) {
549 list = getItemsInReadingOrder();
550 }
551 mContent.removeAllViews();
552
553 for (int i = 0; i < list.size(); i++) {
554 View v = list.get(i);
555 mContent.getVacantCell(vacant, 1, 1);
556 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
557 lp.cellX = vacant[0];
558 lp.cellY = vacant[1];
559 ItemInfo info = (ItemInfo) v.getTag();
560 info.cellX = vacant[0];
561 info.cellY = vacant[1];
562 boolean insert = false;
563 mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true);
564 }
565 }
566
Adam Cohena9cf38f2011-05-02 15:36:58 -0700567 public void onAdd(ShortcutInfo item) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700568 if (!findAndSetEmptyCells(item)) {
569 // The current layout is full, can we expand it?
570 setupContentForNumItems(getItemCount() + 1);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700571 findAndSetEmptyCells(item);
572 }
573 createAndAddShortcut(item);
574 }
575
576 public int getItemCount() {
577 return mContent.getChildrenLayout().getChildCount();
578 }
579
580 public View getItemAt(int index) {
581 return mContent.getChildrenLayout().getChildAt(index);
582 }
583
Adam Cohen2801caf2011-05-13 20:57:39 -0700584 private ArrayList<View> getItemsInReadingOrder() {
585 ArrayList<View> list = new ArrayList<View>();
586 for (int j = 0; j < mContent.getCountY(); j++) {
587 for (int i = 0; i < mContent.getCountX(); i++) {
588 View v = mContent.getChildAt(i, j);
589 if (v != null) {
590 list.add(v);
591 }
592 }
593 }
594 return list;
595 }
596
597 private void onCloseComplete() {
598 if (mRearrangeOnClose) {
599 setupContentForNumItems(getItemCount());
600 mRearrangeOnClose = false;
601 }
602 }
603
Adam Cohena9cf38f2011-05-02 15:36:58 -0700604 public void onRemove(ShortcutInfo item) {
605 View v = mContent.getChildAt(mDragItemPosition[0], mDragItemPosition[1]);
606 mContent.removeView(v);
Adam Cohen2801caf2011-05-13 20:57:39 -0700607 if (mState == STATE_ANIMATING) {
608 mRearrangeOnClose = true;
609 } else {
610 setupContentForNumItems(getItemCount());
611 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700612 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800613}