1b38002419dcb456b51f5d320b224737f16a07088Winson Chung/*
2b38002419dcb456b51f5d320b224737f16a07088Winson Chung * Copyright (C) 2008 The Android Open Source Project
3b38002419dcb456b51f5d320b224737f16a07088Winson Chung *
4b38002419dcb456b51f5d320b224737f16a07088Winson Chung * Licensed under the Apache License, Version 2.0 (the "License");
5b38002419dcb456b51f5d320b224737f16a07088Winson Chung * you may not use this file except in compliance with the License.
6b38002419dcb456b51f5d320b224737f16a07088Winson Chung * You may obtain a copy of the License at
7b38002419dcb456b51f5d320b224737f16a07088Winson Chung *
8b38002419dcb456b51f5d320b224737f16a07088Winson Chung *      http://www.apache.org/licenses/LICENSE-2.0
9b38002419dcb456b51f5d320b224737f16a07088Winson Chung *
10b38002419dcb456b51f5d320b224737f16a07088Winson Chung * Unless required by applicable law or agreed to in writing, software
11b38002419dcb456b51f5d320b224737f16a07088Winson Chung * distributed under the License is distributed on an "AS IS" BASIS,
12b38002419dcb456b51f5d320b224737f16a07088Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b38002419dcb456b51f5d320b224737f16a07088Winson Chung * See the License for the specific language governing permissions and
14b38002419dcb456b51f5d320b224737f16a07088Winson Chung * limitations under the License.
15b38002419dcb456b51f5d320b224737f16a07088Winson Chung */
16b38002419dcb456b51f5d320b224737f16a07088Winson Chung
17b38002419dcb456b51f5d320b224737f16a07088Winson Chungpackage com.android.launcher3;
18b38002419dcb456b51f5d320b224737f16a07088Winson Chung
19b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.appwidget.AppWidgetHostView;
20b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.content.ComponentName;
21b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.content.Context;
22b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.content.res.Resources;
23b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.graphics.Paint;
24b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.graphics.Paint.FontMetrics;
25b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.graphics.Point;
26b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.graphics.Rect;
27b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.util.DisplayMetrics;
28b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.view.Gravity;
29b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.view.View;
30d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggiimport android.view.ViewGroup;
31b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.view.ViewGroup.LayoutParams;
328dfe2da6985d38f23fd3426101574c093f509907Sunny Goyalimport android.view.ViewGroup.MarginLayoutParams;
33b38002419dcb456b51f5d320b224737f16a07088Winson Chungimport android.widget.FrameLayout;
3424ce0b3708b44e738d6ee52477aa4dd917b547e7Adam Cohenimport android.widget.LinearLayout;
35b38002419dcb456b51f5d320b224737f16a07088Winson Chung
36b38002419dcb456b51f5d320b224737f16a07088Winson Chungpublic class DeviceProfile {
372e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen
382e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen    public final InvariantDeviceProfile inv;
39b38002419dcb456b51f5d320b224737f16a07088Winson Chung
40c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    // Device properties
41c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final boolean isTablet;
42c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final boolean isLargeTablet;
43c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final boolean isPhone;
44c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final boolean transposeLayoutWithOrientation;
45c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal
46c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    // Device properties in current orientation
47c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final boolean isLandscape;
48c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final int widthPx;
49c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final int heightPx;
50c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final int availableWidthPx;
51c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final int availableHeightPx;
52c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal
53c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    // Overview mode
54c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private final int overviewModeMinIconZoneHeightPx;
55c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private final int overviewModeMaxIconZoneHeightPx;
56c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private final int overviewModeBarItemWidthPx;
57c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private final int overviewModeBarSpacerWidthPx;
58c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private final float overviewModeIconZoneRatio;
59c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal
60c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    // Workspace
61c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private int desiredWorkspaceLeftRightMarginPx;
62c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final int edgeMarginPx;
63c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final Rect defaultWidgetPadding;
64c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private final int pageIndicatorHeightPx;
65c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private final int defaultPageSpacingPx;
66c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private float dragViewScale;
67c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal
68c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    // Workspace icons
69c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public int iconSizePx;
702e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen    public int iconTextSizePx;
71c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public int iconDrawablePaddingPx;
725f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung    public int iconDrawablePaddingOriginalPx;
7359a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung
74c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public int cellWidthPx;
75c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public int cellHeightPx;
76fee35bbfac29a55382880f846fff86003e615ccbSunny Goyal
77c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    // Folder
78c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public int folderBackgroundOffset;
79c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public int folderIconSizePx;
80c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public int folderCellWidthPx;
81c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public int folderCellHeightPx;
82c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal
83c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    // Hotseat
84c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public int hotseatCellWidthPx;
85c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public int hotseatCellHeightPx;
86c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public int hotseatIconSizePx;
87c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private int hotseatBarHeightPx;
88c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal
89c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    // All apps
905f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung    public int allAppsNumCols;
915f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung    public int allAppsNumPredictiveCols;
92c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public int allAppsButtonVisualSize;
93c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final int allAppsIconSizePx;
94c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public final int allAppsIconTextSizePx;
95c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal
96c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    // QSB
97c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private int searchBarSpaceWidthPx;
98c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private int searchBarSpaceHeightPx;
99c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal
100c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public DeviceProfile(Context context, InvariantDeviceProfile inv,
101c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal            Point minSize, Point maxSize,
102c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal            int width, int height, boolean isLandscape) {
103fee35bbfac29a55382880f846fff86003e615ccbSunny Goyal
1042e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        this.inv = inv;
105c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        this.isLandscape = isLandscape;
106b38002419dcb456b51f5d320b224737f16a07088Winson Chung
1072e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        Resources res = context.getResources();
108b38002419dcb456b51f5d320b224737f16a07088Winson Chung        DisplayMetrics dm = res.getDisplayMetrics();
1092e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen
110c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        // Constants from resources
111c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        isTablet = res.getBoolean(R.bool.is_tablet);
112c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        isLargeTablet = res.getBoolean(R.bool.is_large_tablet);
113c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        isPhone = !isTablet && !isLargeTablet;
114c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal
115c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        // Some more constants
116b38002419dcb456b51f5d320b224737f16a07088Winson Chung        transposeLayoutWithOrientation =
117b38002419dcb456b51f5d320b224737f16a07088Winson Chung                res.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
118b38002419dcb456b51f5d320b224737f16a07088Winson Chung
119b38002419dcb456b51f5d320b224737f16a07088Winson Chung        ComponentName cn = new ComponentName(context.getPackageName(),
120b38002419dcb456b51f5d320b224737f16a07088Winson Chung                this.getClass().getName());
121b38002419dcb456b51f5d320b224737f16a07088Winson Chung        defaultWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context, cn, null);
122b38002419dcb456b51f5d320b224737f16a07088Winson Chung        edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
123b38002419dcb456b51f5d320b224737f16a07088Winson Chung        desiredWorkspaceLeftRightMarginPx = 2 * edgeMarginPx;
124b38002419dcb456b51f5d320b224737f16a07088Winson Chung        pageIndicatorHeightPx =
125b38002419dcb456b51f5d320b224737f16a07088Winson Chung                res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height);
126b38002419dcb456b51f5d320b224737f16a07088Winson Chung        defaultPageSpacingPx =
127b38002419dcb456b51f5d320b224737f16a07088Winson Chung                res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_page_spacing);
128b38002419dcb456b51f5d320b224737f16a07088Winson Chung        overviewModeMinIconZoneHeightPx =
129b38002419dcb456b51f5d320b224737f16a07088Winson Chung                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_min_icon_zone_height);
130b38002419dcb456b51f5d320b224737f16a07088Winson Chung        overviewModeMaxIconZoneHeightPx =
131b38002419dcb456b51f5d320b224737f16a07088Winson Chung                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_max_icon_zone_height);
132d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi        overviewModeBarItemWidthPx =
133d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_item_width);
134d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi        overviewModeBarSpacerWidthPx =
135d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi                res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_spacer_width);
136b38002419dcb456b51f5d320b224737f16a07088Winson Chung        overviewModeIconZoneRatio =
137b38002419dcb456b51f5d320b224737f16a07088Winson Chung                res.getInteger(R.integer.config_dynamic_grid_overview_icon_zone_percentage) / 100f;
138b38002419dcb456b51f5d320b224737f16a07088Winson Chung        iconDrawablePaddingOriginalPx =
139b38002419dcb456b51f5d320b224737f16a07088Winson Chung                res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
1402e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen
141b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // AllApps uses the original non-scaled icon text size
1422e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        allAppsIconTextSizePx = Utilities.pxFromDp(inv.iconTextSize, dm);
143b38002419dcb456b51f5d320b224737f16a07088Winson Chung
1442e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        // AllApps uses the original non-scaled icon size
1452e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        allAppsIconSizePx = Utilities.pxFromDp(inv.iconSize, dm);
146b38002419dcb456b51f5d320b224737f16a07088Winson Chung
147c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        // Determine sizes.
148c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        widthPx = width;
149c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        heightPx = height;
150c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        if (isLandscape) {
151c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal            availableWidthPx = maxSize.x;
152c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal            availableHeightPx = minSize.y;
153c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        } else {
154c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal            availableWidthPx = minSize.x;
155c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal            availableHeightPx = maxSize.y;
156c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        }
1574ae96ce92df7aad3c767c68b8795b80734e01829Adam Cohen
158b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // Calculate the remaining vars
159c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        updateAvailableDimensions(dm, res);
16063f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen        computeAllAppsButtonSize(context);
16163f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen    }
16263f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen
16363f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen    /**
16463f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen     * Determine the exact visual footprint of the all apps button, taking into account scaling
16563f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen     * and internal padding of the drawable.
16663f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen     */
16763f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen    private void computeAllAppsButtonSize(Context context) {
16863f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen        Resources res = context.getResources();
16963f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen        float padding = res.getInteger(R.integer.config_allAppsButtonPaddingPercent) / 100f;
17063f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen        allAppsButtonVisualSize = (int) (hotseatIconSizePx * (1 - padding));
171b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
172b38002419dcb456b51f5d320b224737f16a07088Winson Chung
173c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private void updateAvailableDimensions(DisplayMetrics dm, Resources res) {
174b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // Check to see if the icons fit in the new available height.  If not, then we need to
175b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // shrink the icon size.
176b38002419dcb456b51f5d320b224737f16a07088Winson Chung        float scale = 1f;
177b38002419dcb456b51f5d320b224737f16a07088Winson Chung        int drawablePadding = iconDrawablePaddingOriginalPx;
178c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        updateIconSize(1f, drawablePadding, res, dm);
1792e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        float usedHeight = (cellHeightPx * inv.numRows);
18059a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung
181c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        // We only care about the top and bottom workspace padding, which is not affected by RTL.
182c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        Rect workspacePadding = getWorkspacePadding(false /* isLayoutRtl */);
183b38002419dcb456b51f5d320b224737f16a07088Winson Chung        int maxHeight = (availableHeightPx - workspacePadding.top - workspacePadding.bottom);
184b38002419dcb456b51f5d320b224737f16a07088Winson Chung        if (usedHeight > maxHeight) {
185b38002419dcb456b51f5d320b224737f16a07088Winson Chung            scale = maxHeight / usedHeight;
186b38002419dcb456b51f5d320b224737f16a07088Winson Chung            drawablePadding = 0;
187b38002419dcb456b51f5d320b224737f16a07088Winson Chung        }
188c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        updateIconSize(scale, drawablePadding, res, dm);
189b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
190b38002419dcb456b51f5d320b224737f16a07088Winson Chung
19193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    private void updateIconSize(float scale, int drawablePadding, Resources res,
192b38002419dcb456b51f5d320b224737f16a07088Winson Chung                                DisplayMetrics dm) {
1932e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        iconSizePx = (int) (Utilities.pxFromDp(inv.iconSize, dm) * scale);
1942e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        iconTextSizePx = (int) (Utilities.pxFromSp(inv.iconTextSize, dm) * scale);
195b38002419dcb456b51f5d320b224737f16a07088Winson Chung        iconDrawablePaddingPx = drawablePadding;
1962e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        hotseatIconSizePx = (int) (Utilities.pxFromDp(inv.hotseatIconSize, dm) * scale);
197b38002419dcb456b51f5d320b224737f16a07088Winson Chung
198b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // Search Bar
199594d76dc66cb5666830b62594909fed187987d42Sunny Goyal        searchBarSpaceWidthPx = Math.min(widthPx,
20093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung                res.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_max_width));
201594d76dc66cb5666830b62594909fed187987d42Sunny Goyal        searchBarSpaceHeightPx = getSearchBarTopOffset()
20293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung                + res.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height);
203b38002419dcb456b51f5d320b224737f16a07088Winson Chung
204b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // Calculate the actual text height
205b38002419dcb456b51f5d320b224737f16a07088Winson Chung        Paint textPaint = new Paint();
206b38002419dcb456b51f5d320b224737f16a07088Winson Chung        textPaint.setTextSize(iconTextSizePx);
207b38002419dcb456b51f5d320b224737f16a07088Winson Chung        FontMetrics fm = textPaint.getFontMetrics();
208b38002419dcb456b51f5d320b224737f16a07088Winson Chung        cellWidthPx = iconSizePx;
209b38002419dcb456b51f5d320b224737f16a07088Winson Chung        cellHeightPx = iconSizePx + iconDrawablePaddingPx + (int) Math.ceil(fm.bottom - fm.top);
21093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        final float scaleDps = res.getDimensionPixelSize(R.dimen.dragViewScale);
21159a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung        dragViewScale = (iconSizePx + scaleDps) / iconSizePx;
212b38002419dcb456b51f5d320b224737f16a07088Winson Chung
213b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // Hotseat
214b38002419dcb456b51f5d320b224737f16a07088Winson Chung        hotseatBarHeightPx = iconSizePx + 4 * edgeMarginPx;
215b38002419dcb456b51f5d320b224737f16a07088Winson Chung        hotseatCellWidthPx = iconSizePx;
216b38002419dcb456b51f5d320b224737f16a07088Winson Chung        hotseatCellHeightPx = iconSizePx;
217b38002419dcb456b51f5d320b224737f16a07088Winson Chung
218b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // Folder
219b38002419dcb456b51f5d320b224737f16a07088Winson Chung        folderCellWidthPx = cellWidthPx + 3 * edgeMarginPx;
220b38002419dcb456b51f5d320b224737f16a07088Winson Chung        folderCellHeightPx = cellHeightPx + edgeMarginPx;
221b38002419dcb456b51f5d320b224737f16a07088Winson Chung        folderBackgroundOffset = -edgeMarginPx;
222b38002419dcb456b51f5d320b224737f16a07088Winson Chung        folderIconSizePx = iconSizePx + 2 * -folderBackgroundOffset;
2230f785720667ab8afe4b4620a6c333d382d8659edWinson Chung    }
2240f785720667ab8afe4b4620a6c333d382d8659edWinson Chung
225ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    /**
226ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     * @param recyclerViewWidth the available width of the AllAppsRecyclerView
227ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     */
228ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public void updateAppsViewNumCols(Resources res, int recyclerViewWidth) {
22993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        int appsViewLeftMarginPx =
2305f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chung                res.getDimensionPixelSize(R.dimen.all_apps_grid_view_start_margin);
2312c6e5ccbcd7c3f87e7e85029782440600dc0a3d8Winson Chung        int allAppsCellWidthGap =
2322c6e5ccbcd7c3f87e7e85029782440600dc0a3d8Winson Chung                res.getDimensionPixelSize(R.dimen.all_apps_icon_width_gap);
233ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        int availableAppsWidthPx = (recyclerViewWidth > 0) ? recyclerViewWidth : availableWidthPx;
234208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        int numAppsCols = (availableAppsWidthPx - appsViewLeftMarginPx) /
2352c6e5ccbcd7c3f87e7e85029782440600dc0a3d8Winson Chung                (allAppsIconSizePx + allAppsCellWidthGap);
2362c6e5ccbcd7c3f87e7e85029782440600dc0a3d8Winson Chung        int numPredictiveAppCols = Math.max(inv.minAllAppsPredictionColumns, numAppsCols);
237ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        allAppsNumCols = numAppsCols;
238ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        allAppsNumPredictiveCols = numPredictiveAppCols;
239b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
240b38002419dcb456b51f5d320b224737f16a07088Winson Chung
24169e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung    /** Returns the search bar top offset */
242c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private int getSearchBarTopOffset() {
243c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        if (isTablet && !isVerticalBarLayout()) {
24469e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung            return 4 * edgeMarginPx;
24569e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung        } else {
24669e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung            return 2 * edgeMarginPx;
24769e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung        }
24869e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung    }
24969e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung
250b38002419dcb456b51f5d320b224737f16a07088Winson Chung    /** Returns the search bar bounds in the current orientation */
251c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    public Rect getSearchBarBounds(boolean isLayoutRtl) {
252b38002419dcb456b51f5d320b224737f16a07088Winson Chung        Rect bounds = new Rect();
253c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        if (isLandscape && transposeLayoutWithOrientation) {
25442b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung            if (isLayoutRtl) {
25542b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung                bounds.set(availableWidthPx - searchBarSpaceHeightPx, edgeMarginPx,
25642b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung                        availableWidthPx, availableHeightPx - edgeMarginPx);
25742b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung            } else {
25842b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung                bounds.set(0, edgeMarginPx, searchBarSpaceHeightPx,
25942b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung                        availableHeightPx - edgeMarginPx);
26042b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung            }
261b38002419dcb456b51f5d320b224737f16a07088Winson Chung        } else {
262c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal            if (isTablet) {
263b38002419dcb456b51f5d320b224737f16a07088Winson Chung                // Pad the left and right of the workspace to ensure consistent spacing
264b38002419dcb456b51f5d320b224737f16a07088Winson Chung                // between all icons
2654f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung                int width = getCurrentWidth();
266b38002419dcb456b51f5d320b224737f16a07088Winson Chung                // XXX: If the icon size changes across orientations, we will have to take
267b38002419dcb456b51f5d320b224737f16a07088Winson Chung                //      that into account here too.
268b38002419dcb456b51f5d320b224737f16a07088Winson Chung                int gap = (int) ((width - 2 * edgeMarginPx -
2692e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                        (inv.numColumns * cellWidthPx)) / (2 * (inv.numColumns + 1)));
2702cb2471e7fbade9a785c523df5941f2855e99041Winson Chung                bounds.set(edgeMarginPx + gap, getSearchBarTopOffset(),
2712cb2471e7fbade9a785c523df5941f2855e99041Winson Chung                        availableWidthPx - (edgeMarginPx + gap),
272b38002419dcb456b51f5d320b224737f16a07088Winson Chung                        searchBarSpaceHeightPx);
273b38002419dcb456b51f5d320b224737f16a07088Winson Chung            } else {
2742cb2471e7fbade9a785c523df5941f2855e99041Winson Chung                bounds.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,
2752cb2471e7fbade9a785c523df5941f2855e99041Winson Chung                        getSearchBarTopOffset(),
276b38002419dcb456b51f5d320b224737f16a07088Winson Chung                        availableWidthPx - (desiredWorkspaceLeftRightMarginPx -
277b38002419dcb456b51f5d320b224737f16a07088Winson Chung                        defaultWidgetPadding.right), searchBarSpaceHeightPx);
278b38002419dcb456b51f5d320b224737f16a07088Winson Chung            }
279b38002419dcb456b51f5d320b224737f16a07088Winson Chung        }
280b38002419dcb456b51f5d320b224737f16a07088Winson Chung        return bounds;
281b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
282b38002419dcb456b51f5d320b224737f16a07088Winson Chung
283b38002419dcb456b51f5d320b224737f16a07088Winson Chung    /** Returns the workspace padding in the specified orientation */
284c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    Rect getWorkspacePadding(boolean isLayoutRtl) {
285c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        Rect searchBarBounds = getSearchBarBounds(isLayoutRtl);
286b38002419dcb456b51f5d320b224737f16a07088Winson Chung        Rect padding = new Rect();
287c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        if (isLandscape && transposeLayoutWithOrientation) {
288b38002419dcb456b51f5d320b224737f16a07088Winson Chung            // Pad the left and right of the workspace with search/hotseat bar sizes
28942b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung            if (isLayoutRtl) {
29042b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung                padding.set(hotseatBarHeightPx, edgeMarginPx,
29142b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung                        searchBarBounds.width(), edgeMarginPx);
29242b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung            } else {
29342b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung                padding.set(searchBarBounds.width(), edgeMarginPx,
29442b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung                        hotseatBarHeightPx, edgeMarginPx);
29542b3c06849331aa5ba1f07f8c58915190d386aacWinson Chung            }
296b38002419dcb456b51f5d320b224737f16a07088Winson Chung        } else {
297c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal            if (isTablet) {
298b38002419dcb456b51f5d320b224737f16a07088Winson Chung                // Pad the left and right of the workspace to ensure consistent spacing
299b38002419dcb456b51f5d320b224737f16a07088Winson Chung                // between all icons
30059a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung                float gapScale = 1f + (dragViewScale - 1f) / 2f;
3014f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung                int width = getCurrentWidth();
3024f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung                int height = getCurrentHeight();
30359a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung                int paddingTop = searchBarBounds.bottom;
30459a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung                int paddingBottom = hotseatBarHeightPx + pageIndicatorHeightPx;
3052e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                int availableWidth = Math.max(0, width - (int) ((inv.numColumns * cellWidthPx) +
3062e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                        (inv.numColumns * gapScale * cellWidthPx)));
30759a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung                int availableHeight = Math.max(0, height - paddingTop - paddingBottom
3082e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                        - (int) (2 * inv.numRows * cellHeightPx));
30959a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung                padding.set(availableWidth / 2, paddingTop + availableHeight / 2,
31059a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung                        availableWidth / 2, paddingBottom + availableHeight / 2);
311b38002419dcb456b51f5d320b224737f16a07088Winson Chung            } else {
312b38002419dcb456b51f5d320b224737f16a07088Winson Chung                // Pad the top and bottom of the workspace with search/hotseat bar sizes
313b38002419dcb456b51f5d320b224737f16a07088Winson Chung                padding.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,
314b38002419dcb456b51f5d320b224737f16a07088Winson Chung                        searchBarBounds.bottom,
315b38002419dcb456b51f5d320b224737f16a07088Winson Chung                        desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.right,
316b38002419dcb456b51f5d320b224737f16a07088Winson Chung                        hotseatBarHeightPx + pageIndicatorHeightPx);
317b38002419dcb456b51f5d320b224737f16a07088Winson Chung            }
318b38002419dcb456b51f5d320b224737f16a07088Winson Chung        }
319b38002419dcb456b51f5d320b224737f16a07088Winson Chung        return padding;
320b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
321b38002419dcb456b51f5d320b224737f16a07088Winson Chung
322c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private int getWorkspacePageSpacing(boolean isLayoutRtl) {
323c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        if ((isLandscape && transposeLayoutWithOrientation) || isLargeTablet) {
324b38002419dcb456b51f5d320b224737f16a07088Winson Chung            // In landscape mode the page spacing is set to the default.
325b38002419dcb456b51f5d320b224737f16a07088Winson Chung            return defaultPageSpacingPx;
326b38002419dcb456b51f5d320b224737f16a07088Winson Chung        } else {
327b38002419dcb456b51f5d320b224737f16a07088Winson Chung            // In portrait, we want the pages spaced such that there is no
328b38002419dcb456b51f5d320b224737f16a07088Winson Chung            // overhang of the previous / next page into the current page viewport.
329b38002419dcb456b51f5d320b224737f16a07088Winson Chung            // We assume symmetrical padding in portrait mode.
330c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal            return Math.max(defaultPageSpacingPx, 2 * getWorkspacePadding(isLayoutRtl).left);
331b38002419dcb456b51f5d320b224737f16a07088Winson Chung        }
332b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
333b38002419dcb456b51f5d320b224737f16a07088Winson Chung
3344f7eb4077e901a28b2b698060079292b56e991bdWinson Chung    int getOverviewModeButtonBarHeight() {
335b38002419dcb456b51f5d320b224737f16a07088Winson Chung        int zoneHeight = (int) (overviewModeIconZoneRatio * availableHeightPx);
336b38002419dcb456b51f5d320b224737f16a07088Winson Chung        zoneHeight = Math.min(overviewModeMaxIconZoneHeightPx,
337b38002419dcb456b51f5d320b224737f16a07088Winson Chung                Math.max(overviewModeMinIconZoneHeightPx, zoneHeight));
3384f7eb4077e901a28b2b698060079292b56e991bdWinson Chung        return zoneHeight;
339b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
340b38002419dcb456b51f5d320b224737f16a07088Winson Chung
341b38002419dcb456b51f5d320b224737f16a07088Winson Chung    // The rect returned will be extended to below the system ui that covers the workspace
342b38002419dcb456b51f5d320b224737f16a07088Winson Chung    Rect getHotseatRect() {
343b38002419dcb456b51f5d320b224737f16a07088Winson Chung        if (isVerticalBarLayout()) {
344b38002419dcb456b51f5d320b224737f16a07088Winson Chung            return new Rect(availableWidthPx - hotseatBarHeightPx, 0,
345b38002419dcb456b51f5d320b224737f16a07088Winson Chung                    Integer.MAX_VALUE, availableHeightPx);
346b38002419dcb456b51f5d320b224737f16a07088Winson Chung        } else {
347b38002419dcb456b51f5d320b224737f16a07088Winson Chung            return new Rect(0, availableHeightPx - hotseatBarHeightPx,
348b38002419dcb456b51f5d320b224737f16a07088Winson Chung                    availableWidthPx, Integer.MAX_VALUE);
349b38002419dcb456b51f5d320b224737f16a07088Winson Chung        }
350b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
351b38002419dcb456b51f5d320b224737f16a07088Winson Chung
3522e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen    public static int calculateCellWidth(int width, int countX) {
353b38002419dcb456b51f5d320b224737f16a07088Winson Chung        return width / countX;
354b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
3552e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen    public static int calculateCellHeight(int height, int countY) {
356b38002419dcb456b51f5d320b224737f16a07088Winson Chung        return height / countY;
357b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
358b38002419dcb456b51f5d320b224737f16a07088Winson Chung
35918bfaafd3da45dce7b5f73eaa1665f228353338cHyunyoung Song    /**
36018bfaafd3da45dce7b5f73eaa1665f228353338cHyunyoung Song     * When {@code true}, hotseat is on the bottom row when in landscape mode.
36118bfaafd3da45dce7b5f73eaa1665f228353338cHyunyoung Song     * If {@code false}, hotseat is on the right column when in landscape mode.
36218bfaafd3da45dce7b5f73eaa1665f228353338cHyunyoung Song     */
363b38002419dcb456b51f5d320b224737f16a07088Winson Chung    boolean isVerticalBarLayout() {
364b38002419dcb456b51f5d320b224737f16a07088Winson Chung        return isLandscape && transposeLayoutWithOrientation;
365b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
366b38002419dcb456b51f5d320b224737f16a07088Winson Chung
367b38002419dcb456b51f5d320b224737f16a07088Winson Chung    boolean shouldFadeAdjacentWorkspaceScreens() {
368c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        return isVerticalBarLayout() || isLargeTablet;
369b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
370b38002419dcb456b51f5d320b224737f16a07088Winson Chung
371c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal    private int getVisibleChildCount(ViewGroup parent) {
372d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi        int visibleChildren = 0;
373d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi        for (int i = 0; i < parent.getChildCount(); i++) {
374d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi            if (parent.getChildAt(i).getVisibility() != View.GONE) {
375d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi                visibleChildren++;
376d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi            }
377d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi        }
378d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi        return visibleChildren;
379d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi    }
380d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi
381b38002419dcb456b51f5d320b224737f16a07088Winson Chung    public void layout(Launcher launcher) {
382b38002419dcb456b51f5d320b224737f16a07088Winson Chung        FrameLayout.LayoutParams lp;
383b38002419dcb456b51f5d320b224737f16a07088Winson Chung        boolean hasVerticalBarLayout = isVerticalBarLayout();
384c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        final boolean isLayoutRtl = Utilities.isRtl(launcher.getResources());
385b38002419dcb456b51f5d320b224737f16a07088Winson Chung
386b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // Layout the search bar space
387006ee269ba2e9946a83b42f96d4a0296254cba4aWinson Chung        View searchBar = launcher.getSearchDropTargetBar();
388b38002419dcb456b51f5d320b224737f16a07088Winson Chung        lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams();
389b38002419dcb456b51f5d320b224737f16a07088Winson Chung        if (hasVerticalBarLayout) {
390f8c6f885f032dad4e6b09e02ca97545783bccb70Winson Chung            // Vertical search bar space -- The search bar is fixed in the layout to be on the left
391f8c6f885f032dad4e6b09e02ca97545783bccb70Winson Chung            //                              of the screen regardless of RTL
392d9cc780fade7a078d127c7e5b8209d414a46f0a5Sunny Goyal            lp.gravity = Gravity.LEFT;
393b38002419dcb456b51f5d320b224737f16a07088Winson Chung            lp.width = searchBarSpaceHeightPx;
39424ce0b3708b44e738d6ee52477aa4dd917b547e7Adam Cohen
39524ce0b3708b44e738d6ee52477aa4dd917b547e7Adam Cohen            LinearLayout targets = (LinearLayout) searchBar.findViewById(R.id.drag_target_bar);
39624ce0b3708b44e738d6ee52477aa4dd917b547e7Adam Cohen            targets.setOrientation(LinearLayout.VERTICAL);
397d9cc780fade7a078d127c7e5b8209d414a46f0a5Sunny Goyal            FrameLayout.LayoutParams targetsLp = (FrameLayout.LayoutParams) targets.getLayoutParams();
398d9cc780fade7a078d127c7e5b8209d414a46f0a5Sunny Goyal            targetsLp.gravity = Gravity.TOP;
399d9cc780fade7a078d127c7e5b8209d414a46f0a5Sunny Goyal            targetsLp.height = LayoutParams.WRAP_CONTENT;
400d9cc780fade7a078d127c7e5b8209d414a46f0a5Sunny Goyal
401b38002419dcb456b51f5d320b224737f16a07088Winson Chung        } else {
40269e04ea5ab08ae923d5c8de079c7a36998e5e46aWinson Chung            // Horizontal search bar space
403d9cc780fade7a078d127c7e5b8209d414a46f0a5Sunny Goyal            lp.gravity = Gravity.TOP;
404b38002419dcb456b51f5d320b224737f16a07088Winson Chung            lp.height = searchBarSpaceHeightPx;
405d9cc780fade7a078d127c7e5b8209d414a46f0a5Sunny Goyal
406d9cc780fade7a078d127c7e5b8209d414a46f0a5Sunny Goyal            LinearLayout targets = (LinearLayout) searchBar.findViewById(R.id.drag_target_bar);
407d9cc780fade7a078d127c7e5b8209d414a46f0a5Sunny Goyal            targets.getLayoutParams().width = searchBarSpaceWidthPx;
408b38002419dcb456b51f5d320b224737f16a07088Winson Chung        }
409b38002419dcb456b51f5d320b224737f16a07088Winson Chung        searchBar.setLayoutParams(lp);
410b38002419dcb456b51f5d320b224737f16a07088Winson Chung
411b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // Layout the workspace
412b38002419dcb456b51f5d320b224737f16a07088Winson Chung        PagedView workspace = (PagedView) launcher.findViewById(R.id.workspace);
413b38002419dcb456b51f5d320b224737f16a07088Winson Chung        lp = (FrameLayout.LayoutParams) workspace.getLayoutParams();
414b38002419dcb456b51f5d320b224737f16a07088Winson Chung        lp.gravity = Gravity.CENTER;
415c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        Rect padding = getWorkspacePadding(isLayoutRtl);
416b38002419dcb456b51f5d320b224737f16a07088Winson Chung        workspace.setLayoutParams(lp);
417b38002419dcb456b51f5d320b224737f16a07088Winson Chung        workspace.setPadding(padding.left, padding.top, padding.right, padding.bottom);
418c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        workspace.setPageSpacing(getWorkspacePageSpacing(isLayoutRtl));
419b38002419dcb456b51f5d320b224737f16a07088Winson Chung
420b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // Layout the hotseat
421b38002419dcb456b51f5d320b224737f16a07088Winson Chung        View hotseat = launcher.findViewById(R.id.hotseat);
422b38002419dcb456b51f5d320b224737f16a07088Winson Chung        lp = (FrameLayout.LayoutParams) hotseat.getLayoutParams();
423b38002419dcb456b51f5d320b224737f16a07088Winson Chung        if (hasVerticalBarLayout) {
424f8c6f885f032dad4e6b09e02ca97545783bccb70Winson Chung            // Vertical hotseat -- The hotseat is fixed in the layout to be on the right of the
425f8c6f885f032dad4e6b09e02ca97545783bccb70Winson Chung            //                     screen regardless of RTL
426f8c6f885f032dad4e6b09e02ca97545783bccb70Winson Chung            lp.gravity = Gravity.RIGHT;
427b38002419dcb456b51f5d320b224737f16a07088Winson Chung            lp.width = hotseatBarHeightPx;
428b38002419dcb456b51f5d320b224737f16a07088Winson Chung            lp.height = LayoutParams.MATCH_PARENT;
429b38002419dcb456b51f5d320b224737f16a07088Winson Chung            hotseat.findViewById(R.id.layout).setPadding(0, 2 * edgeMarginPx, 0, 2 * edgeMarginPx);
430c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyal        } else if (isTablet) {
43159a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung            // Pad the hotseat with the workspace padding calculated above
432b38002419dcb456b51f5d320b224737f16a07088Winson Chung            lp.gravity = Gravity.BOTTOM;
433b38002419dcb456b51f5d320b224737f16a07088Winson Chung            lp.width = LayoutParams.MATCH_PARENT;
434b38002419dcb456b51f5d320b224737f16a07088Winson Chung            lp.height = hotseatBarHeightPx;
43559a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung            hotseat.setPadding(edgeMarginPx + padding.left, 0,
43659a488ac03aa122b75e9a358db74acf7bb4d2508Winson Chung                    edgeMarginPx + padding.right,
437b38002419dcb456b51f5d320b224737f16a07088Winson Chung                    2 * edgeMarginPx);
438b38002419dcb456b51f5d320b224737f16a07088Winson Chung        } else {
439b38002419dcb456b51f5d320b224737f16a07088Winson Chung            // For phones, layout the hotseat without any bottom margin
440b38002419dcb456b51f5d320b224737f16a07088Winson Chung            // to ensure that we have space for the folders
441b38002419dcb456b51f5d320b224737f16a07088Winson Chung            lp.gravity = Gravity.BOTTOM;
442b38002419dcb456b51f5d320b224737f16a07088Winson Chung            lp.width = LayoutParams.MATCH_PARENT;
443b38002419dcb456b51f5d320b224737f16a07088Winson Chung            lp.height = hotseatBarHeightPx;
444e0bca386247024728b1e71e9ae530fac7e5b3171Sunny Goyal            hotseat.findViewById(R.id.layout).setPadding(2 * edgeMarginPx, 0,
445e0bca386247024728b1e71e9ae530fac7e5b3171Sunny Goyal                    2 * edgeMarginPx, 0);
446b38002419dcb456b51f5d320b224737f16a07088Winson Chung        }
447b38002419dcb456b51f5d320b224737f16a07088Winson Chung        hotseat.setLayoutParams(lp);
448b38002419dcb456b51f5d320b224737f16a07088Winson Chung
449b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // Layout the page indicators
450b38002419dcb456b51f5d320b224737f16a07088Winson Chung        View pageIndicator = launcher.findViewById(R.id.page_indicator);
451b38002419dcb456b51f5d320b224737f16a07088Winson Chung        if (pageIndicator != null) {
452b38002419dcb456b51f5d320b224737f16a07088Winson Chung            if (hasVerticalBarLayout) {
453b38002419dcb456b51f5d320b224737f16a07088Winson Chung                // Hide the page indicators when we have vertical search/hotseat
454b38002419dcb456b51f5d320b224737f16a07088Winson Chung                pageIndicator.setVisibility(View.GONE);
455b38002419dcb456b51f5d320b224737f16a07088Winson Chung            } else {
456b38002419dcb456b51f5d320b224737f16a07088Winson Chung                // Put the page indicators above the hotseat
457b38002419dcb456b51f5d320b224737f16a07088Winson Chung                lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams();
458b38002419dcb456b51f5d320b224737f16a07088Winson Chung                lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
459b38002419dcb456b51f5d320b224737f16a07088Winson Chung                lp.width = LayoutParams.WRAP_CONTENT;
460b38002419dcb456b51f5d320b224737f16a07088Winson Chung                lp.height = LayoutParams.WRAP_CONTENT;
461b38002419dcb456b51f5d320b224737f16a07088Winson Chung                lp.bottomMargin = hotseatBarHeightPx;
462b38002419dcb456b51f5d320b224737f16a07088Winson Chung                pageIndicator.setLayoutParams(lp);
463b38002419dcb456b51f5d320b224737f16a07088Winson Chung            }
464b38002419dcb456b51f5d320b224737f16a07088Winson Chung        }
465b38002419dcb456b51f5d320b224737f16a07088Winson Chung
466b38002419dcb456b51f5d320b224737f16a07088Winson Chung        // Layout the Overview Mode
467d017f882eb67b630adb082dd2227e20f5bc77b05Jorim Jaggi        ViewGroup overviewMode = launcher.getOverviewPanel();
468b38002419dcb456b51f5d320b224737f16a07088Winson Chung        if (overviewMode != null) {
4694f7eb4077e901a28b2b698060079292b56e991bdWinson Chung            int overviewButtonBarHeight = getOverviewModeButtonBarHeight();
470b38002419dcb456b51f5d320b224737f16a07088Winson Chung            lp = (FrameLayout.LayoutParams) overviewMode.getLayoutParams();
471b38002419dcb456b51f5d320b224737f16a07088Winson Chung            lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
4728dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal
4738dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal            int visibleChildCount = getVisibleChildCount(overviewMode);
4748dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal            int totalItemWidth = visibleChildCount * overviewModeBarItemWidthPx;
4758dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal            int maxWidth = totalItemWidth + (visibleChildCount-1) * overviewModeBarSpacerWidthPx;
4768dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal
4778dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal            lp.width = Math.min(availableWidthPx, maxWidth);
4784f7eb4077e901a28b2b698060079292b56e991bdWinson Chung            lp.height = overviewButtonBarHeight;
479b38002419dcb456b51f5d320b224737f16a07088Winson Chung            overviewMode.setLayoutParams(lp);
4808dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal
4818dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal            if (lp.width > totalItemWidth && visibleChildCount > 1) {
4828dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                // We have enough space. Lets add some margin too.
4838dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                int margin = (lp.width - totalItemWidth) / (visibleChildCount-1);
4848dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                View lastChild = null;
4858dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal
4868dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                // Set margin of all visible children except the last visible child
4878dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                for (int i = 0; i < visibleChildCount; i++) {
4888dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                    if (lastChild != null) {
4898dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                        MarginLayoutParams clp = (MarginLayoutParams) lastChild.getLayoutParams();
4908dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                        if (isLayoutRtl) {
4918dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                            clp.leftMargin = margin;
4928dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                        } else {
4938dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                            clp.rightMargin = margin;
4948dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                        }
4958dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                        lastChild.setLayoutParams(clp);
4968dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                        lastChild = null;
4978dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                    }
4988dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                    View thisChild = overviewMode.getChildAt(i);
4998dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                    if (thisChild.getVisibility() != View.GONE) {
5008dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                        lastChild = thisChild;
5018dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                    }
5028dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal                }
5038dfe2da6985d38f23fd3426101574c093f509907Sunny Goyal            }
504b38002419dcb456b51f5d320b224737f16a07088Winson Chung        }
505b38002419dcb456b51f5d320b224737f16a07088Winson Chung    }
5064f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung
5074f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung    private int getCurrentWidth() {
5084f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung        return isLandscape
5094f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung                ? Math.max(widthPx, heightPx)
5104f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung                : Math.min(widthPx, heightPx);
5114f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung    }
5124f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung
5134f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung    private int getCurrentHeight() {
5144f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung        return isLandscape
5154f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung                ? Math.min(widthPx, heightPx)
5164f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung                : Math.max(widthPx, heightPx);
5174f3bfadbf472665ea8431cf2616d56a9445df466Winson Chung    }
518b38002419dcb456b51f5d320b224737f16a07088Winson Chung}
519