WidgetsContainerView.java revision 316490e636aad788fcfbfc2e04dd4f0e145bdd00
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.graphics.Bitmap; 213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.graphics.Rect; 223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.graphics.drawable.Drawable; 233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.support.v7.widget.LinearLayoutManager; 243f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.support.v7.widget.RecyclerView; 25e809332032c8f0c2f361eb8fc753f3b57d9cfaaaHyunyoung Songimport android.support.v7.widget.RecyclerView.State; 263f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.util.AttributeSet; 273f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.util.Log; 283f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.view.View; 29b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Songimport android.widget.Toast; 30f52abd7758b8f245522936e941336e574debabf5Sunny Goyal 319480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chungimport com.android.launcher3.BaseContainerView; 323f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.CellLayout; 333f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.DeleteDropTarget; 34fe7580aac4a75dfae5e59c52608182c5e9f76011Hyunyoung Songimport com.android.launcher3.DeviceProfile; 353f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.DragController; 363f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.DragSource; 373f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.DropTarget.DragObject; 383f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.Folder; 393f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.IconCache; 403f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.ItemInfo; 413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.Launcher; 423f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.LauncherAppState; 433f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.PendingAddItemInfo; 443f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.R; 453f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.Utilities; 463f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.WidgetPreviewLoader; 473f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.Workspace; 4858376925f9596c23f5c9ffa6c99630dfddcfce9cSunny Goyalimport com.android.launcher3.model.WidgetsModel; 49316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyalimport com.android.launcher3.util.Thunk; 503f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song/** 523f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * The widgets list view container. 533f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */ 549480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chungpublic class WidgetsContainerView extends BaseContainerView 559480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chung implements View.OnLongClickListener, View.OnClickListener, DragSource{ 563f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 57b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song private static final String TAG = "WidgetsContainerView"; 583f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private static final boolean DEBUG = false; 593f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 60e809332032c8f0c2f361eb8fc753f3b57d9cfaaaHyunyoung Song /* Coefficient multiplied to the screen height for preloading widgets. */ 61e809332032c8f0c2f361eb8fc753f3b57d9cfaaaHyunyoung Song private static final int PRELOAD_SCREEN_HEIGHT_MULTIPLE = 1; 62e809332032c8f0c2f361eb8fc753f3b57d9cfaaaHyunyoung Song 633f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* Global instances that are used inside this container. */ 64316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal @Thunk Launcher mLauncher; 653f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private DragController mDragController; 663f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private IconCache mIconCache; 673f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 683f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* Recycler view related member variables */ 69ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song private WidgetsRecyclerView mView; 703f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private WidgetsListAdapter mAdapter; 713f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 72b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song /* Touch handling related member variables. */ 73b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song private Toast mWidgetInstructionToast; 743f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 753f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* Rendering related. */ 763f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private WidgetPreviewLoader mWidgetPreviewLoader; 77b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song private WidgetHostViewLoader mWidgetHostViewLoader; 78b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 793f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private Rect mPadding = new Rect(); 803f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 813f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public WidgetsContainerView(Context context) { 823f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song this(context, null); 833f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 843f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 853f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public WidgetsContainerView(Context context, AttributeSet attrs) { 863f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song this(context, attrs, 0); 873f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 883f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 893f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public WidgetsContainerView(Context context, AttributeSet attrs, int defStyleAttr) { 903f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song super(context, attrs, defStyleAttr); 913f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher = (Launcher) context; 923f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mDragController = mLauncher.getDragController(); 93b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mWidgetHostViewLoader = new WidgetHostViewLoader(mLauncher); 94b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mAdapter = new WidgetsListAdapter(context, this, this, mLauncher); 953f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mIconCache = (LauncherAppState.getInstance()).getIconCache(); 963f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 973f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (DEBUG) { 983f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.d(TAG, "WidgetsContainerView constructor"); 993f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1003f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1013f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1023f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 1033f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song protected void onFinishInflate() { 104ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song mView = (WidgetsRecyclerView) findViewById(R.id.widgets_list_view); 1053f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mView.setAdapter(mAdapter); 1063f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 107e809332032c8f0c2f361eb8fc753f3b57d9cfaaaHyunyoung Song // This extends the layout space so that preloading happen for the {@link RecyclerView} 108e809332032c8f0c2f361eb8fc753f3b57d9cfaaaHyunyoung Song mView.setLayoutManager(new LinearLayoutManager(getContext()) { 109e809332032c8f0c2f361eb8fc753f3b57d9cfaaaHyunyoung Song @Override 110e809332032c8f0c2f361eb8fc753f3b57d9cfaaaHyunyoung Song protected int getExtraLayoutSpace(State state) { 1112e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen DeviceProfile grid = mLauncher.getDeviceProfile(); 112e809332032c8f0c2f361eb8fc753f3b57d9cfaaaHyunyoung Song return super.getExtraLayoutSpace(state) 113fe7580aac4a75dfae5e59c52608182c5e9f76011Hyunyoung Song + grid.availableHeightPx * PRELOAD_SCREEN_HEIGHT_MULTIPLE; 114e809332032c8f0c2f361eb8fc753f3b57d9cfaaaHyunyoung Song } 115e809332032c8f0c2f361eb8fc753f3b57d9cfaaaHyunyoung Song }); 1163f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mPadding.set(getPaddingLeft(), getPaddingTop(), getPaddingRight(), 1173f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song getPaddingBottom()); 1189480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chung onUpdatePaddings(); 1193f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1203f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 1223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Returns views used for launcher transitions. 1233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 1243f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1253f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public View getContentView() { 12699d950fb4dfb5cb9edaae572579fc25b2aca726fSunny Goyal return mView; 1273f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1283f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1293f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public View getRevealView() { 1303f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // TODO(hyunyoungs): temporarily use apps view transition. 1313f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return findViewById(R.id.widgets_reveal_view); 1323f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1333f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1343f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public void scrollToTop() { 1353f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mView.scrollToPosition(0); 1363f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1373f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1383f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 1393f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Touch related handling. 1403f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 1413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1423f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 143b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song public void onClick(View v) { 144b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song // When we have exited widget tray or are in transition, disregard clicks 145b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song if (!mLauncher.isWidgetsViewVisible() 146b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song || mLauncher.getWorkspace().isSwitchingState() 147b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song || !(v instanceof WidgetCell)) return; 148b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 149b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song // Let the user know that they have to long press to add a widget 150b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song if (mWidgetInstructionToast != null) { 151b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mWidgetInstructionToast.cancel(); 152b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 153b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mWidgetInstructionToast = Toast.makeText(getContext(),R.string.long_press_widget_to_add, 154b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song Toast.LENGTH_SHORT); 155b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mWidgetInstructionToast.show(); 156b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 157b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 158b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song @Override 1593f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean onLongClick(View v) { 1603f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (DEBUG) { 1613f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.d(TAG, String.format("onLonglick [v=%s]", v)); 1623f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1633f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Return early if this is not initiated from a touch 1643f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!v.isInTouchMode()) return false; 1653f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // When we have exited all apps or are in transition, disregard long clicks 1663f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!mLauncher.isWidgetsViewVisible() || 1673f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.getWorkspace().isSwitchingState()) return false; 1683f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Return if global dragging is not enabled 1693f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.d(TAG, String.format("onLonglick dragging enabled?.", v)); 1703f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!mLauncher.isDraggingEnabled()) return false; 1713f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 172b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song boolean status = beginDragging(v); 173b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song if (status) { 174b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mWidgetHostViewLoader.load(v); 175b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 176b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song return status; 1773f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1783f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1793f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private boolean beginDragging(View v) { 1803f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (v instanceof WidgetCell) { 1813f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!beginDraggingWidget((WidgetCell) v)) { 1823f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return false; 1833f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1843f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } else { 1853f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.e(TAG, "Unexpected dragging view: " + v); 1863f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1873f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 18858376925f9596c23f5c9ffa6c99630dfddcfce9cSunny Goyal // We don't enter spring-loaded mode if the drag has been cancelled 18958376925f9596c23f5c9ffa6c99630dfddcfce9cSunny Goyal if (mLauncher.getDragController().isDragging()) { 19058376925f9596c23f5c9ffa6c99630dfddcfce9cSunny Goyal // Go into spring loaded mode (must happen before we startDrag()) 19158376925f9596c23f5c9ffa6c99630dfddcfce9cSunny Goyal mLauncher.enterSpringLoadedDragMode(); 19258376925f9596c23f5c9ffa6c99630dfddcfce9cSunny Goyal } 1933f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1943f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return true; 1953f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1963f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1973f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private boolean beginDraggingWidget(WidgetCell v) { 1983f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Get the widget preview as the drag representation 199f52abd7758b8f245522936e941336e574debabf5Sunny Goyal WidgetImageView image = (WidgetImageView) 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. 204f52abd7758b8f245522936e941336e574debabf5Sunny Goyal if (image.getBitmap() == null) { 2053f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return false; 2063f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2073f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2083f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Compose the drag image 2093f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Bitmap preview; 2103f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song float scale = 1f; 211f52abd7758b8f245522936e941336e574debabf5Sunny Goyal final Rect bounds = image.getBitmapBounds(); 2123f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2133f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (createItemInfo instanceof PendingAddWidgetInfo) { 2143f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // This can happen in some weird cases involving multi-touch. We can't start dragging 2153f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // the widget if this is null, so we break out. 2163f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2173f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) createItemInfo; 2183f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song int[] size = mLauncher.getWorkspace().estimateItemSize(createWidgetInfo, true); 2193f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 220f52abd7758b8f245522936e941336e574debabf5Sunny Goyal Bitmap icon = image.getBitmap(); 2213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song float minScale = 1.25f; 222f52abd7758b8f245522936e941336e574debabf5Sunny Goyal int maxWidth = Math.min((int) (icon.getWidth() * minScale), size[0]); 2233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2243f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song int[] previewSizeBeforeScale = new int[1]; 2252e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen preview = getWidgetPreviewLoader().generateWidgetPreview(mLauncher, 2262e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen createWidgetInfo.info, maxWidth, null, previewSizeBeforeScale); 227f52abd7758b8f245522936e941336e574debabf5Sunny Goyal 228f52abd7758b8f245522936e941336e574debabf5Sunny Goyal if (previewSizeBeforeScale[0] < icon.getWidth()) { 229f52abd7758b8f245522936e941336e574debabf5Sunny Goyal // The icon has extra padding around it. 230f52abd7758b8f245522936e941336e574debabf5Sunny Goyal int padding = (icon.getWidth() - previewSizeBeforeScale[0]) / 2; 231f52abd7758b8f245522936e941336e574debabf5Sunny Goyal if (icon.getWidth() > image.getWidth()) { 232f52abd7758b8f245522936e941336e574debabf5Sunny Goyal padding = padding * image.getWidth() / icon.getWidth(); 233f52abd7758b8f245522936e941336e574debabf5Sunny Goyal } 234f52abd7758b8f245522936e941336e574debabf5Sunny Goyal 235f52abd7758b8f245522936e941336e574debabf5Sunny Goyal bounds.left += padding; 236f52abd7758b8f245522936e941336e574debabf5Sunny Goyal bounds.right -= padding; 2373f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 238f52abd7758b8f245522936e941336e574debabf5Sunny Goyal scale = bounds.width() / (float) preview.getWidth(); 2393f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } else { 2403f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag(); 2413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Drawable icon = mIconCache.getFullResIcon(createShortcutInfo.activityInfo); 2423f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song preview = Utilities.createIconBitmap(icon, mLauncher); 2433f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song createItemInfo.spanX = createItemInfo.spanY = 1; 2443f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2453f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2463f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Don't clip alpha values for the drag outline if we're using the default widget preview 2473f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song boolean clipAlpha = !(createItemInfo instanceof PendingAddWidgetInfo && 2483f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song (((PendingAddWidgetInfo) createItemInfo).previewImage == 0)); 2493f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2503f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Start the drag 2513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.lockScreenOrientation(); 252f52abd7758b8f245522936e941336e574debabf5Sunny Goyal mLauncher.getWorkspace().onDragStartedWithItem(createItemInfo, preview, clipAlpha); 2533f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mDragController.startDrag(image, preview, this, createItemInfo, 254f52abd7758b8f245522936e941336e574debabf5Sunny Goyal bounds, DragController.DRAG_ACTION_COPY, scale); 255f52abd7758b8f245522936e941336e574debabf5Sunny Goyal 2563f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song preview.recycle(); 2573f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return true; 2583f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2593f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2603f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 2613f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Drag related handling methods that implement {@link DragSource} interface. 2623f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 2633f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2643f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2653f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean supportsFlingToDelete() { 2663f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return false; 2673f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2683f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2693f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2703f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean supportsAppInfoDropTarget() { 2713f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return true; 2723f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2733f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2743f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* 2753f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Both this method and {@link #supportsFlingToDelete} has to return {@code false} for the 2763f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * {@link DeleteDropTarget} to be invisible.) 2773f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */ 2783f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2793f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean supportsDeleteDropTarget() { 2803f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return false; 2813f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2823f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2833f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2843f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public float getIntrinsicIconScaleFactor() { 2853f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return 0; 2863f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2873f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2883f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2893f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public void onFlingToDeleteCompleted() { 2903f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // We just dismiss the drag when we fling, so cleanup here 2913f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.exitSpringLoadedDragModeDelayed(true, 2923f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null); 2933f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.unlockScreenOrientation(false); 2943f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2953f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2963f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2973f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete, 2983f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song boolean success) { 2993f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() && 3003f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song !(target instanceof DeleteDropTarget) && !(target instanceof Folder))) { 3013f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Exit spring loaded mode if we have not successfully dropped or have not handled the 3023f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // drop in Workspace 3033f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.exitSpringLoadedDragModeDelayed(true, 3043f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null); 3053f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3063f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.unlockScreenOrientation(false); 3073f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3083f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Display an error message if the drag failed due to there not being enough space on the 3093f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // target layout we were dropping on. 3103f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!success) { 3113f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song boolean showOutOfSpaceMessage = false; 3123f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (target instanceof Workspace) { 3133f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song int currentScreen = mLauncher.getCurrentWorkspaceScreen(); 3143f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Workspace workspace = (Workspace) target; 3153f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen); 3163f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song ItemInfo itemInfo = (ItemInfo) d.dragInfo; 3173f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (layout != null) { 3183f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song layout.calculateSpans(itemInfo); 3193f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song showOutOfSpaceMessage = 3203f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song !layout.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY); 3213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (showOutOfSpaceMessage) { 3243f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.showOutOfSpaceMessage(false); 3253f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3263f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song d.deferDragViewCleanupPostAnimation = false; 3273f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 328b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song //TODO(hyunyoungs): if drop fails, this call cleans up correctly. 329b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song // However, in rare corner case where drop succeeds but doesn't end up using the widget 330b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song // id created by the loader, this finish will leave dangling widget id. 331b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mWidgetHostViewLoader.finish(success); 3323f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3333f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3343f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 3353f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Container rendering related. 3363f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 3373f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3383f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 3399480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chung protected void onUpdatePaddings() { 3409480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chung if (mFixedBounds.isEmpty()) { 3419480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chung // If there are no fixed bounds, then use the default padding and insets 3429480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chung setPadding(mPadding.left + mInsets.left, mPadding.top + mInsets.top, 3439480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chung mPadding.right + mInsets.right, mPadding.bottom + mInsets.bottom); 3449480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chung } else { 3459480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chung // If there are fixed bounds, then we update the padding to reflect the fixed bounds. 3469480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chung setPadding(mFixedBounds.left, mFixedBounds.top, getMeasuredWidth() - mFixedBounds.right, 34713eb527b5ae7f564e3ace6137a8d466636d87188Winson Chung mFixedBounds.bottom); 3489480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chung } 3493f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3503f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /** 3523f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Initialize the widget data model. 3533f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */ 3542bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Song public void addWidgets(WidgetsModel model) { 355ac5f6af1488ec1cf0b73aa0848a675764c2f652bHyunyoung Song mView.setWidgets(model); 3562bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Song mAdapter.setWidgetsModel(model); 3572bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Song mAdapter.notifyDataSetChanged(); 3583f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3593f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3603f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private WidgetPreviewLoader getWidgetPreviewLoader() { 3613f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (mWidgetPreviewLoader == null) { 3623f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mWidgetPreviewLoader = LauncherAppState.getInstance().getWidgetCache(); 3633f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3643f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return mWidgetPreviewLoader; 3653f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3663f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song}