WidgetsContainerView.java revision 3f471440a8b6b71d4c15501a96befd3b715c9e8f
13f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song/* 23f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Copyright (C) 2015 The Android Open Source Project 33f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * 43f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Licensed under the Apache License, Version 2.0 (the "License"); 53f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * you may not use this file except in compliance with the License. 63f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * You may obtain a copy of the License at 73f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * 83f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * http://www.apache.org/licenses/LICENSE-2.0 93f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * 103f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Unless required by applicable law or agreed to in writing, software 113f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * distributed under the License is distributed on an "AS IS" BASIS, 123f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * See the License for the specific language governing permissions and 143f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * limitations under the License. 153f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */ 163f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 173f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songpackage com.android.launcher3.widget; 183f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 193f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.content.Context; 203f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.content.pm.PackageManager; 213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.graphics.Bitmap; 223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.graphics.Point; 233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.graphics.Rect; 243f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.graphics.drawable.Drawable; 253f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.support.v7.widget.LinearLayoutManager; 263f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.support.v7.widget.RecyclerView; 273f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.util.AttributeSet; 283f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.util.Log; 293f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.view.MotionEvent; 303f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.view.View; 313f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.widget.FrameLayout; 323f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.widget.ImageView; 333f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 343f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.CellLayout; 353f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.DeleteDropTarget; 363f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.DragController; 373f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.DragSource; 383f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.DropTarget.DragObject; 393f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.FastBitmapDrawable; 403f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.Folder; 413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.IconCache; 423f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.Insettable; 433f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.ItemInfo; 443f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.Launcher; 453f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.LauncherAppState; 463f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.PendingAddItemInfo; 473f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.R; 483f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.Utilities; 493f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.WidgetPreviewLoader; 503f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.Workspace; 513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 523f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport java.util.ArrayList; 533f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 543f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song/** 553f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * The widgets list view container. 563f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */ 573f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songpublic class WidgetsContainerView extends FrameLayout implements Insettable, View.OnTouchListener, 583f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song View.OnLongClickListener, DragSource{ 593f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 603f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private static final String TAG = "WidgetContainerView"; 613f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private static final boolean DEBUG = false; 623f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 633f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* {@link RecyclerView} will keep following # of views in cache, before recycling. */ 643f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private static final int WIDGET_CACHE_SIZE = 2; 653f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 663f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* Global instances that are used inside this container. */ 673f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private Launcher mLauncher; 683f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private DragController mDragController; 693f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private IconCache mIconCache; 703f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 713f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* Data model for the widget */ 723f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private WidgetsModel mWidgets; 733f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 743f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* Recycler view related member variables */ 753f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private RecyclerView mView; 763f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private WidgetsListAdapter mAdapter; 773f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 783f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* Dragging related. */ 793f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private boolean mDraggingWidget = false; // TODO(hyunyoungs): seems not needed? check! 803f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private Point mLastTouchDownPos = new Point(); 813f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 823f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* Rendering related. */ 833f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private WidgetPreviewLoader mWidgetPreviewLoader; 843f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private Rect mPadding = new Rect(); 853f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 863f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public WidgetsContainerView(Context context) { 873f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song this(context, null); 883f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 893f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 903f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public WidgetsContainerView(Context context, AttributeSet attrs) { 913f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song this(context, attrs, 0); 923f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 933f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 943f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public WidgetsContainerView(Context context, AttributeSet attrs, int defStyleAttr) { 953f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song this(context, attrs, defStyleAttr, 0); 963f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 973f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 983f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public WidgetsContainerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 993f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song super(context, attrs, defStyleAttr); 1003f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher = (Launcher) context; 1013f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mDragController = mLauncher.getDragController(); 1023f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1033f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mAdapter = new WidgetsListAdapter(context, this, mLauncher, this, mLauncher); 1043f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mWidgets = new WidgetsModel(context, mAdapter); 1053f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mAdapter.setWidgetsModel(mWidgets); 1063f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mIconCache = (LauncherAppState.getInstance()).getIconCache(); 1073f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1083f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (DEBUG) { 1093f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.d(TAG, "WidgetsContainerView constructor"); 1103f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1113f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1123f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1133f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 1143f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song protected void onFinishInflate() { 1153f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (DEBUG) { 1163f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.d(TAG, String.format("onFinishInflate [widgets size=%d]", 1173f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mWidgets.getPackageSize())); 1183f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1193f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mView = (RecyclerView) findViewById(R.id.widgets_list_view); 1203f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mView.setAdapter(mAdapter); 1213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mView.setLayoutManager(new LinearLayoutManager(getContext())); 1223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mView.setItemViewCacheSize(WIDGET_CACHE_SIZE); 1233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1243f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mPadding.set(getPaddingLeft(), getPaddingTop(), getPaddingRight(), 1253f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song getPaddingBottom()); 1263f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1273f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1283f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 1293f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Returns views used for launcher transitions. 1303f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 1313f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1323f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public View getContentView() { 1333f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return findViewById(R.id.widgets_list_view); 1343f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1353f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1363f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public View getRevealView() { 1373f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // TODO(hyunyoungs): temporarily use apps view transition. 1383f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return findViewById(R.id.widgets_reveal_view); 1393f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1403f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public void scrollToTop() { 1423f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mView.scrollToPosition(0); 1433f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (DEBUG) { 1443f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.d(TAG, String.format("scrollToTop, [widgets size=%d]", 1453f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mWidgets.getPackageSize())); 1463f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1473f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1483f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1493f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 1503f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Touch related handling. 1513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 1523f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1533f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 1543f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean onLongClick(View v) { 1553f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (DEBUG) { 1563f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.d(TAG, String.format("onLonglick [v=%s]", v)); 1573f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1583f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1593f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Return early if this is not initiated from a touch 1603f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!v.isInTouchMode()) return false; 1613f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // When we have exited all apps or are in transition, disregard long clicks 1623f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!mLauncher.isWidgetsViewVisible() || 1633f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.getWorkspace().isSwitchingState()) return false; 1643f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Return if global dragging is not enabled 1653f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.d(TAG, String.format("onLonglick dragging enabled?.", v)); 1663f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!mLauncher.isDraggingEnabled()) return false; 1673f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1683f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return beginDragging(v); 1693f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1703f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1713f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private boolean beginDragging(View v) { 1723f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (v instanceof WidgetCell) { 1733f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!beginDraggingWidget((WidgetCell) v)) { 1743f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return false; 1753f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1763f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } else { 1773f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.e(TAG, "Unexpected dragging view: " + v); 1783f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1793f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1803f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // We delay entering spring-loaded mode slightly to make sure the UI 1813f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // thready is free of any work. 1823f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song postDelayed(new Runnable() { 1833f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 1843f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public void run() { 1853f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // We don't enter spring-loaded mode if the drag has been cancelled 1863f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (mLauncher.getDragController().isDragging()) { 1873f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Go into spring loaded mode (must happen before we startDrag()) 1883f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.enterSpringLoadedDragMode(); 1893f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1903f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1913f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song }, 150); 1923f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1933f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return true; 1943f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1953f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1963f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private boolean beginDraggingWidget(WidgetCell v) { 1973f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mDraggingWidget = true; 1983f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Get the widget preview as the drag representation 1993f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song ImageView image = (ImageView) v.findViewById(R.id.widget_preview); 2003f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag(); 2013f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2023f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and 2033f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // we abort the drag. 2043f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (image.getDrawable() == null) { 2053f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mDraggingWidget = false; 2063f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return false; 2073f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2083f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2093f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Compose the drag image 2103f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Bitmap preview; 2113f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Bitmap outline; 2123f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song float scale = 1f; 2133f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Point previewPadding = null; 2143f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2153f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (createItemInfo instanceof PendingAddWidgetInfo) { 2163f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // This can happen in some weird cases involving multi-touch. We can't start dragging 2173f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // the widget if this is null, so we break out. 2183f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2193f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) createItemInfo; 2203f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song int[] size = mLauncher.getWorkspace().estimateItemSize(createWidgetInfo, true); 2213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song FastBitmapDrawable previewDrawable = (FastBitmapDrawable) image.getDrawable(); 2233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song float minScale = 1.25f; 2243f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song int maxWidth = Math.min((int) (previewDrawable.getIntrinsicWidth() * minScale), size[0]); 2253f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2263f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song int[] previewSizeBeforeScale = new int[1]; 2273f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song preview = getWidgetPreviewLoader().generateWidgetPreview(createWidgetInfo.info, 2283f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song maxWidth, null, previewSizeBeforeScale); 2293f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Compare the size of the drag preview to the preview in the AppsCustomize tray 2303f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song int previewWidthInAppsCustomize = Math.min(previewSizeBeforeScale[0], 2313f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song v.getActualItemWidth()); 2323f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song scale = previewWidthInAppsCustomize / (float) preview.getWidth(); 2333f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2343f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // The bitmap in the AppsCustomize tray is always the the same size, so there 2353f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // might be extra pixels around the preview itself - this accounts for that 2363f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (previewWidthInAppsCustomize < previewDrawable.getIntrinsicWidth()) { 2373f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song int padding = 2383f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song (previewDrawable.getIntrinsicWidth() - previewWidthInAppsCustomize) / 2; 2393f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song previewPadding = new Point(padding, 0); 2403f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } else { 2423f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag(); 2433f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Drawable icon = mIconCache.getFullResIcon(createShortcutInfo.activityInfo); 2443f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song preview = Utilities.createIconBitmap(icon, mLauncher); 2453f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song createItemInfo.spanX = createItemInfo.spanY = 1; 2463f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2473f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2483f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Don't clip alpha values for the drag outline if we're using the default widget preview 2493f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song boolean clipAlpha = !(createItemInfo instanceof PendingAddWidgetInfo && 2503f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song (((PendingAddWidgetInfo) createItemInfo).previewImage == 0)); 2513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2523f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Save the preview for the outline generation, then dim the preview 2533f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song outline = Bitmap.createScaledBitmap(preview, preview.getWidth(), preview.getHeight(), 2543f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song false); 2553f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2563f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Start the drag 2573f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.lockScreenOrientation(); 2583f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.getWorkspace().onDragStartedWithItem(createItemInfo, outline, clipAlpha); 2593f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mDragController.startDrag(image, preview, this, createItemInfo, 2603f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song DragController.DRAG_ACTION_COPY, previewPadding, scale); 2613f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song outline.recycle(); 2623f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song preview.recycle(); 2633f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return true; 2643f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2653f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2663f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* 2673f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * @see android.view.View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent) 2683f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */ 2693f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2703f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean onTouch(View v, MotionEvent ev) { 2713f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.d(TAG, String.format("onTouch [MotionEvent=%s]", ev)); 2723f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (ev.getAction() == MotionEvent.ACTION_DOWN || 2733f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song ev.getAction() == MotionEvent.ACTION_MOVE) { 2743f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLastTouchDownPos.set((int) ev.getX(), (int) ev.getY()); 2753f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2763f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return false; 2773f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2783f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2793f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 2803f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Drag related handling methods that implement {@link DragSource} interface. 2813f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 2823f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2833f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2843f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean supportsFlingToDelete() { 2853f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return false; 2863f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2873f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2883f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2893f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean supportsAppInfoDropTarget() { 2903f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return true; 2913f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2923f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2933f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* 2943f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Both this method and {@link #supportsFlingToDelete} has to return {@code false} for the 2953f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * {@link DeleteDropTarget} to be invisible.) 2963f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */ 2973f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2983f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean supportsDeleteDropTarget() { 2993f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return false; 3003f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3013f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3023f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 3033f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public float getIntrinsicIconScaleFactor() { 3043f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return 0; 3053f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3063f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3073f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 3083f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public void onFlingToDeleteCompleted() { 3093f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // We just dismiss the drag when we fling, so cleanup here 3103f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.exitSpringLoadedDragModeDelayed(true, 3113f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null); 3123f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.unlockScreenOrientation(false); 3133f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3143f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3153f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 3163f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete, 3173f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song boolean success) { 3183f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() && 3193f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song !(target instanceof DeleteDropTarget) && !(target instanceof Folder))) { 3203f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Exit spring loaded mode if we have not successfully dropped or have not handled the 3213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // drop in Workspace 3223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.exitSpringLoadedDragModeDelayed(true, 3233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null); 3243f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3253f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.unlockScreenOrientation(false); 3263f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3273f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Display an error message if the drag failed due to there not being enough space on the 3283f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // target layout we were dropping on. 3293f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!success) { 3303f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song boolean showOutOfSpaceMessage = false; 3313f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (target instanceof Workspace) { 3323f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song int currentScreen = mLauncher.getCurrentWorkspaceScreen(); 3333f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Workspace workspace = (Workspace) target; 3343f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen); 3353f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song ItemInfo itemInfo = (ItemInfo) d.dragInfo; 3363f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (layout != null) { 3373f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song layout.calculateSpans(itemInfo); 3383f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song showOutOfSpaceMessage = 3393f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song !layout.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY); 3403f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3423f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (showOutOfSpaceMessage) { 3433f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.showOutOfSpaceMessage(false); 3443f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3453f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song d.deferDragViewCleanupPostAnimation = false; 3463f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3473f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3483f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3493f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 3503f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Container rendering related. 3513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 3523f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3533f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* 3543f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * @see Insettable#setInsets(Rect) 3553f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */ 3563f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 3573f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public void setInsets(Rect insets) { 3583f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song setPadding(mPadding.left + insets.left, mPadding.top + insets.top, 3593f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mPadding.right + insets.right, mPadding.bottom + insets.bottom); 3603f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3613f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3623f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /** 3633f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Initialize the widget data model. 3643f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */ 3653f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public void addWidgets(ArrayList<Object> widgetsShortcuts, PackageManager pm) { 3663f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mWidgets.addWidgetsAndShortcuts(widgetsShortcuts, pm); 3673f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3683f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3693f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private WidgetPreviewLoader getWidgetPreviewLoader() { 3703f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (mWidgetPreviewLoader == null) { 3713f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mWidgetPreviewLoader = LauncherAppState.getInstance().getWidgetCache(); 3723f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3733f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return mWidgetPreviewLoader; 3743f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3753f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3763f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song}