1/*
2 * Copyright (C) 2008 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.launcher2;
18
19import android.app.WallpaperManager;
20import android.content.Context;
21import android.graphics.Canvas;
22import android.graphics.Paint;
23import android.graphics.Rect;
24import android.view.View;
25import android.view.ViewGroup;
26
27public class ShortcutAndWidgetContainer extends ViewGroup {
28    static final String TAG = "CellLayoutChildren";
29
30    // These are temporary variables to prevent having to allocate a new object just to
31    // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
32    private final int[] mTmpCellXY = new int[2];
33
34    private final WallpaperManager mWallpaperManager;
35
36    private int mCellWidth;
37    private int mCellHeight;
38
39    private int mWidthGap;
40    private int mHeightGap;
41
42    private int mCountX;
43
44    private boolean mInvertIfRtl = false;
45
46    public ShortcutAndWidgetContainer(Context context) {
47        super(context);
48        mWallpaperManager = WallpaperManager.getInstance(context);
49    }
50
51    public void setCellDimensions(int cellWidth, int cellHeight, int widthGap, int heightGap,
52            int countX) {
53        mCellWidth = cellWidth;
54        mCellHeight = cellHeight;
55        mWidthGap = widthGap;
56        mHeightGap = heightGap;
57        mCountX = countX;
58    }
59
60    public View getChildAt(int x, int y) {
61        final int count = getChildCount();
62        for (int i = 0; i < count; i++) {
63            View child = getChildAt(i);
64            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
65
66            if ((lp.cellX <= x) && (x < lp.cellX + lp.cellHSpan) &&
67                    (lp.cellY <= y) && (y < lp.cellY + lp.cellVSpan)) {
68                return child;
69            }
70        }
71        return null;
72    }
73
74    @Override
75    protected void dispatchDraw(Canvas canvas) {
76        @SuppressWarnings("all") // suppress dead code warning
77        final boolean debug = false;
78        if (debug) {
79            // Debug drawing for hit space
80            Paint p = new Paint();
81            p.setColor(0x6600FF00);
82            for (int i = getChildCount() - 1; i >= 0; i--) {
83                final View child = getChildAt(i);
84                final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
85
86                canvas.drawRect(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height, p);
87            }
88        }
89        super.dispatchDraw(canvas);
90    }
91
92    @Override
93    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
94        int count = getChildCount();
95        for (int i = 0; i < count; i++) {
96            View child = getChildAt(i);
97            measureChild(child);
98        }
99        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
100        int heightSpecSize =  MeasureSpec.getSize(heightMeasureSpec);
101        setMeasuredDimension(widthSpecSize, heightSpecSize);
102    }
103
104    public void setupLp(CellLayout.LayoutParams lp) {
105        lp.setup(mCellWidth, mCellHeight, mWidthGap, mHeightGap, invertLayoutHorizontally(),
106                mCountX);
107    }
108
109    // Set whether or not to invert the layout horizontally if the layout is in RTL mode.
110    public void setInvertIfRtl(boolean invert) {
111        mInvertIfRtl = invert;
112    }
113
114    public void measureChild(View child) {
115        final int cellWidth = mCellWidth;
116        final int cellHeight = mCellHeight;
117        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
118
119        lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap, invertLayoutHorizontally(), mCountX);
120        int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
121        int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
122                MeasureSpec.EXACTLY);
123        child.measure(childWidthMeasureSpec, childheightMeasureSpec);
124    }
125
126    private boolean invertLayoutHorizontally() {
127        return mInvertIfRtl && isLayoutRtl();
128    }
129
130    public boolean isLayoutRtl() {
131        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
132    }
133
134    @Override
135    protected void onLayout(boolean changed, int l, int t, int r, int b) {
136        int count = getChildCount();
137        for (int i = 0; i < count; i++) {
138            final View child = getChildAt(i);
139            if (child.getVisibility() != GONE) {
140                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
141
142                int childLeft = lp.x;
143                int childTop = lp.y;
144                child.layout(childLeft, childTop, childLeft + lp.width, childTop + lp.height);
145
146                if (lp.dropped) {
147                    lp.dropped = false;
148
149                    final int[] cellXY = mTmpCellXY;
150                    getLocationOnScreen(cellXY);
151                    mWallpaperManager.sendWallpaperCommand(getWindowToken(),
152                            WallpaperManager.COMMAND_DROP,
153                            cellXY[0] + childLeft + lp.width / 2,
154                            cellXY[1] + childTop + lp.height / 2, 0, null);
155                }
156            }
157        }
158    }
159
160    @Override
161    public boolean shouldDelayChildPressedState() {
162        return false;
163    }
164
165    @Override
166    public void requestChildFocus(View child, View focused) {
167        super.requestChildFocus(child, focused);
168        if (child != null) {
169            Rect r = new Rect();
170            child.getDrawingRect(r);
171            requestRectangleOnScreen(r);
172        }
173    }
174
175    @Override
176    public void cancelLongPress() {
177        super.cancelLongPress();
178
179        // Cancel long press for all children
180        final int count = getChildCount();
181        for (int i = 0; i < count; i++) {
182            final View child = getChildAt(i);
183            child.cancelLongPress();
184        }
185    }
186
187    @Override
188    protected void setChildrenDrawingCacheEnabled(boolean enabled) {
189        final int count = getChildCount();
190        for (int i = 0; i < count; i++) {
191            final View view = getChildAt(i);
192            view.setDrawingCacheEnabled(enabled);
193            // Update the drawing caches
194            if (!view.isHardwareAccelerated() && enabled) {
195                view.buildDrawingCache(true);
196            }
197        }
198    }
199
200    @Override
201    protected void setChildrenDrawnWithCacheEnabled(boolean enabled) {
202        super.setChildrenDrawnWithCacheEnabled(enabled);
203    }
204}
205