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
17package com.android.launcher3;
18
19import android.content.ComponentName;
20import android.content.Context;
21import android.content.res.Configuration;
22import android.content.res.Resources;
23import android.graphics.Rect;
24import android.graphics.drawable.Drawable;
25import android.util.AttributeSet;
26import android.util.Log;
27import android.view.LayoutInflater;
28import android.view.MotionEvent;
29import android.view.View;
30import android.widget.FrameLayout;
31import android.widget.TextView;
32
33import java.util.ArrayList;
34
35public class Hotseat extends FrameLayout {
36    private static final String TAG = "Hotseat";
37
38    private CellLayout mContent;
39
40    private Launcher mLauncher;
41
42    private int mAllAppsButtonRank;
43
44    private boolean mTransposeLayoutWithOrientation;
45    private boolean mIsLandscape;
46
47    public Hotseat(Context context) {
48        this(context, null);
49    }
50
51    public Hotseat(Context context, AttributeSet attrs) {
52        this(context, attrs, 0);
53    }
54
55    public Hotseat(Context context, AttributeSet attrs, int defStyle) {
56        super(context, attrs, defStyle);
57
58        Resources r = context.getResources();
59        mTransposeLayoutWithOrientation =
60                r.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
61        mIsLandscape = context.getResources().getConfiguration().orientation ==
62            Configuration.ORIENTATION_LANDSCAPE;
63    }
64
65    public void setup(Launcher launcher) {
66        mLauncher = launcher;
67    }
68
69    CellLayout getLayout() {
70        return mContent;
71    }
72
73    /**
74     * Registers the specified listener on the cell layout of the hotseat.
75     */
76    @Override
77    public void setOnLongClickListener(OnLongClickListener l) {
78        mContent.setOnLongClickListener(l);
79    }
80
81    private boolean hasVerticalHotseat() {
82        return (mIsLandscape && mTransposeLayoutWithOrientation);
83    }
84
85    /* Get the orientation invariant order of the item in the hotseat for persistence. */
86    int getOrderInHotseat(int x, int y) {
87        return hasVerticalHotseat() ? (mContent.getCountY() - y - 1) : x;
88    }
89    /* Get the orientation specific coordinates given an invariant order in the hotseat. */
90    int getCellXFromOrder(int rank) {
91        return hasVerticalHotseat() ? 0 : rank;
92    }
93    int getCellYFromOrder(int rank) {
94        return hasVerticalHotseat() ? (mContent.getCountY() - (rank + 1)) : 0;
95    }
96    public boolean isAllAppsButtonRank(int rank) {
97        if (LauncherAppState.isDisableAllApps()) {
98            return false;
99        } else {
100            return rank == mAllAppsButtonRank;
101        }
102    }
103
104    /** This returns the coordinates of an app in a given cell, relative to the DragLayer */
105    Rect getCellCoordinates(int cellX, int cellY) {
106        Rect coords = new Rect();
107        mContent.cellToRect(cellX, cellY, 1, 1, coords);
108        int[] hotseatInParent = new int[2];
109        Utilities.getDescendantCoordRelativeToParent(this, mLauncher.getDragLayer(),
110                hotseatInParent, false);
111        coords.offset(hotseatInParent[0], hotseatInParent[1]);
112
113        // Center the icon
114        int cWidth = mContent.getShortcutsAndWidgets().getCellContentWidth();
115        int cHeight = mContent.getShortcutsAndWidgets().getCellContentHeight();
116        int cellPaddingX = (int) Math.max(0, ((coords.width() - cWidth) / 2f));
117        int cellPaddingY = (int) Math.max(0, ((coords.height() - cHeight) / 2f));
118        coords.offset(cellPaddingX, cellPaddingY);
119
120        return coords;
121    }
122
123    @Override
124    protected void onFinishInflate() {
125        super.onFinishInflate();
126        LauncherAppState app = LauncherAppState.getInstance();
127        DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
128
129        mAllAppsButtonRank = grid.hotseatAllAppsRank;
130        mContent = (CellLayout) findViewById(R.id.layout);
131        if (grid.isLandscape && !grid.isLargeTablet()) {
132            mContent.setGridSize(1, (int) grid.numHotseatIcons);
133        } else {
134            mContent.setGridSize((int) grid.numHotseatIcons, 1);
135        }
136        mContent.setIsHotseat(true);
137
138        resetLayout();
139    }
140
141    void resetLayout() {
142        mContent.removeAllViewsInLayout();
143
144        if (!LauncherAppState.isDisableAllApps()) {
145            // Add the Apps button
146            Context context = getContext();
147
148            LayoutInflater inflater = LayoutInflater.from(context);
149            TextView allAppsButton = (TextView)
150                    inflater.inflate(R.layout.all_apps_button, mContent, false);
151            Drawable d = context.getResources().getDrawable(R.drawable.all_apps_button_icon);
152
153            Utilities.resizeIconDrawable(d);
154            allAppsButton.setCompoundDrawables(null, d, null, null);
155
156            allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
157            allAppsButton.setOnKeyListener(new HotseatIconKeyEventListener());
158            if (mLauncher != null) {
159                allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
160                mLauncher.setAllAppsButton(allAppsButton);
161                allAppsButton.setOnClickListener(mLauncher);
162                allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
163            }
164
165            // Note: We do this to ensure that the hotseat is always laid out in the orientation of
166            // the hotseat in order regardless of which orientation they were added
167            int x = getCellXFromOrder(mAllAppsButtonRank);
168            int y = getCellYFromOrder(mAllAppsButtonRank);
169            CellLayout.LayoutParams lp = new CellLayout.LayoutParams(x,y,1,1);
170            lp.canReorder = false;
171            mContent.addViewToCellLayout(allAppsButton, -1, allAppsButton.getId(), lp, true);
172        }
173    }
174
175    @Override
176    public boolean onInterceptTouchEvent(MotionEvent ev) {
177        // We don't want any clicks to go through to the hotseat unless the workspace is in
178        // the normal state.
179        if (mLauncher.getWorkspace().workspaceInModalState()) {
180            return true;
181        }
182        return false;
183    }
184
185    void addAllAppsFolder(IconCache iconCache,
186            ArrayList<AppInfo> allApps, ArrayList<ComponentName> onWorkspace,
187            Launcher launcher, Workspace workspace) {
188        if (LauncherAppState.isDisableAllApps()) {
189            FolderInfo fi = new FolderInfo();
190
191            fi.cellX = getCellXFromOrder(mAllAppsButtonRank);
192            fi.cellY = getCellYFromOrder(mAllAppsButtonRank);
193            fi.spanX = 1;
194            fi.spanY = 1;
195            fi.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
196            fi.screenId = mAllAppsButtonRank;
197            fi.itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
198            fi.title = "More Apps";
199            LauncherModel.addItemToDatabase(launcher, fi, fi.container, fi.screenId, fi.cellX,
200                    fi.cellY, false);
201            FolderIcon folder = FolderIcon.fromXml(R.layout.folder_icon, launcher,
202                    getLayout(), fi, iconCache);
203            workspace.addInScreen(folder, fi.container, fi.screenId, fi.cellX, fi.cellY,
204                    fi.spanX, fi.spanY);
205
206            for (AppInfo info: allApps) {
207                ComponentName cn = info.intent.getComponent();
208                if (!onWorkspace.contains(cn)) {
209                    Log.d(TAG, "Adding to 'more apps': " + info.intent);
210                    ShortcutInfo si = info.makeShortcut();
211                    fi.add(si);
212                }
213            }
214        }
215    }
216
217    void addAppsToAllAppsFolder(ArrayList<AppInfo> apps) {
218        if (LauncherAppState.isDisableAllApps()) {
219            View v = mContent.getChildAt(getCellXFromOrder(mAllAppsButtonRank), getCellYFromOrder(mAllAppsButtonRank));
220            FolderIcon fi = null;
221
222            if (v instanceof FolderIcon) {
223                fi = (FolderIcon) v;
224            } else {
225                return;
226            }
227
228            FolderInfo info = fi.getFolderInfo();
229            for (AppInfo a: apps) {
230                ShortcutInfo si = a.makeShortcut();
231                info.add(si);
232            }
233        }
234    }
235}
236