blob: 76e9b357f78b87b42cf841e2ec45d6e52230d2bf [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
Adam Cohencb3382b2011-05-24 14:07:08 -0700366 public boolean acceptDrop(DragObject d) {
367 final ItemInfo item = (ItemInfo) d.dragInfo;
Adam Cohendf2cc412011-04-27 16:56:57 -0700368 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
Adam Cohencb3382b2011-05-24 14:07:08 -0700374 public void onDrop(DragObject d) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700375 ShortcutInfo item;
Adam Cohencb3382b2011-05-24 14:07:08 -0700376 if (d.dragInfo instanceof ApplicationInfo) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700377 // Came from all apps -- make a copy
Adam Cohencb3382b2011-05-24 14:07:08 -0700378 item = ((ApplicationInfo) d.dragInfo).makeShortcut();
Adam Cohendf2cc412011-04-27 16:56:57 -0700379 item.spanX = 1;
380 item.spanY = 1;
381 } else {
Adam Cohencb3382b2011-05-24 14:07:08 -0700382 item = (ShortcutInfo) d.dragInfo;
Adam Cohendf2cc412011-04-27 16:56:57 -0700383 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700384 mInfo.add(item);
Adam Cohendf2cc412011-04-27 16:56:57 -0700385 LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
386 }
387
388 protected boolean findAndSetEmptyCells(ShortcutInfo item) {
389 int[] emptyCell = new int[2];
390 if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
391 item.cellX = emptyCell[0];
392 item.cellY = emptyCell[1];
393 LauncherModel.addOrMoveItemInDatabase(
394 mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
395 return true;
396 } else {
397 return false;
398 }
399 }
400
401 protected void createAndAddShortcut(ShortcutInfo item) {
402 final TextView textView =
403 (TextView) mInflater.inflate(R.layout.application_boxed, this, false);
404 textView.setCompoundDrawablesWithIntrinsicBounds(null,
405 new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
406 textView.setText(item.title);
407 textView.setTag(item);
408
409 textView.setOnClickListener(this);
410 textView.setOnLongClickListener(this);
411
412 CellLayout.LayoutParams lp =
413 new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
414 boolean insert = false;
415 mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
416 }
417
Adam Cohencb3382b2011-05-24 14:07:08 -0700418 public void onDragEnter(DragObject d) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700419 mContent.onDragEnter();
Adam Cohendf2cc412011-04-27 16:56:57 -0700420 }
421
Adam Cohencb3382b2011-05-24 14:07:08 -0700422 public void onDragOver(DragObject d) {
423 float[] r = mapPointFromScreenToContent(d.x, d.y, null);
Adam Cohen2801caf2011-05-13 20:57:39 -0700424 mContent.visualizeDropLocation(null, null, (int) r[0], (int) r[1], 1, 1);
Adam Cohendf2cc412011-04-27 16:56:57 -0700425 }
426
Adam Cohencb3382b2011-05-24 14:07:08 -0700427 public void onDragExit(DragObject d) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700428 mContent.onDragExit();
429 }
430
431 public float[] mapPointFromScreenToContent(int x, int y, float[] r) {
432 if (r == null) {
433 r = new float[2];
434 }
435
436 int[] screenLocation = new int[2];
437 mContent.getLocationOnScreen(screenLocation);
438
439 r[0] = x - screenLocation[0];
440 r[1] = y - screenLocation[1];
441 return r;
Adam Cohendf2cc412011-04-27 16:56:57 -0700442 }
443
444 public void onDropCompleted(View target, Object dragInfo, boolean success) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700445 }
446
447 public boolean isDropEnabled() {
448 return true;
449 }
450
Adam Cohencb3382b2011-05-24 14:07:08 -0700451 public DropTarget getDropTargetDelegate(DragObject d) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700452 return null;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800453 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700454
Adam Cohen2801caf2011-05-13 20:57:39 -0700455 private void setupContentDimension(int count) {
456 ArrayList<View> list = getItemsInReadingOrder();
457
458 int countX = mContent.getCountX();
459 int countY = mContent.getCountY();
Adam Cohen7c693212011-05-18 15:26:57 -0700460 boolean done = false;
Adam Cohen2801caf2011-05-13 20:57:39 -0700461
Adam Cohen7c693212011-05-18 15:26:57 -0700462 while (!done) {
463 int oldCountX = countX;
464 int oldCountY = countY;
465 if (countX * countY < count) {
466 // Current grid is too small, expand it
467 if (countX <= countY && countX < mMaxCountX) {
468 countX++;
469 } else if (countY < mMaxCountY) {
470 countY++;
471 }
472 if (countY == 0) countY++;
473 } else if ((countY - 1) * countX >= count && countY >= countX) {
474 countY = Math.max(0, countY - 1);
475 } else if ((countX - 1) * countY >= count) {
476 countX = Math.max(0, countX - 1);
Adam Cohen2801caf2011-05-13 20:57:39 -0700477 }
Adam Cohen7c693212011-05-18 15:26:57 -0700478 done = countX == oldCountX && countY == oldCountY;
Adam Cohen2801caf2011-05-13 20:57:39 -0700479 }
Adam Cohen7c693212011-05-18 15:26:57 -0700480 mContent.setGridSize(countX, countY);
Adam Cohen2801caf2011-05-13 20:57:39 -0700481 arrangeChildren(list);
482 }
483
484 public boolean isFull() {
485 return getItemCount() >= mMaxCountX * mMaxCountY;
486 }
487
488 private void centerAboutIcon() {
489 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
490 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
491
492 int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
493 int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight();
494
495 int centerX = iconLp.x + iconLp.width / 2;
496 int centerY = iconLp.y + iconLp.height / 2;
497 int centeredLeft = centerX - width / 2;
498 int centeredTop = centerY - height / 2;
499
500 CellLayoutChildren clc = (CellLayoutChildren) getParent();
501 int parentWidth = 0;
502 int parentHeight = 0;
503 if (clc != null) {
504 parentWidth = clc.getMeasuredWidth();
505 parentHeight = clc.getMeasuredHeight();
506 }
507
508 int left = Math.min(Math.max(0, centeredLeft), parentWidth - width);
509 int top = Math.min(Math.max(0, centeredTop), parentHeight - height);
510
511 int folderPivotX = width / 2 + (centeredLeft - left);
512 int folderPivotY = height / 2 + (centeredTop - top);
513 setPivotX(folderPivotX);
514 setPivotY(folderPivotY);
515 int folderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
516 (1.0f * folderPivotX / width));
517 int folderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
518 (1.0f * folderPivotY / height));
519 mFolderIcon.setPivotX(folderIconPivotX);
520 mFolderIcon.setPivotY(folderIconPivotY);
521
522 if (mMode == PARTIAL_GROW) {
523 lp.width = width;
524 lp.height = height;
525 lp.x = left;
526 lp.y = top;
527 } else {
528 mNewSize.set(left, top, left + width, top + height);
529 }
530 }
531
532 private void setupContentForNumItems(int count) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700533 setupContentDimension(count);
534
535 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
536 if (lp == null) {
537 lp = new CellLayout.LayoutParams(0, 0, -1, -1);
538 lp.isLockedToGrid = false;
539 setLayoutParams(lp);
540 }
541 centerAboutIcon();
542 }
543
544 private void arrangeChildren(ArrayList<View> list) {
545 int[] vacant = new int[2];
546 if (list == null) {
547 list = getItemsInReadingOrder();
548 }
549 mContent.removeAllViews();
550
551 for (int i = 0; i < list.size(); i++) {
552 View v = list.get(i);
553 mContent.getVacantCell(vacant, 1, 1);
554 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
555 lp.cellX = vacant[0];
556 lp.cellY = vacant[1];
557 ItemInfo info = (ItemInfo) v.getTag();
558 info.cellX = vacant[0];
559 info.cellY = vacant[1];
560 boolean insert = false;
561 mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true);
Adam Cohen7c693212011-05-18 15:26:57 -0700562 LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0,
563 info.cellX, info.cellY);
Adam Cohen2801caf2011-05-13 20:57:39 -0700564 }
Adam Cohen7c693212011-05-18 15:26:57 -0700565 mItemsInvalidated = true;
Adam Cohen2801caf2011-05-13 20:57:39 -0700566 }
567
Adam Cohena9cf38f2011-05-02 15:36:58 -0700568 public void onAdd(ShortcutInfo item) {
Adam Cohen7c693212011-05-18 15:26:57 -0700569 mItemsInvalidated = true;
Adam Cohen2801caf2011-05-13 20:57:39 -0700570 if (!findAndSetEmptyCells(item)) {
571 // The current layout is full, can we expand it?
572 setupContentForNumItems(getItemCount() + 1);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700573 findAndSetEmptyCells(item);
574 }
575 createAndAddShortcut(item);
576 }
577
578 public int getItemCount() {
579 return mContent.getChildrenLayout().getChildCount();
580 }
581
582 public View getItemAt(int index) {
583 return mContent.getChildrenLayout().getChildAt(index);
584 }
585
Adam Cohen2801caf2011-05-13 20:57:39 -0700586 private void onCloseComplete() {
587 if (mRearrangeOnClose) {
588 setupContentForNumItems(getItemCount());
589 mRearrangeOnClose = false;
590 }
591 }
592
Adam Cohena9cf38f2011-05-02 15:36:58 -0700593 public void onRemove(ShortcutInfo item) {
Adam Cohen7c693212011-05-18 15:26:57 -0700594 mItemsInvalidated = true;
Adam Cohena9cf38f2011-05-02 15:36:58 -0700595 View v = mContent.getChildAt(mDragItemPosition[0], mDragItemPosition[1]);
596 mContent.removeView(v);
Adam Cohen2801caf2011-05-13 20:57:39 -0700597 if (mState == STATE_ANIMATING) {
598 mRearrangeOnClose = true;
599 } else {
600 setupContentForNumItems(getItemCount());
601 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700602 }
Adam Cohen7c693212011-05-18 15:26:57 -0700603
604 public ArrayList<View> getItemsInReadingOrder() {
605 if (mItemsInvalidated) {
606 mItemsInReadingOrder.clear();
607 for (int j = 0; j < mContent.getCountY(); j++) {
608 for (int i = 0; i < mContent.getCountX(); i++) {
609 View v = mContent.getChildAt(i, j);
610 if (v != null) {
611 mItemsInReadingOrder.add(v);
612 }
613 }
614 }
615 mItemsInvalidated = false;
616 }
617 return mItemsInReadingOrder;
618 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800619}