1 /*
2  * Copyright (C) 2018 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.views;
17 
18 import android.content.Context;
19 import android.content.ContextWrapper;
20 import android.graphics.Rect;
21 import android.view.LayoutInflater;
22 import android.view.View;
23 import android.view.View.AccessibilityDelegate;
24 
25 import androidx.annotation.Nullable;
26 
27 import com.android.launcher3.DeviceProfile;
28 import com.android.launcher3.dot.DotInfo;
29 import com.android.launcher3.dragndrop.DragController;
30 import com.android.launcher3.folder.FolderIcon;
31 import com.android.launcher3.logger.LauncherAtom;
32 import com.android.launcher3.logging.StatsLogManager;
33 import com.android.launcher3.model.data.ItemInfo;
34 import com.android.launcher3.util.ViewCache;
35 
36 /**
37  * An interface to be used along with a context for various activities in Launcher. This allows a
38  * generic class to depend on Context subclass instead of an Activity.
39  */
40 public interface ActivityContext {
41 
finishAutoCancelActionMode()42     default boolean finishAutoCancelActionMode() {
43         return false;
44     }
45 
getDotInfoForItem(ItemInfo info)46     default DotInfo getDotInfoForItem(ItemInfo info) {
47         return null;
48     }
49 
50     /**
51      * For items with tree hierarchy, notifies the activity to invalidate the parent when a root
52      * is invalidated
53      * @param info info associated with a root node.
54      */
invalidateParent(ItemInfo info)55     default void invalidateParent(ItemInfo info) { }
56 
getAccessibilityDelegate()57     default AccessibilityDelegate getAccessibilityDelegate() {
58         return null;
59     }
60 
getFolderBoundingBox()61     default Rect getFolderBoundingBox() {
62         return getDeviceProfile().getAbsoluteOpenFolderBounds();
63     }
64 
65     /**
66      * After calling {@link #getFolderBoundingBox()}, we calculate a (left, top) position for a
67      * Folder of size width x height to be within those bounds. However, the chosen position may
68      * not be visually ideal (e.g. uncanny valley of centeredness), so here's a chance to update it.
69      * @param inOutPosition A 2-size array where the first element is the left position of the open
70      *     folder and the second element is the top position. Should be updated in place if desired.
71      * @param bounds The bounds that the open folder should fit inside.
72      * @param width The width of the open folder.
73      * @param height The height of the open folder.
74      */
updateOpenFolderPosition(int[] inOutPosition, Rect bounds, int width, int height)75     default void updateOpenFolderPosition(int[] inOutPosition, Rect bounds, int width, int height) {
76     }
77 
78     /**
79      * Returns a LayoutInflater that is cloned in this Context, so that Views inflated by it will
80      * have the same Context. (i.e. {@link #lookupContext(Context)} will find this ActivityContext.)
81      */
getLayoutInflater()82     default LayoutInflater getLayoutInflater() {
83         if (this instanceof Context) {
84             Context context = (Context) this;
85             return LayoutInflater.from(context).cloneInContext(context);
86         }
87         return null;
88     }
89 
90     /**
91      * The root view to support drag-and-drop and popup support.
92      */
getDragLayer()93     BaseDragLayer getDragLayer();
94 
getDeviceProfile()95     DeviceProfile getDeviceProfile();
96 
getViewCache()97     default ViewCache getViewCache() {
98         return new ViewCache();
99     }
100 
101     /**
102      * Controller for supporting item drag-and-drop
103      */
getDragController()104     default <T extends DragController> T getDragController() {
105         return null;
106     }
107 
108     /**
109      * Returns the FolderIcon with the given item id, if it exists.
110      */
findFolderIcon(final int folderIconId)111     default @Nullable FolderIcon findFolderIcon(final int folderIconId) {
112         return null;
113     }
114 
getStatsLogManager()115     default StatsLogManager getStatsLogManager() {
116         return StatsLogManager.newInstance((Context) this);
117     }
118 
119     /**
120      * Returns {@code true} if popups should use color extraction.
121      */
shouldUseColorExtractionForPopup()122     default boolean shouldUseColorExtractionForPopup() {
123         return true;
124     }
125 
126     /**
127      * Returns whether we can show the IME for elements hosted by this ActivityContext.
128      */
supportsIme()129     default boolean supportsIme() {
130         return true;
131     }
132 
133     /**
134      * Called just before logging the given item.
135      */
applyOverwritesToLogItem(LauncherAtom.ItemInfo.Builder itemInfoBuilder)136     default void applyOverwritesToLogItem(LauncherAtom.ItemInfo.Builder itemInfoBuilder) { }
137 
138     /**
139      * Returns the ActivityContext associated with the given Context, or throws an exception if
140      * the Context is not associated with any ActivityContext.
141      */
lookupContext(Context context)142     static <T extends Context & ActivityContext> T lookupContext(Context context) {
143         T activityContext = lookupContextNoThrow(context);
144         if (activityContext == null) {
145             throw new IllegalArgumentException("Cannot find ActivityContext in parent tree");
146         }
147         return activityContext;
148     }
149 
150     /**
151      * Returns the ActivityContext associated with the given Context, or null if
152      * the Context is not associated with any ActivityContext.
153      */
lookupContextNoThrow(Context context)154     static <T extends Context & ActivityContext> T lookupContextNoThrow(Context context) {
155         if (context instanceof ActivityContext) {
156             return (T) context;
157         } else if (context instanceof ContextWrapper) {
158             return lookupContextNoThrow(((ContextWrapper) context).getBaseContext());
159         } else {
160             return null;
161         }
162     }
163 
getItemOnClickListener()164     default View.OnClickListener getItemOnClickListener() {
165         return v -> {
166             // No op.
167         };
168     }
169 }
170