WidgetsContainerView.java revision 06e21a25877db7207b5393ab163028bb4116df4f
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; 24e809332032c8f0c2f361eb8fc753f3b57d9cfaaaHyunyoung Songimport android.support.v7.widget.RecyclerView.State; 253f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.util.AttributeSet; 263f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.util.Log; 273f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.view.View; 289600d20110861db08f0db21358161dc0ae6b2037Sunny Goyalimport android.view.ViewGroup; 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; 343f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.DragSource; 353f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.DropTarget.DragObject; 36261194387beebaa7927ec4e310274218b651494dSunny Goyalimport com.android.launcher3.folder.Folder; 373f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.IconCache; 383f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.ItemInfo; 393f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.Launcher; 403f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.LauncherAppState; 413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.PendingAddItemInfo; 423f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.R; 433f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.Utilities; 443f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.WidgetPreviewLoader; 453f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.Workspace; 46fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.dragndrop.DragController; 4758376925f9596c23f5c9ffa6c99630dfddcfce9cSunny Goyalimport com.android.launcher3.model.WidgetsModel; 48316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyalimport com.android.launcher3.util.Thunk; 493f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 503f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song/** 513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * The widgets list view container. 523f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */ 539480415d9baf00ecfaac8ab3f608b16a1faa6518Winson Chungpublic class WidgetsContainerView extends BaseContainerView 54a0628cc521614835933db74ba5a2536a936629c5Tony Wickham implements View.OnLongClickListener, View.OnClickListener, DragSource { 55b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song private static final String TAG = "WidgetsContainerView"; 56a0628cc521614835933db74ba5a2536a936629c5Tony Wickham private static final boolean LOGD = false; 573f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 583f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* Global instances that are used inside this container. */ 59316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal @Thunk Launcher mLauncher; 603f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private DragController mDragController; 613f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private IconCache mIconCache; 623f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 631f06427266c0cb5de4561fc7c620ff542f625300Winson private final Rect mTmpBgPaddingRect = new Rect(); 641f06427266c0cb5de4561fc7c620ff542f625300Winson private final Rect mTmpRect = new Rect(); 651f06427266c0cb5de4561fc7c620ff542f625300Winson 663f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* Recycler view related member variables */ 67a6194d3d9205488d6f5400193f8d4d6aaf140218Sunny Goyal private WidgetsRecyclerView mRecyclerView; 683f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private WidgetsListAdapter mAdapter; 693f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 70b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song /* Touch handling related member variables. */ 71b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song private Toast mWidgetInstructionToast; 723f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 733f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* Rendering related. */ 743f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private WidgetPreviewLoader mWidgetPreviewLoader; 75b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 763f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public WidgetsContainerView(Context context) { 773f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song this(context, null); 783f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 793f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 803f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public WidgetsContainerView(Context context, AttributeSet attrs) { 813f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song this(context, attrs, 0); 823f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 833f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 843f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public WidgetsContainerView(Context context, AttributeSet attrs, int defStyleAttr) { 853f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song super(context, attrs, defStyleAttr); 86abef55a1c1f1fda4f42e4b4223534dd21f3dc19fAndrew Sapperstein mLauncher = Launcher.getLauncher(context); 873f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mDragController = mLauncher.getDragController(); 88abef55a1c1f1fda4f42e4b4223534dd21f3dc19fAndrew Sapperstein mAdapter = new WidgetsListAdapter(this, this, context); 893f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mIconCache = (LauncherAppState.getInstance()).getIconCache(); 90a0628cc521614835933db74ba5a2536a936629c5Tony Wickham if (LOGD) { 913f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.d(TAG, "WidgetsContainerView constructor"); 923f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 933f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 943f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 953f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 963f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song protected void onFinishInflate() { 97a0628cc521614835933db74ba5a2536a936629c5Tony Wickham super.onFinishInflate(); 98a6194d3d9205488d6f5400193f8d4d6aaf140218Sunny Goyal mRecyclerView = (WidgetsRecyclerView) getContentView().findViewById(R.id.widgets_list_view); 99a6194d3d9205488d6f5400193f8d4d6aaf140218Sunny Goyal mRecyclerView.setAdapter(mAdapter); 100b7271fd17ea78acbf8506b2c9a34f741680fc4a9Hyunyoung Song mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); 1011f06427266c0cb5de4561fc7c620ff542f625300Winson } 10205c8c57fa72a81f34058036f6dc30c084ca6742bSunny Goyal 1031f06427266c0cb5de4561fc7c620ff542f625300Winson @Override 1041f06427266c0cb5de4561fc7c620ff542f625300Winson protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 1051f06427266c0cb5de4561fc7c620ff542f625300Winson getRevealView().getBackground().getPadding(mTmpBgPaddingRect); 10605c8c57fa72a81f34058036f6dc30c084ca6742bSunny Goyal if (Utilities.isRtl(getResources())) { 1071f06427266c0cb5de4561fc7c620ff542f625300Winson getContentView().setPadding(0, mTmpBgPaddingRect.top, mTmpBgPaddingRect.right, 1081f06427266c0cb5de4561fc7c620ff542f625300Winson mTmpBgPaddingRect.bottom); 1091f06427266c0cb5de4561fc7c620ff542f625300Winson mTmpRect.set(mTmpBgPaddingRect.left, 0, 0, 0); 1101f06427266c0cb5de4561fc7c620ff542f625300Winson mRecyclerView.updateBackgroundPadding(mTmpRect); 11105c8c57fa72a81f34058036f6dc30c084ca6742bSunny Goyal } else { 1121f06427266c0cb5de4561fc7c620ff542f625300Winson getContentView().setPadding(mTmpBgPaddingRect.left, mTmpBgPaddingRect.top, 0, 1131f06427266c0cb5de4561fc7c620ff542f625300Winson mTmpBgPaddingRect.bottom); 1141f06427266c0cb5de4561fc7c620ff542f625300Winson mTmpRect.set(0, 0, mTmpBgPaddingRect.right, 0); 1151f06427266c0cb5de4561fc7c620ff542f625300Winson mRecyclerView.updateBackgroundPadding(mTmpRect); 11605c8c57fa72a81f34058036f6dc30c084ca6742bSunny Goyal } 1171f06427266c0cb5de4561fc7c620ff542f625300Winson 1181f06427266c0cb5de4561fc7c620ff542f625300Winson super.onMeasure(widthMeasureSpec, heightMeasureSpec); 1193f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1203f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 1223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Returns views used for launcher transitions. 1233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 1243f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1253f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public void scrollToTop() { 126a6194d3d9205488d6f5400193f8d4d6aaf140218Sunny Goyal mRecyclerView.scrollToPosition(0); 1273f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1283f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1293f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 1303f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Touch related handling. 1313f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 1323f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1333f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 134b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song public void onClick(View v) { 135b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song // When we have exited widget tray or are in transition, disregard clicks 136b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song if (!mLauncher.isWidgetsViewVisible() 137b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song || mLauncher.getWorkspace().isSwitchingState() 138b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song || !(v instanceof WidgetCell)) return; 139b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 140b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song // Let the user know that they have to long press to add a widget 141b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song if (mWidgetInstructionToast != null) { 142b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mWidgetInstructionToast.cancel(); 143b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 144e78e3d734b577c1ab6dc0738a83600374908ea52Sunny Goyal 145e78e3d734b577c1ab6dc0738a83600374908ea52Sunny Goyal CharSequence msg = Utilities.wrapForTts( 146e78e3d734b577c1ab6dc0738a83600374908ea52Sunny Goyal getContext().getText(R.string.long_press_widget_to_add), 147e78e3d734b577c1ab6dc0738a83600374908ea52Sunny Goyal getContext().getString(R.string.long_accessible_way_to_add)); 148e78e3d734b577c1ab6dc0738a83600374908ea52Sunny Goyal mWidgetInstructionToast = Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT); 149b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song mWidgetInstructionToast.show(); 150b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 151b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song 152b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song @Override 1533f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean onLongClick(View v) { 154a0628cc521614835933db74ba5a2536a936629c5Tony Wickham if (LOGD) { 1553f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.d(TAG, String.format("onLonglick [v=%s]", v)); 1563f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1573f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Return early if this is not initiated from a touch 1583f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!v.isInTouchMode()) return false; 1593f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // When we have exited all apps or are in transition, disregard long clicks 1603f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!mLauncher.isWidgetsViewVisible() || 1613f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.getWorkspace().isSwitchingState()) return false; 1623f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Return if global dragging is not enabled 1633f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!mLauncher.isDraggingEnabled()) return false; 1643f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 165b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song boolean status = beginDragging(v); 1665b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal if (status && v.getTag() instanceof PendingAddWidgetInfo) { 1675b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal WidgetHostViewLoader hostLoader = new WidgetHostViewLoader(mLauncher, v); 1685b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal boolean preloadStatus = hostLoader.preloadWidget(); 169a0628cc521614835933db74ba5a2536a936629c5Tony Wickham if (LOGD) { 1705b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal Log.d(TAG, String.format("preloading widget [status=%s]", preloadStatus)); 1715b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal } 1725b9ebcab3c6c55dcb7575fdbcb77020a5ad274d4Sunny Goyal mLauncher.getDragController().addDragListener(hostLoader); 173b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song } 174b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song return status; 1753f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1763f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1773f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private boolean beginDragging(View v) { 1783f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (v instanceof WidgetCell) { 1793f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!beginDraggingWidget((WidgetCell) v)) { 1803f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return false; 1813f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1823f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } else { 1833f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Log.e(TAG, "Unexpected dragging view: " + v); 1843f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1853f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 18658376925f9596c23f5c9ffa6c99630dfddcfce9cSunny Goyal // We don't enter spring-loaded mode if the drag has been cancelled 18758376925f9596c23f5c9ffa6c99630dfddcfce9cSunny Goyal if (mLauncher.getDragController().isDragging()) { 18858376925f9596c23f5c9ffa6c99630dfddcfce9cSunny Goyal // Go into spring loaded mode (must happen before we startDrag()) 18958376925f9596c23f5c9ffa6c99630dfddcfce9cSunny Goyal mLauncher.enterSpringLoadedDragMode(); 19058376925f9596c23f5c9ffa6c99630dfddcfce9cSunny Goyal } 1913f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1923f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return true; 1933f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 1943f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 1953f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private boolean beginDraggingWidget(WidgetCell v) { 1963f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Get the widget preview as the drag representation 197f52abd7758b8f245522936e941336e574debabf5Sunny Goyal WidgetImageView image = (WidgetImageView) v.findViewById(R.id.widget_preview); 1983f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag(); 1993f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2003f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and 2013f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // we abort the drag. 202f52abd7758b8f245522936e941336e574debabf5Sunny Goyal if (image.getBitmap() == null) { 2033f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return false; 2043f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2053f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2063f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Compose the drag image 2073f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Bitmap preview; 20806e21a25877db7207b5393ab163028bb4116df4fSunny Goyal final float scale; 209f52abd7758b8f245522936e941336e574debabf5Sunny Goyal final Rect bounds = image.getBitmapBounds(); 2103f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2113f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (createItemInfo instanceof PendingAddWidgetInfo) { 2123f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // This can happen in some weird cases involving multi-touch. We can't start dragging 2133f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // the widget if this is null, so we break out. 2143f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2153f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) createItemInfo; 2163f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song int[] size = mLauncher.getWorkspace().estimateItemSize(createWidgetInfo, true); 2173f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 218f52abd7758b8f245522936e941336e574debabf5Sunny Goyal Bitmap icon = image.getBitmap(); 2193f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song float minScale = 1.25f; 220f52abd7758b8f245522936e941336e574debabf5Sunny Goyal int maxWidth = Math.min((int) (icon.getWidth() * minScale), size[0]); 2213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song int[] previewSizeBeforeScale = new int[1]; 2232e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen preview = getWidgetPreviewLoader().generateWidgetPreview(mLauncher, 2242e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen createWidgetInfo.info, maxWidth, null, previewSizeBeforeScale); 225f52abd7758b8f245522936e941336e574debabf5Sunny Goyal 226f52abd7758b8f245522936e941336e574debabf5Sunny Goyal if (previewSizeBeforeScale[0] < icon.getWidth()) { 227f52abd7758b8f245522936e941336e574debabf5Sunny Goyal // The icon has extra padding around it. 228f52abd7758b8f245522936e941336e574debabf5Sunny Goyal int padding = (icon.getWidth() - previewSizeBeforeScale[0]) / 2; 229f52abd7758b8f245522936e941336e574debabf5Sunny Goyal if (icon.getWidth() > image.getWidth()) { 230f52abd7758b8f245522936e941336e574debabf5Sunny Goyal padding = padding * image.getWidth() / icon.getWidth(); 231f52abd7758b8f245522936e941336e574debabf5Sunny Goyal } 232f52abd7758b8f245522936e941336e574debabf5Sunny Goyal 233f52abd7758b8f245522936e941336e574debabf5Sunny Goyal bounds.left += padding; 234f52abd7758b8f245522936e941336e574debabf5Sunny Goyal bounds.right -= padding; 2353f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 236f52abd7758b8f245522936e941336e574debabf5Sunny Goyal scale = bounds.width() / (float) preview.getWidth(); 2373f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } else { 2383f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag(); 2393f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Drawable icon = mIconCache.getFullResIcon(createShortcutInfo.activityInfo); 2403f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song preview = Utilities.createIconBitmap(icon, mLauncher); 2413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song createItemInfo.spanX = createItemInfo.spanY = 1; 24253d7ee4285842732517edcccbdcaa92dccb1e107Sunny Goyal scale = ((float) mLauncher.getDeviceProfile().iconSizePx) / preview.getWidth(); 2433f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2443f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 24506e21a25877db7207b5393ab163028bb4116df4fSunny Goyal // Since we are not going through the workspace for starting the drag, set drag related 24606e21a25877db7207b5393ab163028bb4116df4fSunny Goyal // information on the workspace before starting the drag. 24706e21a25877db7207b5393ab163028bb4116df4fSunny Goyal mLauncher.getWorkspace().prepareDragWithProvider( 24806e21a25877db7207b5393ab163028bb4116df4fSunny Goyal new PendingItemPreviewProvider(v, createItemInfo, preview)); 2493f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2503f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Start the drag 2513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mDragController.startDrag(image, preview, this, createItemInfo, 252f52abd7758b8f245522936e941336e574debabf5Sunny Goyal bounds, DragController.DRAG_ACTION_COPY, scale); 2533f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return true; 2543f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2553f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2563f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 2573f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Drag related handling methods that implement {@link DragSource} interface. 2583f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // 2593f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2603f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2613f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean supportsFlingToDelete() { 2629aae47f8a6e23f1805ee3d44512fc1f80286e6ddTony Wickham return true; 2633f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2643f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2653f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2663f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean supportsAppInfoDropTarget() { 2673f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return true; 2683f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2693f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2703f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /* 2713f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Both this method and {@link #supportsFlingToDelete} has to return {@code false} for the 2723f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * {@link DeleteDropTarget} to be invisible.) 2733f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */ 2743f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2753f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public boolean supportsDeleteDropTarget() { 2763f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return false; 2773f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2783f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2793f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2803f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public float getIntrinsicIconScaleFactor() { 2813f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return 0; 2823f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2833f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2843f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2853f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public void onFlingToDeleteCompleted() { 2863f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // We just dismiss the drag when we fling, so cleanup here 2873f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.exitSpringLoadedDragModeDelayed(true, 2883f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null); 2893f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.unlockScreenOrientation(false); 2903f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 2913f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 2923f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song @Override 2933f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete, 2943f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song boolean success) { 295a0628cc521614835933db74ba5a2536a936629c5Tony Wickham if (LOGD) { 296a0628cc521614835933db74ba5a2536a936629c5Tony Wickham Log.d(TAG, "onDropCompleted"); 297a0628cc521614835933db74ba5a2536a936629c5Tony Wickham } 2983f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() && 2993f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song !(target instanceof DeleteDropTarget) && !(target instanceof Folder))) { 3003f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Exit spring loaded mode if we have not successfully dropped or have not handled the 3013f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // drop in Workspace 3023f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.exitSpringLoadedDragModeDelayed(true, 3033f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null); 3043f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3053f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.unlockScreenOrientation(false); 3063f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3073f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // Display an error message if the drag failed due to there not being enough space on the 3083f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song // target layout we were dropping on. 3093f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (!success) { 3103f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song boolean showOutOfSpaceMessage = false; 3113f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (target instanceof Workspace) { 3123f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song int currentScreen = mLauncher.getCurrentWorkspaceScreen(); 3133f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song Workspace workspace = (Workspace) target; 3143f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen); 315aa8ef119f18864f4ab41c12f9c2ad6d7f643a0a9Sunny Goyal ItemInfo itemInfo = d.dragInfo; 3163f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (layout != null) { 3173f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song showOutOfSpaceMessage = 3183f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song !layout.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY); 3193f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3203f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (showOutOfSpaceMessage) { 3223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mLauncher.showOutOfSpaceMessage(false); 3233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3243f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song d.deferDragViewCleanupPostAnimation = false; 3253f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3263f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3273f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3283f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song /** 3293f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Initialize the widget data model. 3303f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */ 3312bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Song public void addWidgets(WidgetsModel model) { 332a6194d3d9205488d6f5400193f8d4d6aaf140218Sunny Goyal mRecyclerView.setWidgets(model); 3332bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Song mAdapter.setWidgetsModel(model); 3342bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Song mAdapter.notifyDataSetChanged(); 3359600d20110861db08f0db21358161dc0ae6b2037Sunny Goyal 3369600d20110861db08f0db21358161dc0ae6b2037Sunny Goyal View loader = getContentView().findViewById(R.id.loader); 3379600d20110861db08f0db21358161dc0ae6b2037Sunny Goyal if (loader != null) { 3389600d20110861db08f0db21358161dc0ae6b2037Sunny Goyal ((ViewGroup) getContentView()).removeView(loader); 3399600d20110861db08f0db21358161dc0ae6b2037Sunny Goyal } 3403f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song 3422e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal public boolean isEmpty() { 3432e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal return mAdapter.getItemCount() == 0; 3442e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal } 3452e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal 3463f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song private WidgetPreviewLoader getWidgetPreviewLoader() { 3473f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song if (mWidgetPreviewLoader == null) { 3483f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song mWidgetPreviewLoader = LauncherAppState.getInstance().getWidgetCache(); 3493f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3503f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song return mWidgetPreviewLoader; 3513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song } 3523f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song}