blob: 5c87e094da885b69209043ffabcbf765da6f1f74 [file] [log] [blame]
Joe Onoratoa5902522009-07-30 13:37:37 -07001package com.android.launcher2;
The Android Open Source Project31dd5032009-03-03 19:32:27 -08002
Adam Cohen66396872011-04-15 17:50:36 -07003import java.util.ArrayList;
4
Adam Cohen7f4eabe2011-04-21 16:19:16 -07005import android.animation.Animator;
6import android.animation.AnimatorListenerAdapter;
7import android.animation.AnimatorSet;
8import android.animation.ObjectAnimator;
9import android.animation.PropertyValuesHolder;
10import android.animation.ValueAnimator;
11import android.animation.Animator.AnimatorListener;
12import android.animation.ValueAnimator.AnimatorUpdateListener;
13import android.appwidget.AppWidgetProviderInfo;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080014import android.content.Context;
Adam Cohen7f4eabe2011-04-21 16:19:16 -070015import android.graphics.Color;
Michael Jurka66d72172011-04-12 16:29:25 -070016import android.graphics.Rect;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080017import android.util.AttributeSet;
18import android.view.LayoutInflater;
19import android.view.View;
Michael Jurka66d72172011-04-12 16:29:25 -070020import android.widget.TextView;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080021
Romain Guyedcce092010-03-04 13:03:17 -080022import com.android.launcher.R;
23
The Android Open Source Project31dd5032009-03-03 19:32:27 -080024/**
25 * Folder which contains applications or shortcuts chosen by the user.
26 *
27 */
28public class UserFolder extends Folder implements DropTarget {
Joe Onorato2e5c4322009-10-06 12:34:42 -070029 private static final String TAG = "Launcher.UserFolder";
30
Adam Cohen7f4eabe2011-04-21 16:19:16 -070031 static final int STATE_NONE = -1;
32 static final int STATE_SMALL = 0;
33 static final int STATE_ANIMATING = 1;
34 static final int STATE_OPEN = 2;
35
36 private int mExpandDuration;
Michael Jurka66d72172011-04-12 16:29:25 -070037 protected CellLayout mContent;
38 private final LayoutInflater mInflater;
39 private final IconCache mIconCache;
Adam Cohen7f4eabe2011-04-21 16:19:16 -070040 private int mState = STATE_NONE;
Michael Jurka66d72172011-04-12 16:29:25 -070041
The Android Open Source Project31dd5032009-03-03 19:32:27 -080042 public UserFolder(Context context, AttributeSet attrs) {
43 super(context, attrs);
Michael Jurka66d72172011-04-12 16:29:25 -070044 mInflater = LayoutInflater.from(context);
45 mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
Adam Cohen7f4eabe2011-04-21 16:19:16 -070046 mExpandDuration = getResources().getInteger(R.integer.config_folderAnimDuration);
Michael Jurka66d72172011-04-12 16:29:25 -070047 }
48
49 @Override
50 protected void onFinishInflate() {
51 super.onFinishInflate();
Michael Jurka66d72172011-04-12 16:29:25 -070052 mContent = (CellLayout) findViewById(R.id.folder_content);
The Android Open Source Project31dd5032009-03-03 19:32:27 -080053 }
Adam Cohen7f4eabe2011-04-21 16:19:16 -070054
The Android Open Source Project31dd5032009-03-03 19:32:27 -080055 /**
56 * Creates a new UserFolder, inflated from R.layout.user_folder.
57 *
58 * @param context The application's context.
59 *
60 * @return A new UserFolder.
61 */
62 static UserFolder fromXml(Context context) {
63 return (UserFolder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
64 }
65
Adam Cohen7f4eabe2011-04-21 16:19:16 -070066 /**
67 * This method is intended to make the UserFolder to be visually identical in size and position
68 * to its associated FolderIcon. This allows for a seamless transition into the expanded state.
69 */
70 private void positionAndSizeAsIcon() {
71 if (!(getParent() instanceof CellLayoutChildren)) return;
72
73 CellLayoutChildren clc = (CellLayoutChildren) getParent();
74 CellLayout cellLayout = (CellLayout) clc.getParent();
75
76 FolderIcon fi = (FolderIcon) cellLayout.getChildAt(mInfo.cellX, mInfo.cellY);
77 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) fi.getLayoutParams();
78 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
79
80 lp.width = iconLp.width;
81 lp.height = iconLp.height;
82 lp.x = iconLp.x;
83 lp.y = iconLp.y;
84
85 mContent.setAlpha(0f);
86 mState = STATE_SMALL;
87 }
88
89 public void animateOpen() {
90 if (mState != STATE_SMALL) {
91 positionAndSizeAsIcon();
92 }
93 if (!(getParent() instanceof CellLayoutChildren)) return;
94
95 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
96
97 CellLayoutChildren clc = (CellLayoutChildren) getParent();
98 CellLayout cellLayout = (CellLayout) clc.getParent();
99 Rect r = cellLayout.getContentRect(null);
100
101 PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", r.width());
102 PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", r.height());
103 PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", 0);
104 PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", 0);
105
106 ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
107 oa.addUpdateListener(new AnimatorUpdateListener() {
108 public void onAnimationUpdate(ValueAnimator animation) {
109 requestLayout();
110 }
111 });
112
113 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
114 ObjectAnimator oaContentAlpha = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
115
116 AnimatorSet set = new AnimatorSet();
117 set.playTogether(oa, oaContentAlpha);
118 set.setDuration(mExpandDuration);
119 set.addListener(new AnimatorListenerAdapter() {
120 @Override
121 public void onAnimationStart(Animator animation) {
122 mState = STATE_ANIMATING;
123 }
124 @Override
125 public void onAnimationEnd(Animator animation) {
126 mState = STATE_SMALL;
127 }
128 });
129 set.start();
130 }
131
132 public void animateClosed() {
133 if (!(getParent() instanceof CellLayoutChildren)) return;
134
135 CellLayoutChildren clc = (CellLayoutChildren) getParent();
136 final CellLayout cellLayout = (CellLayout) clc.getParent();
137
138 FolderIcon fi = (FolderIcon) cellLayout.getChildAt(mInfo.cellX, mInfo.cellY);
139 CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) fi.getLayoutParams();
140 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
141
142 PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", iconLp.width);
143 PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", iconLp.height);
144 PropertyValuesHolder x = PropertyValuesHolder.ofInt("x",iconLp.x);
145 PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", iconLp.y);
146
147 ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
148 oa.addUpdateListener(new AnimatorUpdateListener() {
149 public void onAnimationUpdate(ValueAnimator animation) {
150 requestLayout();
151 }
152 });
153
154 PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
155 ObjectAnimator oaContentAlpha = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
156
157 AnimatorSet set = new AnimatorSet();
158 set.playTogether(oa, oaContentAlpha);
159 set.setDuration(mExpandDuration);
160
161 set.addListener(new AnimatorListenerAdapter() {
162 @Override
163 public void onAnimationEnd(Animator animation) {
164 cellLayout.removeViewWithoutMarkingCells(UserFolder.this);
165 mState = STATE_OPEN;
166 }
167 @Override
168 public void onAnimationStart(Animator animation) {
169 mState = STATE_ANIMATING;
170 }
171 });
172 set.start();
173 }
174
Michael Jurka66d72172011-04-12 16:29:25 -0700175 @Override
176 void notifyDataSetChanged() {
177 // recreate all the children if the data set changes under us. We may want to do this more
178 // intelligently (ie just removing the views that should no longer exist)
179 mContent.removeAllViewsInLayout();
180 bind(mInfo);
181 }
182
183 public void onClick(View v) {
184 Object tag = v.getTag();
185 if (tag instanceof ShortcutInfo) {
186 // refactor this code from Folder
187 ShortcutInfo item = (ShortcutInfo) tag;
188 int[] pos = new int[2];
189 v.getLocationOnScreen(pos);
190 item.intent.setSourceBounds(new Rect(pos[0], pos[1],
191 pos[0] + v.getWidth(), pos[1] + v.getHeight()));
192 mLauncher.startActivitySafely(item.intent, item);
193 } else {
194 super.onClick(v);
195 }
196 }
197
198 public boolean onLongClick(View v) {
199 Object tag = v.getTag();
200 if (tag instanceof ShortcutInfo) {
201 // refactor this code from Folder
202 ShortcutInfo item = (ShortcutInfo) tag;
203 if (!v.isInTouchMode()) {
204 return false;
205 }
206
Adam Cohen66396872011-04-15 17:50:36 -0700207 mLauncher.getWorkspace().onDragStartedWithItem(v);
Michael Jurka66d72172011-04-12 16:29:25 -0700208 mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
Adam Cohen66396872011-04-15 17:50:36 -0700209
Michael Jurka66d72172011-04-12 16:29:25 -0700210 mLauncher.closeFolder(this);
211 mDragItem = item;
212
213 return true;
214 } else {
215 return super.onLongClick(v);
216 }
217 }
218
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800219 public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
Joe Onorato00acb122009-08-04 16:04:30 -0400220 DragView dragView, Object dragInfo) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800221 final ItemInfo item = (ItemInfo) dragInfo;
222 final int itemType = item.itemType;
223 return (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
Joe Onorato2e5c4322009-10-06 12:34:42 -0700224 itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT)
225 && item.container != mInfo.id;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800226 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800227
Joe Onorato00acb122009-08-04 16:04:30 -0400228 public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
229 DragView dragView, Object dragInfo) {
Joe Onorato0589f0f2010-02-08 13:44:00 -0800230 ShortcutInfo item;
231 if (dragInfo instanceof ApplicationInfo) {
Joe Onorato2e5c4322009-10-06 12:34:42 -0700232 // Came from all apps -- make a copy
Joe Onorato0589f0f2010-02-08 13:44:00 -0800233 item = ((ApplicationInfo)dragInfo).makeShortcut();
Michael Jurka66d72172011-04-12 16:29:25 -0700234 item.spanX = 1;
235 item.spanY = 1;
Joe Onorato0589f0f2010-02-08 13:44:00 -0800236 } else {
237 item = (ShortcutInfo)dragInfo;
Joe Onorato2e5c4322009-10-06 12:34:42 -0700238 }
Michael Jurka66d72172011-04-12 16:29:25 -0700239 findAndSetEmptyCells(item);
240 ((UserFolderInfo)mInfo).add(item);
241 createAndAddShortcut(item);
242 LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
243 }
244
245 protected boolean findAndSetEmptyCells(ShortcutInfo item) {
246 int[] emptyCell = new int[2];
247 if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
248 item.cellX = emptyCell[0];
249 item.cellY = emptyCell[1];
250 LauncherModel.addOrMoveItemInDatabase(
251 mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
252 return true;
253 } else {
254 return false;
255 }
256 }
257
258 protected void createAndAddShortcut(ShortcutInfo item) {
259 final TextView textView =
260 (TextView) mInflater.inflate(R.layout.application_boxed, this, false);
261 textView.setCompoundDrawablesWithIntrinsicBounds(null,
262 new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
263 textView.setText(item.title);
264 textView.setTag(item);
265
266 textView.setOnClickListener(this);
267 textView.setOnLongClickListener(this);
268
269 CellLayout.LayoutParams lp =
270 new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
271 boolean insert = false;
272 mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800273 }
274
Joe Onorato00acb122009-08-04 16:04:30 -0400275 public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
276 DragView dragView, Object dragInfo) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800277 }
278
Joe Onorato00acb122009-08-04 16:04:30 -0400279 public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
280 DragView dragView, Object dragInfo) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800281 }
282
Joe Onorato00acb122009-08-04 16:04:30 -0400283 public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
284 DragView dragView, Object dragInfo) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800285 }
286
287 @Override
Patrick Dubroy5f445422011-02-18 14:35:21 -0800288 public void onDropCompleted(View target, Object dragInfo, boolean success) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800289 if (success) {
Michael Jurka66d72172011-04-12 16:29:25 -0700290 ((UserFolderInfo)mInfo).remove(mDragItem);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800291 }
292 }
293
Michael Jurka0280c3b2010-09-17 15:00:07 -0700294 public boolean isDropEnabled() {
295 return true;
296 }
297
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800298 void bind(FolderInfo info) {
299 super.bind(info);
Michael Jurka66d72172011-04-12 16:29:25 -0700300 ArrayList<ShortcutInfo> children = ((UserFolderInfo)info).contents;
301 for (int i = 0; i < children.size(); i++) {
302 ShortcutInfo child = (ShortcutInfo) children.get(i);
303 if ((child.cellX == -1 && child.cellY == -1) ||
304 mContent.isOccupied(child.cellX, child.cellY)) {
305 findAndSetEmptyCells(child);
306 }
307 createAndAddShortcut((ShortcutInfo) children.get(i));
308 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800309 }
310
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800311 @Override
312 void onOpen() {
313 super.onOpen();
Michael Jurka66d72172011-04-12 16:29:25 -0700314 // When the folder opens, we need to refresh the GridView's selection by
315 // forcing a layout
316 // TODO: find out if this is still necessary
317 mContent.requestLayout();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800318 requestFocus();
319 }
Patrick Dubroy440c3602010-07-13 17:50:32 -0700320
321 @Override
322 public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
323 DragView dragView, Object dragInfo) {
324 return null;
325 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800326}