blob: a6139ccbc58179f8780fe38bcb08dfc0fdbf7426 [file] [log] [blame]
Winson Chung82f55532011-08-09 14:14:23 -07001/*
2 * Copyright (C) 2011 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
Daniel Sandler325dc232013-06-05 22:57:57 -040017package com.android.launcher3;
Winson Chung82f55532011-08-09 14:14:23 -070018
Winson Chungaf40f202013-09-18 18:26:31 -070019import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
Winson Chung3a6e7f32013-10-09 15:50:52 -070021import android.content.ComponentName;
Michael Jurka34c2e6c2013-12-13 16:07:45 +010022import android.content.Context;
Winson Chung3a6e7f32013-10-09 15:50:52 -070023import android.content.Intent;
Winson Chung82f55532011-08-09 14:14:23 -070024import android.content.res.Resources;
25import android.content.res.TypedArray;
Winson Chung3a6e7f32013-10-09 15:50:52 -070026import android.graphics.*;
Winson Chung82f55532011-08-09 14:14:23 -070027import android.graphics.drawable.Drawable;
28import android.util.AttributeSet;
29import android.util.DisplayMetrics;
Svetoslav Ganov55d225d2012-05-22 15:19:14 -070030import android.view.FocusFinder;
31import android.view.MotionEvent;
32import android.view.View;
Winson Chung205cd772014-01-15 14:31:59 -080033import android.view.ViewGroup;
Winson Chungaf40f202013-09-18 18:26:31 -070034import android.view.animation.AccelerateInterpolator;
Winson Chung82f55532011-08-09 14:14:23 -070035import android.widget.FrameLayout;
Winson Chung3a6e7f32013-10-09 15:50:52 -070036import android.widget.TextView;
Winson Chung82f55532011-08-09 14:14:23 -070037
Winson Chung3a6e7f32013-10-09 15:50:52 -070038public class Cling extends FrameLayout implements Insettable, View.OnClickListener,
39 View.OnLongClickListener, View.OnTouchListener {
Winson Chung82f55532011-08-09 14:14:23 -070040
Winson Chungaf40f202013-09-18 18:26:31 -070041 private static String FIRST_RUN_PORTRAIT = "first_run_portrait";
42 private static String FIRST_RUN_LANDSCAPE = "first_run_landscape";
Winson Chung7d7541e2011-09-16 20:14:36 -070043
Winson Chung82f55532011-08-09 14:14:23 -070044 private static String WORKSPACE_PORTRAIT = "workspace_portrait";
45 private static String WORKSPACE_LANDSCAPE = "workspace_landscape";
Andrew Flynn2f5f9452012-05-12 17:00:35 -070046 private static String WORKSPACE_LARGE = "workspace_large";
47 private static String WORKSPACE_CUSTOM = "workspace_custom";
48
Winson Chunga6945242014-01-08 14:04:34 -080049 private static String MIGRATION_PORTRAIT = "migration_portrait";
50 private static String MIGRATION_LANDSCAPE = "migration_landscape";
51
52 private static String MIGRATION_WORKSPACE_PORTRAIT = "migration_workspace_portrait";
Winson Chung205cd772014-01-15 14:31:59 -080053 private static String MIGRATION_WORKSPACE_LARGE_PORTRAIT = "migration_workspace_large_portrait";
Winson Chunga6945242014-01-08 14:04:34 -080054 private static String MIGRATION_WORKSPACE_LANDSCAPE = "migration_workspace_landscape";
55
Winson Chung7d7541e2011-09-16 20:14:36 -070056 private static String FOLDER_PORTRAIT = "folder_portrait";
57 private static String FOLDER_LANDSCAPE = "folder_landscape";
Winson Chungd0160152011-11-15 15:04:42 -080058 private static String FOLDER_LARGE = "folder_large";
Winson Chung82f55532011-08-09 14:14:23 -070059
Winson Chunge6eabff2013-09-24 11:01:23 -070060 private static float FIRST_RUN_CIRCLE_BUFFER_DPS = 60;
Winson Chung205cd772014-01-15 14:31:59 -080061 private static float FIRST_RUN_MAX_CIRCLE_RADIUS_DPS = 180;
Winson Chungaf40f202013-09-18 18:26:31 -070062 private static float WORKSPACE_INNER_CIRCLE_RADIUS_DPS = 50;
63 private static float WORKSPACE_OUTER_CIRCLE_RADIUS_DPS = 60;
64 private static float WORKSPACE_CIRCLE_Y_OFFSET_DPS = 30;
Winson Chunga6945242014-01-08 14:04:34 -080065 private static float MIGRATION_WORKSPACE_INNER_CIRCLE_RADIUS_DPS = 42;
66 private static float MIGRATION_WORKSPACE_OUTER_CIRCLE_RADIUS_DPS = 46;
Winson Chungaf40f202013-09-18 18:26:31 -070067
Winson Chung82f55532011-08-09 14:14:23 -070068 private Launcher mLauncher;
69 private boolean mIsInitialized;
70 private String mDrawIdentifier;
Winson Chung7d7541e2011-09-16 20:14:36 -070071 private Drawable mBackground;
Winson Chung82f55532011-08-09 14:14:23 -070072
Winson Chung3a6e7f32013-10-09 15:50:52 -070073 private int[] mTouchDownPt = new int[2];
74
75 private Drawable mFocusedHotseatApp;
76 private ComponentName mFocusedHotseatAppComponent;
77 private Rect mFocusedHotseatAppBounds;
78
Winson Chung7d7541e2011-09-16 20:14:36 -070079 private Paint mErasePaint;
Winson Chunga6945242014-01-08 14:04:34 -080080 private Paint mBorderPaint;
Winson Chungaf40f202013-09-18 18:26:31 -070081 private Paint mBubblePaint;
82 private Paint mDotPaint;
83
Winson Chungfa545132013-09-26 17:45:32 -070084 private View mScrimView;
85 private int mBackgroundColor;
86
Winson Chungaf40f202013-09-18 18:26:31 -070087 private final Rect mInsets = new Rect();
Winson Chung7d7541e2011-09-16 20:14:36 -070088
Winson Chung82f55532011-08-09 14:14:23 -070089 public Cling(Context context) {
90 this(context, null, 0);
91 }
92
93 public Cling(Context context, AttributeSet attrs) {
94 this(context, attrs, 0);
95 }
96
97 public Cling(Context context, AttributeSet attrs, int defStyle) {
98 super(context, attrs, defStyle);
99
100 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Cling, defStyle, 0);
101 mDrawIdentifier = a.getString(R.styleable.Cling_drawIdentifier);
102 a.recycle();
Michael Jurka9bc8eba2012-05-21 20:36:44 -0700103
104 setClickable(true);
Winson Chungaf40f202013-09-18 18:26:31 -0700105
Winson Chung82f55532011-08-09 14:14:23 -0700106 }
107
Winson Chungfa545132013-09-26 17:45:32 -0700108 void init(Launcher l, View scrim) {
Winson Chung82f55532011-08-09 14:14:23 -0700109 if (!mIsInitialized) {
110 mLauncher = l;
Winson Chungfa545132013-09-26 17:45:32 -0700111 mScrimView = scrim;
Winson Chung205cd772014-01-15 14:31:59 -0800112 mBackgroundColor = 0xcc000000;
Winson Chungaf40f202013-09-18 18:26:31 -0700113 setOnLongClickListener(this);
Winson Chung3a6e7f32013-10-09 15:50:52 -0700114 setOnClickListener(this);
115 setOnTouchListener(this);
Winson Chung82f55532011-08-09 14:14:23 -0700116
Winson Chung7d7541e2011-09-16 20:14:36 -0700117 mErasePaint = new Paint();
118 mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
119 mErasePaint.setColor(0xFFFFFF);
120 mErasePaint.setAlpha(0);
Winson Chungaf40f202013-09-18 18:26:31 -0700121 mErasePaint.setAntiAlias(true);
122
Winson Chunga6945242014-01-08 14:04:34 -0800123 mBorderPaint = new Paint();
124 mBorderPaint.setColor(0xFFFFFFFF);
125 mBorderPaint.setAntiAlias(true);
126
Winson Chunge6eabff2013-09-24 11:01:23 -0700127 int circleColor = getResources().getColor(
128 R.color.first_run_cling_circle_background_color);
Winson Chungaf40f202013-09-18 18:26:31 -0700129 mBubblePaint = new Paint();
Winson Chunge6eabff2013-09-24 11:01:23 -0700130 mBubblePaint.setColor(circleColor);
Winson Chungaf40f202013-09-18 18:26:31 -0700131 mBubblePaint.setAntiAlias(true);
132
133 mDotPaint = new Paint();
134 mDotPaint.setColor(0x72BBED);
135 mDotPaint.setAntiAlias(true);
Winson Chung7d7541e2011-09-16 20:14:36 -0700136
Winson Chung82f55532011-08-09 14:14:23 -0700137 mIsInitialized = true;
138 }
139 }
140
Winson Chung3a6e7f32013-10-09 15:50:52 -0700141 void setFocusedHotseatApp(int drawableId, int appRank, ComponentName cn, String title,
142 String description) {
143 // Get the app to draw
144 Resources r = getResources();
145 int appIconId = drawableId;
146 Hotseat hotseat = mLauncher.getHotseat();
Winson Chung205cd772014-01-15 14:31:59 -0800147 // Skip the focused app in the large layouts
148 if (!mDrawIdentifier.equals(WORKSPACE_LARGE) &&
149 hotseat != null && appIconId > -1 && appRank > -1 && !title.isEmpty() &&
Winson Chung3a6e7f32013-10-09 15:50:52 -0700150 !description.isEmpty()) {
151 // Set the app bounds
152 int x = hotseat.getCellXFromOrder(appRank);
153 int y = hotseat.getCellYFromOrder(appRank);
154 Rect pos = hotseat.getCellCoordinates(x, y);
155 LauncherAppState app = LauncherAppState.getInstance();
156 DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
157 mFocusedHotseatApp = getResources().getDrawable(appIconId);
158 mFocusedHotseatAppComponent = cn;
159 mFocusedHotseatAppBounds = new Rect(pos.left, pos.top,
160 pos.left + Utilities.sIconTextureWidth,
161 pos.top + Utilities.sIconTextureHeight);
162 Utilities.scaleRectAboutCenter(mFocusedHotseatAppBounds,
Winson Chung6e1c0d32013-10-25 15:24:24 -0700163 ((float) grid.hotseatIconSizePx / grid.iconSizePx));
Winson Chung3a6e7f32013-10-09 15:50:52 -0700164
165 // Set the title
166 TextView v = (TextView) findViewById(R.id.focused_hotseat_app_title);
167 if (v != null) {
168 v.setText(title);
169 }
170
171 // Set the description
172 v = (TextView) findViewById(R.id.focused_hotseat_app_description);
173 if (v != null) {
174 v.setText(description);
175 }
176
177 // Show the bubble
178 View bubble = findViewById(R.id.focused_hotseat_app_bubble);
179 bubble.setVisibility(View.VISIBLE);
180 }
181 }
182
Winson Chung205cd772014-01-15 14:31:59 -0800183 void setOpenFolderRect(Rect r) {
184 if (mDrawIdentifier.equals(FOLDER_LANDSCAPE) ||
185 mDrawIdentifier.equals(FOLDER_LARGE)) {
186 ViewGroup vg = (ViewGroup) findViewById(R.id.folder_bubble);
187 ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) vg.getLayoutParams();
188 lp.topMargin = r.top - mInsets.bottom;
189 lp.leftMargin = r.right;
190 vg.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
191 vg.requestLayout();
192 }
193 }
194
Winson Chunga6945242014-01-08 14:04:34 -0800195 void updateMigrationWorkspaceBubblePosition() {
196 DisplayMetrics metrics = new DisplayMetrics();
197 mLauncher.getWindowManager().getDefaultDisplay().getMetrics(metrics);
198
199 // Get the page indicator bounds
200 LauncherAppState app = LauncherAppState.getInstance();
201 DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
202 Rect pageIndicatorBounds = grid.getWorkspacePageIndicatorBounds(mInsets);
203
Winson Chung205cd772014-01-15 14:31:59 -0800204 if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT)) {
205 View bubble = findViewById(R.id.migration_workspace_cling_bubble);
206 ViewGroup.MarginLayoutParams lp =
207 (ViewGroup.MarginLayoutParams) bubble.getLayoutParams();
208 lp.bottomMargin = grid.heightPx - pageIndicatorBounds.top;
209 bubble.requestLayout();
210 } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT)) {
211 View bubble = findViewById(R.id.content);
212 ViewGroup.MarginLayoutParams lp =
213 (ViewGroup.MarginLayoutParams) bubble.getLayoutParams();
214 lp.bottomMargin = grid.heightPx - pageIndicatorBounds.top;
215 bubble.requestLayout();
216 } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
217 View bubble = findViewById(R.id.content);
218 ViewGroup.MarginLayoutParams lp =
219 (ViewGroup.MarginLayoutParams) bubble.getLayoutParams();
220 if (grid.isLayoutRtl) {
221 lp.leftMargin = pageIndicatorBounds.right;
222 } else {
223 lp.rightMargin = (grid.widthPx - pageIndicatorBounds.left);
224 }
225 bubble.requestLayout();
226 }
227 }
228
229 void updateWorkspaceBubblePosition() {
230 DisplayMetrics metrics = new DisplayMetrics();
231 mLauncher.getWindowManager().getDefaultDisplay().getMetrics(metrics);
232
233 // Get the cut-out bounds
234 LauncherAppState app = LauncherAppState.getInstance();
235 DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
236 Rect cutOutBounds = getWorkspaceCutOutBounds(metrics);
237
238 if (mDrawIdentifier.equals(WORKSPACE_LARGE)) {
239 View bubble = findViewById(R.id.workspace_cling_bubble);
240 ViewGroup.MarginLayoutParams lp =
241 (ViewGroup.MarginLayoutParams) bubble.getLayoutParams();
242 lp.bottomMargin = grid.heightPx - cutOutBounds.top - mInsets.bottom;
243 bubble.requestLayout();
244 }
245 }
246
247 private Rect getWorkspaceCutOutBounds(DisplayMetrics metrics) {
248 int halfWidth = metrics.widthPixels / 2;
249 int halfHeight = metrics.heightPixels / 2;
250 int yOffset = DynamicGrid.pxFromDp(WORKSPACE_CIRCLE_Y_OFFSET_DPS, metrics);
251 if (mDrawIdentifier.equals(WORKSPACE_LARGE)) {
252 yOffset = 0;
253 }
254 int radius = DynamicGrid.pxFromDp(WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics);
255 return new Rect(halfWidth - radius, halfHeight - yOffset - radius, halfWidth + radius,
256 halfHeight - yOffset + radius);
Winson Chunga6945242014-01-08 14:04:34 -0800257 }
258
Winson Chungaf40f202013-09-18 18:26:31 -0700259 void show(boolean animate, int duration) {
260 setVisibility(View.VISIBLE);
261 setLayerType(View.LAYER_TYPE_HARDWARE, null);
262 if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
263 mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
264 mDrawIdentifier.equals(WORKSPACE_LARGE) ||
Winson Chunga6945242014-01-08 14:04:34 -0800265 mDrawIdentifier.equals(WORKSPACE_CUSTOM) ||
266 mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
Winson Chung205cd772014-01-15 14:31:59 -0800267 mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT) ||
Winson Chunga6945242014-01-08 14:04:34 -0800268 mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
Winson Chungaf40f202013-09-18 18:26:31 -0700269 View content = getContent();
270 content.setAlpha(0f);
271 content.animate()
272 .alpha(1f)
273 .setDuration(duration)
Winson Chungfa545132013-09-26 17:45:32 -0700274 .setListener(null)
Winson Chungaf40f202013-09-18 18:26:31 -0700275 .start();
276 setAlpha(1f);
277 } else {
278 if (animate) {
279 buildLayer();
280 setAlpha(0f);
281 animate()
282 .alpha(1f)
283 .setInterpolator(new AccelerateInterpolator())
284 .setDuration(duration)
Winson Chungfa545132013-09-26 17:45:32 -0700285 .setListener(null)
Winson Chungaf40f202013-09-18 18:26:31 -0700286 .start();
287 } else {
288 setAlpha(1f);
289 }
290 }
Winson Chungfa545132013-09-26 17:45:32 -0700291
292 // Show the scrim if necessary
293 if (mScrimView != null) {
294 mScrimView.setVisibility(View.VISIBLE);
295 mScrimView.setAlpha(0f);
296 mScrimView.animate()
297 .alpha(1f)
298 .setDuration(duration)
299 .setListener(null)
300 .start();
301 }
302
Winson Chungaf40f202013-09-18 18:26:31 -0700303 setFocusableInTouchMode(true);
304 post(new Runnable() {
305 public void run() {
306 setFocusable(true);
307 requestFocus();
308 }
309 });
310 }
311
312 void hide(final int duration, final Runnable postCb) {
313 if (mDrawIdentifier.equals(FIRST_RUN_PORTRAIT) ||
Winson Chunga6945242014-01-08 14:04:34 -0800314 mDrawIdentifier.equals(FIRST_RUN_LANDSCAPE) ||
315 mDrawIdentifier.equals(MIGRATION_PORTRAIT) ||
316 mDrawIdentifier.equals(MIGRATION_LANDSCAPE)) {
Winson Chungaf40f202013-09-18 18:26:31 -0700317 View content = getContent();
Winson Chungfa545132013-09-26 17:45:32 -0700318 content.animate()
319 .alpha(0f)
320 .setDuration(duration)
321 .setListener(new AnimatorListenerAdapter() {
322 public void onAnimationEnd(Animator animation) {
323 // We are about to trigger the workspace cling, so don't do anything else
324 setVisibility(View.GONE);
325 postCb.run();
326 };
327 })
328 .start();
Winson Chungaf40f202013-09-18 18:26:31 -0700329 } else {
Winson Chungfa545132013-09-26 17:45:32 -0700330 animate()
331 .alpha(0f)
332 .setDuration(duration)
333 .setListener(new AnimatorListenerAdapter() {
334 public void onAnimationEnd(Animator animation) {
335 // We are about to trigger the workspace cling, so don't do anything else
336 setVisibility(View.GONE);
337 postCb.run();
338 };
339 })
340 .start();
341 }
342
343 // Show the scrim if necessary
344 if (mScrimView != null) {
345 mScrimView.animate()
346 .alpha(0f)
347 .setDuration(duration)
348 .setListener(new AnimatorListenerAdapter() {
349 public void onAnimationEnd(Animator animation) {
350 mScrimView.setVisibility(View.GONE);
351 };
352 })
353 .start();
Winson Chungaf40f202013-09-18 18:26:31 -0700354 }
355 }
356
Winson Chung82f55532011-08-09 14:14:23 -0700357 void cleanup() {
Winson Chung7d7541e2011-09-16 20:14:36 -0700358 mBackground = null;
Winson Chung7d7541e2011-09-16 20:14:36 -0700359 mIsInitialized = false;
360 }
361
Winson Chungfa545132013-09-26 17:45:32 -0700362 void bringScrimToFront() {
363 if (mScrimView != null) {
364 mScrimView.bringToFront();
365 }
366 }
367
Winson Chungaf40f202013-09-18 18:26:31 -0700368 @Override
369 public void setInsets(Rect insets) {
370 mInsets.set(insets);
371 setPadding(insets.left, insets.top, insets.right, insets.bottom);
Michael Jurka974c3862012-05-22 22:00:31 -0700372 }
373
Winson Chungaf40f202013-09-18 18:26:31 -0700374 View getContent() {
375 return findViewById(R.id.content);
376 }
377
378 String getDrawIdentifier() {
379 return mDrawIdentifier;
Winson Chung82f55532011-08-09 14:14:23 -0700380 }
381
382 @Override
Svetoslav Ganov55d225d2012-05-22 15:19:14 -0700383 public View focusSearch(int direction) {
Michael Jurka9bc8eba2012-05-21 20:36:44 -0700384 return this.focusSearch(this, direction);
Svetoslav Ganov55d225d2012-05-22 15:19:14 -0700385 }
386
387 @Override
388 public View focusSearch(View focused, int direction) {
389 return FocusFinder.getInstance().findNextFocus(this, focused, direction);
390 }
391
392 @Override
393 public boolean onHoverEvent(MotionEvent event) {
394 return (mDrawIdentifier.equals(WORKSPACE_PORTRAIT)
395 || mDrawIdentifier.equals(WORKSPACE_LANDSCAPE)
396 || mDrawIdentifier.equals(WORKSPACE_LARGE)
Svetoslav Ganov55d225d2012-05-22 15:19:14 -0700397 || mDrawIdentifier.equals(WORKSPACE_CUSTOM));
398 }
399
400 @Override
Winson Chung82f55532011-08-09 14:14:23 -0700401 public boolean onTouchEvent(android.view.MotionEvent event) {
Winson Chungaf40f202013-09-18 18:26:31 -0700402 if (mDrawIdentifier.equals(FOLDER_PORTRAIT) ||
Winson Chungd0160152011-11-15 15:04:42 -0800403 mDrawIdentifier.equals(FOLDER_LANDSCAPE) ||
404 mDrawIdentifier.equals(FOLDER_LARGE)) {
Winson Chung7d7541e2011-09-16 20:14:36 -0700405 Folder f = mLauncher.getWorkspace().getOpenFolder();
406 if (f != null) {
407 Rect r = new Rect();
408 f.getHitRect(r);
409 if (r.contains((int) event.getX(), (int) event.getY())) {
410 return false;
411 }
412 }
413 }
Winson Chungaf40f202013-09-18 18:26:31 -0700414 return super.onTouchEvent(event);
Winson Chung82f55532011-08-09 14:14:23 -0700415 };
416
417 @Override
Winson Chung3a6e7f32013-10-09 15:50:52 -0700418 public boolean onTouch(View v, MotionEvent ev) {
419 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
420 mTouchDownPt[0] = (int) ev.getX();
421 mTouchDownPt[1] = (int) ev.getY();
422 }
423 return false;
424 }
425
426 @Override
427 public void onClick(View v) {
428 if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
429 mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
430 mDrawIdentifier.equals(WORKSPACE_LARGE)) {
431 if (mFocusedHotseatAppBounds != null &&
432 mFocusedHotseatAppBounds.contains(mTouchDownPt[0], mTouchDownPt[1])) {
433 // Launch the activity that is being highlighted
434 Intent intent = new Intent(Intent.ACTION_MAIN);
435 intent.setComponent(mFocusedHotseatAppComponent);
436 intent.addCategory(Intent.CATEGORY_LAUNCHER);
437 mLauncher.startActivity(intent, null);
Winson Chunga6945242014-01-08 14:04:34 -0800438 mLauncher.getLauncherClings().dismissWorkspaceCling(this);
Winson Chung3a6e7f32013-10-09 15:50:52 -0700439 }
440 }
441 }
442
443 @Override
Winson Chungaf40f202013-09-18 18:26:31 -0700444 public boolean onLongClick(View v) {
445 if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
446 mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
447 mDrawIdentifier.equals(WORKSPACE_LARGE)) {
Winson Chunga6945242014-01-08 14:04:34 -0800448 mLauncher.getLauncherClings().dismissWorkspaceCling(null);
449 return true;
450 } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
Winson Chung205cd772014-01-15 14:31:59 -0800451 mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT) ||
Winson Chunga6945242014-01-08 14:04:34 -0800452 mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
453 mLauncher.getLauncherClings().dismissMigrationWorkspaceCling(null);
Winson Chungaf40f202013-09-18 18:26:31 -0700454 return true;
455 }
456 return false;
457 }
458
459 @Override
Winson Chung82f55532011-08-09 14:14:23 -0700460 protected void dispatchDraw(Canvas canvas) {
Winson Chung82f55532011-08-09 14:14:23 -0700461 if (mIsInitialized) {
Winson Chungaf40f202013-09-18 18:26:31 -0700462 canvas.save();
Winson Chung82f55532011-08-09 14:14:23 -0700463
Winson Chunga6945242014-01-08 14:04:34 -0800464 // Get the page indicator bounds
465 LauncherAppState app = LauncherAppState.getInstance();
466 DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
467 Rect pageIndicatorBounds = grid.getWorkspacePageIndicatorBounds(mInsets);
468
Winson Chungaf40f202013-09-18 18:26:31 -0700469 // Get the background override if there is one
Winson Chung7d7541e2011-09-16 20:14:36 -0700470 if (mBackground == null) {
Winson Chungaf40f202013-09-18 18:26:31 -0700471 if (mDrawIdentifier.equals(WORKSPACE_CUSTOM)) {
Andrew Flynna743d352012-05-18 13:38:52 -0700472 mBackground = getResources().getDrawable(R.drawable.bg_cling5);
Winson Chung7d7541e2011-09-16 20:14:36 -0700473 }
474 }
Winson Chungaf40f202013-09-18 18:26:31 -0700475 // Draw the background
476 Bitmap eraseBg = null;
477 Canvas eraseCanvas = null;
Winson Chungfa545132013-09-26 17:45:32 -0700478 if (mScrimView != null) {
479 // Skip drawing the background
480 mScrimView.setBackgroundColor(mBackgroundColor);
481 } else if (mBackground != null) {
Winson Chung7d7541e2011-09-16 20:14:36 -0700482 mBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
Winson Chungaf40f202013-09-18 18:26:31 -0700483 mBackground.draw(canvas);
Winson Chungaf40f202013-09-18 18:26:31 -0700484 } else if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
485 mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
Winson Chunga6945242014-01-08 14:04:34 -0800486 mDrawIdentifier.equals(WORKSPACE_LARGE) ||
487 mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
Winson Chung205cd772014-01-15 14:31:59 -0800488 mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT) ||
Winson Chunga6945242014-01-08 14:04:34 -0800489 mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
Winson Chungaf40f202013-09-18 18:26:31 -0700490 // Initialize the draw buffer (to allow punching through)
491 eraseBg = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),
492 Bitmap.Config.ARGB_8888);
493 eraseCanvas = new Canvas(eraseBg);
Winson Chungfa545132013-09-26 17:45:32 -0700494 eraseCanvas.drawColor(mBackgroundColor);
Winson Chung7d7541e2011-09-16 20:14:36 -0700495 } else {
Winson Chungfa545132013-09-26 17:45:32 -0700496 canvas.drawColor(mBackgroundColor);
Winson Chung7d7541e2011-09-16 20:14:36 -0700497 }
Winson Chung82f55532011-08-09 14:14:23 -0700498
Winson Chungaf40f202013-09-18 18:26:31 -0700499 // Draw everything else
500 DisplayMetrics metrics = new DisplayMetrics();
501 mLauncher.getWindowManager().getDefaultDisplay().getMetrics(metrics);
502 float alpha = getAlpha();
503 View content = getContent();
504 if (content != null) {
505 alpha *= content.getAlpha();
506 }
507 if (mDrawIdentifier.equals(FIRST_RUN_PORTRAIT) ||
508 mDrawIdentifier.equals(FIRST_RUN_LANDSCAPE)) {
Winson Chung45cab392013-10-02 17:45:32 -0700509 // Draw the circle
Winson Chungaf40f202013-09-18 18:26:31 -0700510 View bubbleContent = findViewById(R.id.bubble_content);
511 Rect bubbleRect = new Rect();
512 bubbleContent.getGlobalVisibleRect(bubbleRect);
513 mBubblePaint.setAlpha((int) (255 * alpha));
514 float buffer = DynamicGrid.pxFromDp(FIRST_RUN_CIRCLE_BUFFER_DPS, metrics);
Winson Chung205cd772014-01-15 14:31:59 -0800515 float maxRadius = DynamicGrid.pxFromDp(FIRST_RUN_MAX_CIRCLE_RADIUS_DPS, metrics);
516 float radius = Math.min(maxRadius, (bubbleContent.getMeasuredWidth() + buffer) / 2);
Winson Chungaf40f202013-09-18 18:26:31 -0700517 canvas.drawCircle(metrics.widthPixels / 2,
Winson Chung205cd772014-01-15 14:31:59 -0800518 bubbleRect.centerY(), radius,
Winson Chungaf40f202013-09-18 18:26:31 -0700519 mBubblePaint);
520 } else if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
521 mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
522 mDrawIdentifier.equals(WORKSPACE_LARGE)) {
Winson Chung205cd772014-01-15 14:31:59 -0800523 Rect cutOutBounds = getWorkspaceCutOutBounds(metrics);
Winson Chunga6945242014-01-08 14:04:34 -0800524 // Draw the outer circle
525 mErasePaint.setAlpha(128);
Winson Chung205cd772014-01-15 14:31:59 -0800526 eraseCanvas.drawCircle(cutOutBounds.centerX(), cutOutBounds.centerY(),
Winson Chungaf40f202013-09-18 18:26:31 -0700527 DynamicGrid.pxFromDp(WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics),
528 mErasePaint);
Winson Chunga6945242014-01-08 14:04:34 -0800529 // Draw the inner circle
Winson Chungaf40f202013-09-18 18:26:31 -0700530 mErasePaint.setAlpha(0);
Winson Chung205cd772014-01-15 14:31:59 -0800531 eraseCanvas.drawCircle(cutOutBounds.centerX(), cutOutBounds.centerY(),
Winson Chungaf40f202013-09-18 18:26:31 -0700532 DynamicGrid.pxFromDp(WORKSPACE_INNER_CIRCLE_RADIUS_DPS, metrics),
533 mErasePaint);
534 canvas.drawBitmap(eraseBg, 0, 0, null);
535 eraseCanvas.setBitmap(null);
536 eraseBg = null;
Winson Chung7d7541e2011-09-16 20:14:36 -0700537
Winson Chung3a6e7f32013-10-09 15:50:52 -0700538 // Draw the focused hotseat app icon
539 if (mFocusedHotseatAppBounds != null && mFocusedHotseatApp != null) {
540 mFocusedHotseatApp.setBounds(mFocusedHotseatAppBounds.left,
541 mFocusedHotseatAppBounds.top, mFocusedHotseatAppBounds.right,
542 mFocusedHotseatAppBounds.bottom);
543 mFocusedHotseatApp.setAlpha((int) (255 * alpha));
544 mFocusedHotseatApp.draw(canvas);
545 }
Winson Chunga6945242014-01-08 14:04:34 -0800546 } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
Winson Chung205cd772014-01-15 14:31:59 -0800547 mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT) ||
Winson Chunga6945242014-01-08 14:04:34 -0800548 mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
549 int offset = DynamicGrid.pxFromDp(WORKSPACE_CIRCLE_Y_OFFSET_DPS, metrics);
550 // Draw the outer circle
551 eraseCanvas.drawCircle(pageIndicatorBounds.centerX(),
552 pageIndicatorBounds.centerY(),
553 DynamicGrid.pxFromDp(MIGRATION_WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics),
554 mBorderPaint);
555 // Draw the inner circle
556 mErasePaint.setAlpha(0);
557 eraseCanvas.drawCircle(pageIndicatorBounds.centerX(),
558 pageIndicatorBounds.centerY(),
559 DynamicGrid.pxFromDp(MIGRATION_WORKSPACE_INNER_CIRCLE_RADIUS_DPS, metrics),
560 mErasePaint);
561 canvas.drawBitmap(eraseBg, 0, 0, null);
562 eraseCanvas.setBitmap(null);
563 eraseBg = null;
Winson Chung3a6e7f32013-10-09 15:50:52 -0700564 }
Winson Chungaf40f202013-09-18 18:26:31 -0700565 canvas.restore();
Winson Chung82f55532011-08-09 14:14:23 -0700566 }
Winson Chung7d7541e2011-09-16 20:14:36 -0700567
568 // Draw the rest of the cling
569 super.dispatchDraw(canvas);
Winson Chung82f55532011-08-09 14:14:23 -0700570 };
571}