• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.launcher3;
18 
19 import static com.android.launcher3.LauncherState.ALL_APPS;
20 
21 import android.content.Context;
22 import android.graphics.Rect;
23 import android.graphics.drawable.Drawable;
24 import android.util.AttributeSet;
25 import android.view.Gravity;
26 import android.view.LayoutInflater;
27 import android.view.MotionEvent;
28 import android.view.View;
29 import android.view.ViewDebug;
30 import android.view.ViewGroup;
31 import android.widget.FrameLayout;
32 import android.widget.TextView;
33 
34 import com.android.launcher3.config.FeatureFlags;
35 import com.android.launcher3.logging.UserEventDispatcher.LogContainerProvider;
36 import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
37 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
38 import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
39 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
40 
41 public class Hotseat extends FrameLayout implements LogContainerProvider, Insettable {
42 
43     private final Launcher mLauncher;
44     private CellLayout mContent;
45 
46     @ViewDebug.ExportedProperty(category = "launcher")
47     private boolean mHasVerticalHotseat;
48 
Hotseat(Context context)49     public Hotseat(Context context) {
50         this(context, null);
51     }
52 
Hotseat(Context context, AttributeSet attrs)53     public Hotseat(Context context, AttributeSet attrs) {
54         this(context, attrs, 0);
55     }
56 
Hotseat(Context context, AttributeSet attrs, int defStyle)57     public Hotseat(Context context, AttributeSet attrs, int defStyle) {
58         super(context, attrs, defStyle);
59         mLauncher = Launcher.getLauncher(context);
60     }
61 
getLayout()62     public CellLayout getLayout() {
63         return mContent;
64     }
65 
66     /* Get the orientation invariant order of the item in the hotseat for persistence. */
getOrderInHotseat(int x, int y)67     int getOrderInHotseat(int x, int y) {
68         return mHasVerticalHotseat ? (mContent.getCountY() - y - 1) : x;
69     }
70 
71     /* Get the orientation specific coordinates given an invariant order in the hotseat. */
getCellXFromOrder(int rank)72     int getCellXFromOrder(int rank) {
73         return mHasVerticalHotseat ? 0 : rank;
74     }
75 
getCellYFromOrder(int rank)76     int getCellYFromOrder(int rank) {
77         return mHasVerticalHotseat ? (mContent.getCountY() - (rank + 1)) : 0;
78     }
79 
80     @Override
onFinishInflate()81     protected void onFinishInflate() {
82         super.onFinishInflate();
83         mContent = findViewById(R.id.layout);
84     }
85 
resetLayout(boolean hasVerticalHotseat)86     void resetLayout(boolean hasVerticalHotseat) {
87         mContent.removeAllViewsInLayout();
88         mHasVerticalHotseat = hasVerticalHotseat;
89         InvariantDeviceProfile idp = mLauncher.getDeviceProfile().inv;
90         if (hasVerticalHotseat) {
91             mContent.setGridSize(1, idp.numHotseatIcons);
92         } else {
93             mContent.setGridSize(idp.numHotseatIcons, 1);
94         }
95 
96         if (!FeatureFlags.NO_ALL_APPS_ICON) {
97             // Add the Apps button
98             Context context = getContext();
99             DeviceProfile grid = mLauncher.getDeviceProfile();
100             int allAppsButtonRank = grid.inv.getAllAppsButtonRank();
101 
102             LayoutInflater inflater = LayoutInflater.from(context);
103             TextView allAppsButton = (TextView)
104                     inflater.inflate(R.layout.all_apps_button, mContent, false);
105             Drawable d = context.getResources().getDrawable(R.drawable.all_apps_button_icon);
106             d.setBounds(0, 0, grid.iconSizePx, grid.iconSizePx);
107 
108             int scaleDownPx = getResources().getDimensionPixelSize(R.dimen.all_apps_button_scale_down);
109             Rect bounds = d.getBounds();
110             d.setBounds(bounds.left, bounds.top + scaleDownPx / 2, bounds.right - scaleDownPx,
111                     bounds.bottom - scaleDownPx / 2);
112             allAppsButton.setCompoundDrawables(null, d, null, null);
113 
114             allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
115             if (mLauncher != null) {
116                 allAppsButton.setOnClickListener((v) -> {
117                     if (!mLauncher.isInState(ALL_APPS)) {
118                         mLauncher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
119                                 ControlType.ALL_APPS_BUTTON);
120                         mLauncher.getStateManager().goToState(ALL_APPS);
121                     }
122                 });
123                 allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
124             }
125 
126             // Note: We do this to ensure that the hotseat is always laid out in the orientation of
127             // the hotseat in order regardless of which orientation they were added
128             int x = getCellXFromOrder(allAppsButtonRank);
129             int y = getCellYFromOrder(allAppsButtonRank);
130             CellLayout.LayoutParams lp = new CellLayout.LayoutParams(x, y, 1, 1);
131             lp.canReorder = false;
132             mContent.addViewToCellLayout(allAppsButton, -1, allAppsButton.getId(), lp, true);
133         }
134     }
135 
136     @Override
onInterceptTouchEvent(MotionEvent ev)137     public boolean onInterceptTouchEvent(MotionEvent ev) {
138         // We don't want any clicks to go through to the hotseat unless the workspace is in
139         // the normal state or an accessible drag is in progress.
140         return !mLauncher.getWorkspace().workspaceIconsCanBeDragged() &&
141                 !mLauncher.getAccessibilityDelegate().isInAccessibleDrag();
142     }
143 
144     @Override
fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent)145     public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) {
146         target.gridX = info.cellX;
147         target.gridY = info.cellY;
148         targetParent.containerType = ContainerType.HOTSEAT;
149     }
150 
151     @Override
setInsets(Rect insets)152     public void setInsets(Rect insets) {
153         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
154         DeviceProfile grid = mLauncher.getDeviceProfile();
155 
156         if (grid.isVerticalBarLayout()) {
157             lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
158             if (grid.isSeascape()) {
159                 lp.gravity = Gravity.LEFT;
160                 lp.width = grid.hotseatBarSizePx + insets.left + grid.hotseatBarSidePaddingPx;
161             } else {
162                 lp.gravity = Gravity.RIGHT;
163                 lp.width = grid.hotseatBarSizePx + insets.right + grid.hotseatBarSidePaddingPx;
164             }
165         } else {
166             lp.gravity = Gravity.BOTTOM;
167             lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
168             lp.height = grid.hotseatBarSizePx + insets.bottom;
169         }
170         Rect padding = grid.getHotseatLayoutPadding();
171         getLayout().setPadding(padding.left, padding.top, padding.right, padding.bottom);
172 
173         setLayoutParams(lp);
174         InsettableFrameLayout.dispatchInsets(this, insets);
175     }
176 }
177