• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.launcher3.secondarydisplay;
17 
18 import static android.view.View.MeasureSpec.EXACTLY;
19 import static android.view.View.MeasureSpec.makeMeasureSpec;
20 
21 import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
22 
23 import android.content.Context;
24 import android.util.AttributeSet;
25 import android.view.MotionEvent;
26 import android.view.View;
27 import android.widget.GridView;
28 
29 import com.android.launcher3.AbstractFloatingView;
30 import com.android.launcher3.BubbleTextView;
31 import com.android.launcher3.DeviceProfile;
32 import com.android.launcher3.R;
33 import com.android.launcher3.allapps.AllAppsContainerView;
34 import com.android.launcher3.model.data.ItemInfo;
35 import com.android.launcher3.popup.PopupContainerWithArrow;
36 import com.android.launcher3.util.ShortcutUtil;
37 import com.android.launcher3.util.TouchController;
38 import com.android.launcher3.views.BaseDragLayer;
39 
40 import java.util.Arrays;
41 import java.util.Collections;
42 
43 /**
44  * DragLayer for Secondary launcher
45  */
46 public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher> {
47 
48     private View mAllAppsButton;
49     private AllAppsContainerView mAppsView;
50 
51     private GridView mWorkspace;
52     private PinnedAppsAdapter mPinnedAppsAdapter;
53 
SecondaryDragLayer(Context context, AttributeSet attrs)54     public SecondaryDragLayer(Context context, AttributeSet attrs) {
55         super(context, attrs, 1 /* alphaChannelCount */);
56         recreateControllers();
57     }
58 
59     @Override
recreateControllers()60     public void recreateControllers() {
61         mControllers = new TouchController[] {new CloseAllAppsTouchController()};
62     }
63 
64     /**
65      * {@inheritDoc}
66      */
67     @Override
onFinishInflate()68     protected void onFinishInflate() {
69         super.onFinishInflate();
70         mAllAppsButton = findViewById(R.id.all_apps_button);
71 
72         mAppsView = findViewById(R.id.apps_view);
73         mAppsView.setOnIconLongClickListener(this::onIconLongClicked);
74 
75         // Setup workspace
76         mWorkspace = findViewById(R.id.workspace_grid);
77         mPinnedAppsAdapter = new PinnedAppsAdapter(mActivity, mAppsView.getAppsStore(),
78                 this::onIconLongClicked);
79         mWorkspace.setAdapter(mPinnedAppsAdapter);
80         mWorkspace.setNumColumns(mActivity.getDeviceProfile().inv.numColumns);
81     }
82 
83     /**
84      * {@inheritDoc}
85      */
86     @Override
onAttachedToWindow()87     protected void onAttachedToWindow() {
88         super.onAttachedToWindow();
89         mPinnedAppsAdapter.init();
90     }
91 
92     /**
93      * {@inheritDoc}
94      */
95     @Override
onDetachedFromWindow()96     protected void onDetachedFromWindow() {
97         super.onDetachedFromWindow();
98         mPinnedAppsAdapter.destroy();
99     }
100 
101     /**
102      * {@inheritDoc}
103      */
104     @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)105     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
106         int width = MeasureSpec.getSize(widthMeasureSpec);
107         int height = MeasureSpec.getSize(heightMeasureSpec);
108         setMeasuredDimension(width, height);
109 
110         DeviceProfile grid = mActivity.getDeviceProfile();
111         int count = getChildCount();
112         for (int i = 0; i < count; i++) {
113             final View child = getChildAt(i);
114             if (child == mAppsView) {
115                 int padding = 2 * (grid.desiredWorkspaceLeftRightMarginPx
116                         + grid.cellLayoutPaddingLeftRightPx);
117 
118                 int maxWidth = grid.allAppsCellWidthPx * grid.numShownAllAppsColumns + padding;
119                 int appsWidth = Math.min(width, maxWidth);
120 
121                 int maxHeight = grid.allAppsCellHeightPx * grid.numShownAllAppsColumns + padding;
122                 int appsHeight = Math.min(height, maxHeight);
123 
124                 mAppsView.measure(
125                         makeMeasureSpec(appsWidth, EXACTLY), makeMeasureSpec(appsHeight, EXACTLY));
126 
127             } else if (child == mAllAppsButton) {
128                 int appsButtonSpec = makeMeasureSpec(grid.iconSizePx, EXACTLY);
129                 mAllAppsButton.measure(appsButtonSpec, appsButtonSpec);
130 
131             } else if (child == mWorkspace) {
132                 measureChildWithMargins(mWorkspace, widthMeasureSpec, 0, heightMeasureSpec,
133                         grid.iconSizePx + grid.edgeMarginPx);
134 
135             } else {
136                 measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
137             }
138         }
139     }
140 
141     private class CloseAllAppsTouchController implements TouchController {
142 
143         @Override
onControllerTouchEvent(MotionEvent ev)144         public boolean onControllerTouchEvent(MotionEvent ev) {
145             return false;
146         }
147 
148         @Override
onControllerInterceptTouchEvent(MotionEvent ev)149         public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
150             if (!mActivity.isAppDrawerShown()) {
151                 return false;
152             }
153 
154             if (AbstractFloatingView.getTopOpenView(mActivity) != null) {
155                 return false;
156             }
157 
158             if (ev.getAction() == MotionEvent.ACTION_DOWN
159                     && !isEventOverView(mActivity.getAppsView(), ev)) {
160                 mActivity.showAppDrawer(false);
161                 return true;
162             }
163             return false;
164         }
165     }
166 
onIconLongClicked(View v)167     private boolean onIconLongClicked(View v) {
168         if (!(v instanceof BubbleTextView)) {
169             return false;
170         }
171         if (PopupContainerWithArrow.getOpen(mActivity) != null) {
172             // There is already an items container open, so don't open this one.
173             v.clearFocus();
174             return false;
175         }
176         ItemInfo item = (ItemInfo) v.getTag();
177         if (!ShortcutUtil.supportsShortcuts(item)) {
178             return false;
179         }
180         final PopupContainerWithArrow container =
181                 (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate(
182                         R.layout.popup_container, mActivity.getDragLayer(), false);
183 
184         container.populateAndShow((BubbleTextView) v,
185                 mActivity.getPopupDataProvider().getShortcutCountForItem(item),
186                 Collections.emptyList(),
187                 Arrays.asList(mPinnedAppsAdapter.getSystemShortcut(item),
188                         APP_INFO.getShortcut(mActivity, item)));
189         v.getParent().requestDisallowInterceptTouchEvent(true);
190         return true;
191     }
192 }
193