1 /*
2  * Copyright (C) 2017 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;
17 
18 import static com.android.launcher3.anim.Interpolators.ACCEL_2;
19 import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
20 import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
21 import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL;
22 import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
23 import static com.android.launcher3.testing.TestProtocol.OVERVIEW_MODAL_TASK_STATE_ORDINAL;
24 import static com.android.launcher3.testing.TestProtocol.OVERVIEW_PEEK_STATE_ORDINAL;
25 import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
26 import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
27 import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
28 
29 import android.content.Context;
30 import android.view.animation.Interpolator;
31 
32 import com.android.launcher3.statemanager.BaseState;
33 import com.android.launcher3.statemanager.StateManager;
34 import com.android.launcher3.states.HintState;
35 import com.android.launcher3.states.SpringLoadedState;
36 import com.android.launcher3.testing.TestProtocol;
37 import com.android.launcher3.uioverrides.states.AllAppsState;
38 import com.android.launcher3.uioverrides.states.OverviewState;
39 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
40 
41 import java.util.Arrays;
42 
43 /**
44  * Base state for various states used for the Launcher
45  */
46 public abstract class LauncherState implements BaseState<LauncherState> {
47 
48     /**
49      * Set of elements indicating various workspace elements which change visibility across states
50      * Note that workspace is not included here as in that case, we animate individual pages
51      */
52     public static final int NONE = 0;
53     public static final int HOTSEAT_ICONS = 1 << 0;
54     public static final int HOTSEAT_SEARCH_BOX = 1 << 1;
55     public static final int ALL_APPS_HEADER = 1 << 2;
56     public static final int ALL_APPS_HEADER_EXTRA = 1 << 3; // e.g. app predictions
57     public static final int ALL_APPS_CONTENT = 1 << 4;
58     public static final int VERTICAL_SWIPE_INDICATOR = 1 << 5;
59     public static final int OVERVIEW_BUTTONS = 1 << 6;
60 
61     /** Mask of all the items that are contained in the apps view. */
62     public static final int APPS_VIEW_ITEM_MASK =
63             HOTSEAT_SEARCH_BOX | ALL_APPS_HEADER | ALL_APPS_HEADER_EXTRA | ALL_APPS_CONTENT;
64 
65     // Flag indicating workspace has multiple pages visible.
66     public static final int FLAG_MULTI_PAGE = BaseState.getFlag(0);
67     // Flag indicating that workspace and its contents are not accessible
68     public static final int FLAG_WORKSPACE_INACCESSIBLE = BaseState.getFlag(1);
69 
70     // Flag indicating the state allows workspace icons to be dragged.
71     public static final int FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED = BaseState.getFlag(2);
72     // Flag to indicate that workspace should draw page background
73     public static final int FLAG_WORKSPACE_HAS_BACKGROUNDS = BaseState.getFlag(3);
74     // True if the back button should be hidden when in this state (assuming no floating views are
75     // open, launcher has window focus, etc).
76     public static final int FLAG_HIDE_BACK_BUTTON = BaseState.getFlag(4);
77     // Flag to indicate if the state would have scrim over sysui region: statu sbar and nav bar
78     public static final int FLAG_HAS_SYS_UI_SCRIM = BaseState.getFlag(5);
79     // Flag to inticate that all popups should be closed when this state is enabled.
80     public static final int FLAG_CLOSE_POPUPS = BaseState.getFlag(6);
81     public static final int FLAG_OVERVIEW_UI = BaseState.getFlag(7);
82 
83 
84     public static final float NO_OFFSET = 0;
85     public static final float NO_SCALE = 1;
86 
87     protected static final PageAlphaProvider DEFAULT_ALPHA_PROVIDER =
88             new PageAlphaProvider(ACCEL_2) {
89                 @Override
90                 public float getPageAlpha(int pageIndex) {
91                     return 1;
92                 }
93             };
94 
95     private static final LauncherState[] sAllStates = new LauncherState[9];
96 
97     /**
98      * TODO: Create a separate class for NORMAL state.
99      */
100     public static final LauncherState NORMAL = new LauncherState(NORMAL_STATE_ORDINAL,
101             ContainerType.WORKSPACE,
102             FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_HIDE_BACK_BUTTON |
103                     FLAG_HAS_SYS_UI_SCRIM) {
104         @Override
105         public int getTransitionDuration(Context context) {
106             // Arbitrary duration, when going to NORMAL we use the state we're coming from instead.
107             return 0;
108         }
109     };
110 
111     /**
112      * Various Launcher states arranged in the increasing order of UI layers
113      */
114     public static final LauncherState SPRING_LOADED = new SpringLoadedState(
115             SPRING_LOADED_STATE_ORDINAL);
116     public static final LauncherState ALL_APPS = new AllAppsState(ALL_APPS_STATE_ORDINAL);
117     public static final LauncherState HINT_STATE = new HintState(HINT_STATE_ORDINAL);
118 
119     public static final LauncherState OVERVIEW = new OverviewState(OVERVIEW_STATE_ORDINAL);
120     public static final LauncherState OVERVIEW_PEEK =
121             OverviewState.newPeekState(OVERVIEW_PEEK_STATE_ORDINAL);
122     public static final LauncherState OVERVIEW_MODAL_TASK = OverviewState.newModalTaskState(
123             OVERVIEW_MODAL_TASK_STATE_ORDINAL);
124     public static final LauncherState QUICK_SWITCH =
125             OverviewState.newSwitchState(QUICK_SWITCH_STATE_ORDINAL);
126     public static final LauncherState BACKGROUND_APP =
127             OverviewState.newBackgroundState(BACKGROUND_APP_STATE_ORDINAL);
128 
129     public final int ordinal;
130 
131     /**
132      * Used for containerType in {@link com.android.launcher3.logging.UserEventDispatcher}
133      */
134     public final int containerType;
135 
136     /**
137      * True if the state has overview panel visible.
138      */
139     public final boolean overviewUi;
140 
141     private final int mFlags;
142 
LauncherState(int id, int containerType, int flags)143     public LauncherState(int id, int containerType, int flags) {
144         this.containerType = containerType;
145         this.mFlags = flags;
146         this.overviewUi = (flags & FLAG_OVERVIEW_UI) != 0;
147         this.ordinal = id;
148         sAllStates[id] = this;
149     }
150 
151     /**
152      * Returns if the state has the provided flag
153      */
154     @Override
hasFlag(int mask)155     public final boolean hasFlag(int mask) {
156         return (mFlags & mask) != 0;
157     }
158 
values()159     public static LauncherState[] values() {
160         return Arrays.copyOf(sAllStates, sAllStates.length);
161     }
162 
getWorkspaceScaleAndTranslation(Launcher launcher)163     public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
164         return new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET);
165     }
166 
getHotseatScaleAndTranslation(Launcher launcher)167     public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) {
168         // For most states, treat the hotseat as if it were part of the workspace.
169         return getWorkspaceScaleAndTranslation(launcher);
170     }
171 
172     /**
173      * Returns an array of two elements.
174      *   The first specifies the scale for the overview
175      *   The second is the factor ([0, 1], 0 => center-screen; 1 => offscreen) by which overview
176      *   should be shifted horizontally.
177      */
getOverviewScaleAndOffset(Launcher launcher)178     public float[] getOverviewScaleAndOffset(Launcher launcher) {
179         return launcher.getNormalOverviewScaleAndOffset();
180     }
181 
getQsbScaleAndTranslation(Launcher launcher)182     public ScaleAndTranslation getQsbScaleAndTranslation(Launcher launcher) {
183         return new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET);
184     }
185 
getOverviewFullscreenProgress()186     public float getOverviewFullscreenProgress() {
187         return 0;
188     }
189 
getVisibleElements(Launcher launcher)190     public int getVisibleElements(Launcher launcher) {
191         if (launcher.getDeviceProfile().isVerticalBarLayout()) {
192             return HOTSEAT_ICONS | VERTICAL_SWIPE_INDICATOR;
193         }
194         return HOTSEAT_ICONS | HOTSEAT_SEARCH_BOX | VERTICAL_SWIPE_INDICATOR;
195     }
196 
197     /**
198      * Fraction shift in the vertical translation UI and related properties
199      *
200      * @see com.android.launcher3.allapps.AllAppsTransitionController
201      */
getVerticalProgress(Launcher launcher)202     public float getVerticalProgress(Launcher launcher) {
203         return 1f;
204     }
205 
getWorkspaceScrimAlpha(Launcher launcher)206     public float getWorkspaceScrimAlpha(Launcher launcher) {
207         return 0;
208     }
209 
getOverviewScrimAlpha(Launcher launcher)210     public float getOverviewScrimAlpha(Launcher launcher) {
211         return 0;
212     }
213 
214     /**
215      * For this state, how modal should over view been shown. 0 modalness means all tasks drawn,
216      * 1 modalness means the current task is show on its own.
217      */
getOverviewModalness()218     public float getOverviewModalness() {
219         return 0;
220     }
221 
222     /**
223      * The amount of blur and wallpaper zoom to apply to the background of either the app
224      * or Launcher surface in this state. Should be a number between 0 and 1, inclusive.
225      *
226      * 0 means completely zoomed in, without blurs. 1 is zoomed out, with blurs.
227      */
getDepth(Context context)228     public final float getDepth(Context context) {
229         return getDepth(context,
230                 BaseDraggingActivity.fromContext(context).getDeviceProfile().isMultiWindowMode);
231     }
232 
233     /**
234      * Returns the amount of blur and wallpaper zoom for this state with {@param isMultiWindowMode}.
235      * @see #getDepth(Context).
236      */
getDepth(Context context, boolean isMultiWindowMode)237     public final float getDepth(Context context, boolean isMultiWindowMode) {
238         if (isMultiWindowMode) {
239             return 0;
240         }
241         return getDepthUnchecked(context);
242     }
243 
getDepthUnchecked(Context context)244     protected float getDepthUnchecked(Context context) {
245         return 0f;
246     }
247 
getDescription(Launcher launcher)248     public String getDescription(Launcher launcher) {
249         return launcher.getWorkspace().getCurrentPageDescription();
250     }
251 
getWorkspacePageAlphaProvider(Launcher launcher)252     public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
253         if (this != NORMAL || !launcher.getDeviceProfile().shouldFadeAdjacentWorkspaceScreens()) {
254             return DEFAULT_ALPHA_PROVIDER;
255         }
256         final int centerPage = launcher.getWorkspace().getNextPage();
257         return new PageAlphaProvider(ACCEL_2) {
258             @Override
259             public float getPageAlpha(int pageIndex) {
260                 return  pageIndex != centerPage ? 0 : 1f;
261             }
262         };
263     }
264 
265     @Override
266     public LauncherState getHistoryForState(LauncherState previousState) {
267         // No history is supported
268         return NORMAL;
269     }
270 
271     @Override
272     public String toString() {
273         return TestProtocol.stateOrdinalToString(ordinal);
274     }
275 
276     public void onBackPressed(Launcher launcher) {
277         if (this != NORMAL) {
278             StateManager<LauncherState> lsm = launcher.getStateManager();
279             LauncherState lastState = lsm.getLastState();
280             lsm.goToState(lastState);
281         }
282     }
283 
284     public static abstract class PageAlphaProvider {
285 
286         public final Interpolator interpolator;
287 
288         public PageAlphaProvider(Interpolator interpolator) {
289             this.interpolator = interpolator;
290         }
291 
292         public abstract float getPageAlpha(int pageIndex);
293     }
294 
295     public static class ScaleAndTranslation {
296         public float scale;
297         public float translationX;
298         public float translationY;
299 
300         public ScaleAndTranslation(float scale, float translationX, float translationY) {
301             this.scale = scale;
302             this.translationX = translationX;
303             this.translationY = translationY;
304         }
305     }
306 }
307