blob: 0b35acbb1180c70e8e224221ec99540d075388aa [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;
Adam Cohenbadf71e2011-05-26 19:08:29 -070029import android.graphics.drawable.Drawable;
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 Cohen7c693212011-05-18 15:26:57 -070084 private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
Adam Cohenbadf71e2011-05-26 19:08:29 -070085 private Drawable mIconDrawable;
Adam Cohen7c693212011-05-18 15:26:57 -070086 boolean mItemsInvalidated = false;
Adam Cohendf2cc412011-04-27 16:56:57 -070087
The Android Open Source Project31dd5032009-03-03 19:32:27 -080088 /**
89 * Used to inflate the Workspace from XML.
90 *
91 * @param context The application's context.
92 * @param attrs The attribtues set containing the Workspace's customization values.
93 */
94 public Folder(Context context, AttributeSet attrs) {
95 super(context, attrs);
96 setAlwaysDrawnWithCacheEnabled(false);
Adam Cohendf2cc412011-04-27 16:56:57 -070097 mInflater = LayoutInflater.from(context);
98 mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
99 mExpandDuration = getResources().getInteger(R.integer.config_folderAnimDuration);
Adam Cohen2801caf2011-05-13 20:57:39 -0700100
101 mMaxCountX = LauncherModel.getCellCountX() - 1;
102 mMaxCountY = LauncherModel.getCellCountY() - 1;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800103 }
104
105 @Override
106 protected void onFinishInflate() {
107 super.onFinishInflate();
Adam Cohendf2cc412011-04-27 16:56:57 -0700108 mContent = (CellLayout) findViewById(R.id.folder_content);
Adam Cohen2801caf2011-05-13 20:57:39 -0700109 mContent.setGridSize(0, 0);
110 mContent.enableHardwareLayers();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800111 }
Adam Cohen2801caf2011-05-13 20:57:39 -0700112
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800113 public void onItemClick(AdapterView parent, View v, int position, long id) {
Joe Onorato0589f0f2010-02-08 13:44:00 -0800114 ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
Romain Guyfb5411e2010-02-24 10:04:17 -0800115 int[] pos = new int[2];
116 v.getLocationOnScreen(pos);
117 app.intent.setSourceBounds(new Rect(pos[0], pos[1],
118 pos[0] + v.getWidth(), pos[1] + v.getHeight()));
Joe Onoratof984e852010-03-25 09:47:45 -0700119 mLauncher.startActivitySafely(app.intent, app);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800120 }
121
122 public void onClick(View v) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700123 Object tag = v.getTag();
124 if (tag instanceof ShortcutInfo) {
125 // refactor this code from Folder
126 ShortcutInfo item = (ShortcutInfo) tag;
127 int[] pos = new int[2];
128 v.getLocationOnScreen(pos);
129 item.intent.setSourceBounds(new Rect(pos[0], pos[1],
130 pos[0] + v.getWidth(), pos[1] + v.getHeight()));
131 mLauncher.startActivitySafely(item.intent, item);
Adam Cohendf2cc412011-04-27 16:56:57 -0700132 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800133 }
134
135 public boolean onLongClick(View v) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700136 Object tag = v.getTag();
137 if (tag instanceof ShortcutInfo) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700138 mLauncher.closeFolder(this);
139
Adam Cohendf2cc412011-04-27 16:56:57 -0700140 ShortcutInfo item = (ShortcutInfo) tag;
141 if (!v.isInTouchMode()) {
142 return false;
143 }
144
145 mLauncher.getWorkspace().onDragStartedWithItem(v);
146 mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700147 mDragItemPosition[0] = item.cellX;
148 mDragItemPosition[1] = item.cellY;
Adam Cohenbadf71e2011-05-26 19:08:29 -0700149 mIconDrawable = ((TextView) v).getCompoundDrawables()[1];
Adam Cohen2801caf2011-05-13 20:57:39 -0700150 mInfo.remove(item);
151
Adam Cohendf2cc412011-04-27 16:56:57 -0700152 mDragItem = item;
153 } else {
154 mLauncher.closeFolder(this);
155 mLauncher.showRenameDialog(mInfo);
156 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800157 return true;
158 }
159
Adam Cohenbadf71e2011-05-26 19:08:29 -0700160 public Drawable getDragDrawable() {
161 return mIconDrawable;
162 }
163
Adam Cohen0c872ba2011-05-05 10:34:16 -0700164 /**
165 * We need to handle touch events to prevent them from falling through to the workspace below.
166 */
167 @Override
168 public boolean onTouchEvent(MotionEvent ev) {
169 return true;
170 }
171
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800172 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
173 if (!view.isInTouchMode()) {
174 return false;
175 }
176
Joe Onorato0589f0f2010-02-08 13:44:00 -0800177 ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800178
Joe Onorato00acb122009-08-04 16:04:30 -0400179 mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800180 mLauncher.closeFolder(this);
181 mDragItem = app;
182
183 return true;
184 }
185
Joe Onorato00acb122009-08-04 16:04:30 -0400186 public void setDragController(DragController dragController) {
187 mDragController = dragController;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800188 }
189
Patrick Dubroya669d792010-11-23 14:40:33 -0800190 public void onDragViewVisible() {
191 }
192
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800193 void setLauncher(Launcher launcher) {
194 mLauncher = launcher;
195 }
Adam Cohen2801caf2011-05-13 20:57:39 -0700196
197 void setFolderIcon(FolderIcon icon) {
198 mFolderIcon = icon;
199 }
200
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800201 /**
202 * @return the FolderInfo object associated with this folder
203 */
204 FolderInfo getInfo() {
205 return mInfo;
206 }
207
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800208 void onOpen() {
Adam Cohendf2cc412011-04-27 16:56:57 -0700209 // When the folder opens, we need to refresh the GridView's selection by
210 // forcing a layout
211 // TODO: find out if this is still necessary
212 mContent.requestLayout();
213 requestFocus();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800214 }
215
216 void onClose() {
217 final Workspace workspace = mLauncher.getWorkspace();
Michael Jurka0142d492010-08-25 17:46:15 -0700218 workspace.getChildAt(workspace.getCurrentPage()).requestFocus();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800219 }
220
221 void bind(FolderInfo info) {
222 mInfo = info;
Adam Cohendf2cc412011-04-27 16:56:57 -0700223 ArrayList<ShortcutInfo> children = info.contents;
Adam Cohen7c693212011-05-18 15:26:57 -0700224 setupContentForNumItems(children.size());
Adam Cohendf2cc412011-04-27 16:56:57 -0700225 for (int i = 0; i < children.size(); i++) {
226 ShortcutInfo child = (ShortcutInfo) children.get(i);
Adam Cohen7c693212011-05-18 15:26:57 -0700227 createAndAddShortcut(child);
Adam Cohendf2cc412011-04-27 16:56:57 -0700228 }
Adam Cohen4dbe6d92011-05-18 17:14:15 -0700229 mItemsInvalidated = true;
Adam Cohena9cf38f2011-05-02 15:36:58 -0700230 mInfo.addListener(this);
Adam Cohendf2cc412011-04-27 16:56:57 -0700231 }
232
233 /**
234 * Creates a new UserFolder, inflated from R.layout.user_folder.
235 *
236 * @param context The application's context.
237 *
238 * @return A new UserFolder.
239 */
240 static Folder fromXml(Context context) {
241 return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
242 }
243
244 /**
245 * This method is intended to make the UserFolder to be visually identical in size and position
246 * to its associated FolderIcon. This allows for a seamless transition into the expanded state.
247 */
248 private void positionAndSizeAsIcon() {
249 if (!(getParent() instanceof CellLayoutChildren)) return;
250
Adam Cohen2801caf2011-05-13 20:57:39 -0700251 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
Adam Cohendf2cc412011-04-27 16:56:57 -0700252 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
253
Adam Cohen2801caf2011-05-13 20:57:39 -0700254 if (mMode == PARTIAL_GROW) {
255 setScaleX(0.8f);
256 setScaleY(0.8f);
257 setAlpha(0f);
258 } else {
259 lp.width = iconLp.width;
260 lp.height = iconLp.height;
261 lp.x = iconLp.x;
262 lp.y = iconLp.y;
263 mContent.setAlpha(0);
264 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700265 mState = STATE_SMALL;
266 }
267
268 public void animateOpen() {
269 if (mState != STATE_SMALL) {
270 positionAndSizeAsIcon();
271 }
272 if (!(getParent() instanceof CellLayoutChildren)) return;
273
Adam Cohen2801caf2011-05-13 20:57:39 -0700274 ObjectAnimator oa;
Adam Cohendf2cc412011-04-27 16:56:57 -0700275 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
276
Adam Cohen2801caf2011-05-13 20:57:39 -0700277 centerAboutIcon();
278 if (mMode == PARTIAL_GROW) {
279 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
280 PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
281 PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
282 oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
283 } else {
284 PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", mNewSize.width());
285 PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", mNewSize.height());
286 PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", mNewSize.left);
287 PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", mNewSize.top);
288 oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
289 oa.addUpdateListener(new AnimatorUpdateListener() {
290 public void onAnimationUpdate(ValueAnimator animation) {
291 requestLayout();
292 }
293 });
Adam Cohendf2cc412011-04-27 16:56:57 -0700294
Adam Cohen2801caf2011-05-13 20:57:39 -0700295 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
296 ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
297 alphaOa.setDuration(mExpandDuration);
298 alphaOa.setInterpolator(new AccelerateInterpolator(2.0f));
299 alphaOa.start();
300 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700301
Adam Cohen2801caf2011-05-13 20:57:39 -0700302 oa.addListener(new AnimatorListenerAdapter() {
Adam Cohendf2cc412011-04-27 16:56:57 -0700303 @Override
304 public void onAnimationStart(Animator animation) {
305 mState = STATE_ANIMATING;
306 }
307 @Override
308 public void onAnimationEnd(Animator animation) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700309 mState = STATE_OPEN;
Adam Cohendf2cc412011-04-27 16:56:57 -0700310 }
311 });
Adam Cohen2801caf2011-05-13 20:57:39 -0700312 oa.setDuration(mExpandDuration);
313 oa.start();
Adam Cohendf2cc412011-04-27 16:56:57 -0700314 }
315
316 public void animateClosed() {
317 if (!(getParent() instanceof CellLayoutChildren)) return;
318
319 CellLayoutChildren clc = (CellLayoutChildren) getParent();
320 final CellLayout cellLayout = (CellLayout) clc.getParent();
Adam Cohen2801caf2011-05-13 20:57:39 -0700321 ObjectAnimator oa;
Adam Cohendf2cc412011-04-27 16:56:57 -0700322
Adam Cohen2801caf2011-05-13 20:57:39 -0700323 if (mMode == PARTIAL_GROW) {
324 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
325 PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
326 PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
327 oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
328 } else {
329 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
330 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
Adam Cohendf2cc412011-04-27 16:56:57 -0700331
Adam Cohen2801caf2011-05-13 20:57:39 -0700332 PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", iconLp.width);
333 PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", iconLp.height);
334 PropertyValuesHolder x = PropertyValuesHolder.ofInt("x",iconLp.x);
335 PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", iconLp.y);
336 oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
337 oa.addUpdateListener(new AnimatorUpdateListener() {
338 public void onAnimationUpdate(ValueAnimator animation) {
339 requestLayout();
340 }
341 });
Adam Cohendf2cc412011-04-27 16:56:57 -0700342
Adam Cohen2801caf2011-05-13 20:57:39 -0700343 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
344 ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
345 alphaOa.setDuration(mExpandDuration);
346 alphaOa.setInterpolator(new DecelerateInterpolator(2.0f));
347 alphaOa.start();
348 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700349
Adam Cohen2801caf2011-05-13 20:57:39 -0700350 oa.addListener(new AnimatorListenerAdapter() {
Adam Cohendf2cc412011-04-27 16:56:57 -0700351 @Override
352 public void onAnimationEnd(Animator animation) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700353 onCloseComplete();
Adam Cohendf2cc412011-04-27 16:56:57 -0700354 cellLayout.removeViewWithoutMarkingCells(Folder.this);
Adam Cohen2801caf2011-05-13 20:57:39 -0700355 mState = STATE_SMALL;
Adam Cohendf2cc412011-04-27 16:56:57 -0700356 }
357 @Override
358 public void onAnimationStart(Animator animation) {
359 mState = STATE_ANIMATING;
360 }
361 });
Adam Cohen2801caf2011-05-13 20:57:39 -0700362 oa.setDuration(mExpandDuration);
363 oa.start();
Adam Cohendf2cc412011-04-27 16:56:57 -0700364 }
365
366 void notifyDataSetChanged() {
367 // recreate all the children if the data set changes under us. We may want to do this more
368 // intelligently (ie just removing the views that should no longer exist)
369 mContent.removeAllViewsInLayout();
370 bind(mInfo);
371 }
372
Adam Cohencb3382b2011-05-24 14:07:08 -0700373 public boolean acceptDrop(DragObject d) {
374 final ItemInfo item = (ItemInfo) d.dragInfo;
Adam Cohendf2cc412011-04-27 16:56:57 -0700375 final int itemType = item.itemType;
Adam Cohen2801caf2011-05-13 20:57:39 -0700376 return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
377 itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
378 !isFull());
Adam Cohendf2cc412011-04-27 16:56:57 -0700379 }
380
Adam Cohencb3382b2011-05-24 14:07:08 -0700381 public void onDrop(DragObject d) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700382 ShortcutInfo item;
Adam Cohencb3382b2011-05-24 14:07:08 -0700383 if (d.dragInfo instanceof ApplicationInfo) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700384 // Came from all apps -- make a copy
Adam Cohencb3382b2011-05-24 14:07:08 -0700385 item = ((ApplicationInfo) d.dragInfo).makeShortcut();
Adam Cohendf2cc412011-04-27 16:56:57 -0700386 item.spanX = 1;
387 item.spanY = 1;
388 } else {
Adam Cohencb3382b2011-05-24 14:07:08 -0700389 item = (ShortcutInfo) d.dragInfo;
Adam Cohendf2cc412011-04-27 16:56:57 -0700390 }
Adam Cohendf2cc412011-04-27 16:56:57 -0700391 mInfo.add(item);
Adam Cohendf2cc412011-04-27 16:56:57 -0700392 LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
393 }
394
395 protected boolean findAndSetEmptyCells(ShortcutInfo item) {
396 int[] emptyCell = new int[2];
397 if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
398 item.cellX = emptyCell[0];
399 item.cellY = emptyCell[1];
400 LauncherModel.addOrMoveItemInDatabase(
401 mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
402 return true;
403 } else {
404 return false;
405 }
406 }
407
408 protected void createAndAddShortcut(ShortcutInfo item) {
409 final TextView textView =
410 (TextView) mInflater.inflate(R.layout.application_boxed, this, false);
411 textView.setCompoundDrawablesWithIntrinsicBounds(null,
412 new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
413 textView.setText(item.title);
414 textView.setTag(item);
415
416 textView.setOnClickListener(this);
417 textView.setOnLongClickListener(this);
418
419 CellLayout.LayoutParams lp =
420 new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
421 boolean insert = false;
422 mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
423 }
424
Adam Cohencb3382b2011-05-24 14:07:08 -0700425 public void onDragEnter(DragObject d) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700426 mContent.onDragEnter();
Adam Cohendf2cc412011-04-27 16:56:57 -0700427 }
428
Adam Cohencb3382b2011-05-24 14:07:08 -0700429 public void onDragOver(DragObject d) {
430 float[] r = mapPointFromScreenToContent(d.x, d.y, null);
Adam Cohen2801caf2011-05-13 20:57:39 -0700431 mContent.visualizeDropLocation(null, null, (int) r[0], (int) r[1], 1, 1);
Adam Cohendf2cc412011-04-27 16:56:57 -0700432 }
433
Adam Cohencb3382b2011-05-24 14:07:08 -0700434 public void onDragExit(DragObject d) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700435 mContent.onDragExit();
436 }
437
438 public float[] mapPointFromScreenToContent(int x, int y, float[] r) {
439 if (r == null) {
440 r = new float[2];
441 }
442
443 int[] screenLocation = new int[2];
444 mContent.getLocationOnScreen(screenLocation);
445
446 r[0] = x - screenLocation[0];
447 r[1] = y - screenLocation[1];
448 return r;
Adam Cohendf2cc412011-04-27 16:56:57 -0700449 }
450
451 public void onDropCompleted(View target, Object dragInfo, boolean success) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700452 }
453
454 public boolean isDropEnabled() {
455 return true;
456 }
457
Adam Cohencb3382b2011-05-24 14:07:08 -0700458 public DropTarget getDropTargetDelegate(DragObject d) {
Adam Cohendf2cc412011-04-27 16:56:57 -0700459 return null;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800460 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700461
Adam Cohen2801caf2011-05-13 20:57:39 -0700462 private void setupContentDimension(int count) {
463 ArrayList<View> list = getItemsInReadingOrder();
464
465 int countX = mContent.getCountX();
466 int countY = mContent.getCountY();
Adam Cohen7c693212011-05-18 15:26:57 -0700467 boolean done = false;
Adam Cohen2801caf2011-05-13 20:57:39 -0700468
Adam Cohen7c693212011-05-18 15:26:57 -0700469 while (!done) {
470 int oldCountX = countX;
471 int oldCountY = countY;
472 if (countX * countY < count) {
473 // Current grid is too small, expand it
474 if (countX <= countY && countX < mMaxCountX) {
475 countX++;
476 } else if (countY < mMaxCountY) {
477 countY++;
478 }
479 if (countY == 0) countY++;
480 } else if ((countY - 1) * countX >= count && countY >= countX) {
481 countY = Math.max(0, countY - 1);
482 } else if ((countX - 1) * countY >= count) {
483 countX = Math.max(0, countX - 1);
Adam Cohen2801caf2011-05-13 20:57:39 -0700484 }
Adam Cohen7c693212011-05-18 15:26:57 -0700485 done = countX == oldCountX && countY == oldCountY;
Adam Cohen2801caf2011-05-13 20:57:39 -0700486 }
Adam Cohen7c693212011-05-18 15:26:57 -0700487 mContent.setGridSize(countX, countY);
Adam Cohen2801caf2011-05-13 20:57:39 -0700488 arrangeChildren(list);
489 }
490
491 public boolean isFull() {
492 return getItemCount() >= mMaxCountX * mMaxCountY;
493 }
494
495 private void centerAboutIcon() {
496 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
497 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
498
499 int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
500 int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight();
501
502 int centerX = iconLp.x + iconLp.width / 2;
503 int centerY = iconLp.y + iconLp.height / 2;
504 int centeredLeft = centerX - width / 2;
505 int centeredTop = centerY - height / 2;
506
507 CellLayoutChildren clc = (CellLayoutChildren) getParent();
508 int parentWidth = 0;
509 int parentHeight = 0;
510 if (clc != null) {
511 parentWidth = clc.getMeasuredWidth();
512 parentHeight = clc.getMeasuredHeight();
513 }
514
515 int left = Math.min(Math.max(0, centeredLeft), parentWidth - width);
516 int top = Math.min(Math.max(0, centeredTop), parentHeight - height);
517
518 int folderPivotX = width / 2 + (centeredLeft - left);
519 int folderPivotY = height / 2 + (centeredTop - top);
520 setPivotX(folderPivotX);
521 setPivotY(folderPivotY);
522 int folderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
523 (1.0f * folderPivotX / width));
524 int folderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
525 (1.0f * folderPivotY / height));
526 mFolderIcon.setPivotX(folderIconPivotX);
527 mFolderIcon.setPivotY(folderIconPivotY);
528
529 if (mMode == PARTIAL_GROW) {
530 lp.width = width;
531 lp.height = height;
532 lp.x = left;
533 lp.y = top;
534 } else {
535 mNewSize.set(left, top, left + width, top + height);
536 }
537 }
538
539 private void setupContentForNumItems(int count) {
Adam Cohen2801caf2011-05-13 20:57:39 -0700540 setupContentDimension(count);
541
542 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
543 if (lp == null) {
544 lp = new CellLayout.LayoutParams(0, 0, -1, -1);
545 lp.isLockedToGrid = false;
546 setLayoutParams(lp);
547 }
548 centerAboutIcon();
549 }
550
551 private void arrangeChildren(ArrayList<View> list) {
552 int[] vacant = new int[2];
553 if (list == null) {
554 list = getItemsInReadingOrder();
555 }
556 mContent.removeAllViews();
557
558 for (int i = 0; i < list.size(); i++) {
559 View v = list.get(i);
560 mContent.getVacantCell(vacant, 1, 1);
561 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
562 lp.cellX = vacant[0];
563 lp.cellY = vacant[1];
564 ItemInfo info = (ItemInfo) v.getTag();
565 info.cellX = vacant[0];
566 info.cellY = vacant[1];
567 boolean insert = false;
568 mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true);
Adam Cohen7c693212011-05-18 15:26:57 -0700569 LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0,
570 info.cellX, info.cellY);
Adam Cohen2801caf2011-05-13 20:57:39 -0700571 }
Adam Cohen7c693212011-05-18 15:26:57 -0700572 mItemsInvalidated = true;
Adam Cohen2801caf2011-05-13 20:57:39 -0700573 }
574
Adam Cohena9cf38f2011-05-02 15:36:58 -0700575 public void onAdd(ShortcutInfo item) {
Adam Cohen7c693212011-05-18 15:26:57 -0700576 mItemsInvalidated = true;
Adam Cohen2801caf2011-05-13 20:57:39 -0700577 if (!findAndSetEmptyCells(item)) {
578 // The current layout is full, can we expand it?
579 setupContentForNumItems(getItemCount() + 1);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700580 findAndSetEmptyCells(item);
581 }
582 createAndAddShortcut(item);
583 }
584
585 public int getItemCount() {
586 return mContent.getChildrenLayout().getChildCount();
587 }
588
589 public View getItemAt(int index) {
590 return mContent.getChildrenLayout().getChildAt(index);
591 }
592
Adam Cohen2801caf2011-05-13 20:57:39 -0700593 private void onCloseComplete() {
594 if (mRearrangeOnClose) {
595 setupContentForNumItems(getItemCount());
596 mRearrangeOnClose = false;
597 }
598 }
599
Adam Cohena9cf38f2011-05-02 15:36:58 -0700600 public void onRemove(ShortcutInfo item) {
Adam Cohen7c693212011-05-18 15:26:57 -0700601 mItemsInvalidated = true;
Adam Cohena9cf38f2011-05-02 15:36:58 -0700602 View v = mContent.getChildAt(mDragItemPosition[0], mDragItemPosition[1]);
603 mContent.removeView(v);
Adam Cohen2801caf2011-05-13 20:57:39 -0700604 if (mState == STATE_ANIMATING) {
605 mRearrangeOnClose = true;
606 } else {
607 setupContentForNumItems(getItemCount());
608 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700609 }
Adam Cohen7c693212011-05-18 15:26:57 -0700610
611 public ArrayList<View> getItemsInReadingOrder() {
612 if (mItemsInvalidated) {
613 mItemsInReadingOrder.clear();
614 for (int j = 0; j < mContent.getCountY(); j++) {
615 for (int i = 0; i < mContent.getCountX(); i++) {
616 View v = mContent.getChildAt(i, j);
617 if (v != null) {
618 mItemsInReadingOrder.add(v);
619 }
620 }
621 }
622 mItemsInvalidated = false;
623 }
624 return mItemsInReadingOrder;
625 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800626}