14e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung/*
24e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung * Copyright (C) 2011 The Android Open Source Project
34e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung *
44e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung * Licensed under the Apache License, Version 2.0 (the "License");
54e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung * you may not use this file except in compliance with the License.
64e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung * You may obtain a copy of the License at
74e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung *
84e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung *      http://www.apache.org/licenses/LICENSE-2.0
94e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung *
104e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung * Unless required by applicable law or agreed to in writing, software
114e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung * distributed under the License is distributed on an "AS IS" BASIS,
124e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung * See the License for the specific language governing permissions and
144e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung * limitations under the License.
154e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung */
164e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
174e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chungpackage com.android.launcher2;
184e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
194e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chungimport android.content.Context;
204e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chungimport android.view.MotionEvent;
214e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chungimport android.view.View;
224e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chungimport android.widget.FrameLayout;
23fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chungimport android.widget.GridLayout;
244e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
254e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung/**
264e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung * The grid based layout used strictly for the widget/wallpaper tab of the AppsCustomize pane
274e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung */
28fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chungpublic class PagedViewGridLayout extends GridLayout implements Page {
294e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    static final String TAG = "PagedViewGridLayout";
304e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
314e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    private int mCellCountX;
324e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    private int mCellCountY;
33038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka    private Runnable mOnLayoutListener;
344e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
354e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    public PagedViewGridLayout(Context context, int cellCountX, int cellCountY) {
364e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        super(context, null, 0);
374e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        mCellCountX = cellCountX;
384e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        mCellCountY = cellCountY;
394e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    }
404e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
414e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    int getCellCountX() {
424e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        return mCellCountX;
434e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    }
4422f823d340710bcde587b18a1542570cbe0360f5Adam Cohen
454e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    int getCellCountY() {
464e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        return mCellCountY;
474e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    }
484e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
49c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung    /**
50c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung     * Clears all the key listeners for the individual widgets.
51c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung     */
52c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung    public void resetChildrenOnKeyListeners() {
53c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung        int childCount = getChildCount();
54c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung        for (int j = 0; j < childCount; ++j) {
55c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung            getChildAt(j).setOnKeyListener(null);
56c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung        }
57c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung    }
58c6f10b906fc9c120cafc81046a42b2434ff635a9Winson Chung
594e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
604e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        // PagedView currently has issues with different-sized pages since it calculates the
614e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        // offset of each page to scroll to before it updates the actual size of each page
624e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        // (which can change depending on the content if the contents aren't a fixed size).
634e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        // We work around this by having a minimum size on each widget page).
64fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chung        int widthSpecSize = Math.min(getSuggestedMinimumWidth(),
654e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung                MeasureSpec.getSize(widthMeasureSpec));
66fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chung        int widthSpecMode = MeasureSpec.EXACTLY;
674e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        super.onMeasure(MeasureSpec.makeMeasureSpec(widthSpecSize, widthSpecMode),
684e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung                heightMeasureSpec);
694e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    }
704e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
71e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka    @Override
72e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka    protected void onDetachedFromWindow() {
73e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka        super.onDetachedFromWindow();
74e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka        mOnLayoutListener = null;
75e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka    }
76e326f186af6b00e4ea32849f1527254c669d0600Michael Jurka
77038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka    public void setOnLayoutListener(Runnable r) {
78038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka        mOnLayoutListener = r;
79038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka    }
80038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka
81038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
82038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka        super.onLayout(changed, left, top, right, bottom);
83038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka        if (mOnLayoutListener != null) {
84038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka            mOnLayoutListener.run();
85038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka        }
86038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka    }
87038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka
884e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    @Override
894e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    public boolean onTouchEvent(MotionEvent event) {
90f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        boolean result = super.onTouchEvent(event);
91f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        int count = getPageChildCount();
92f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        if (count > 0) {
93f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            // We only intercept the touch if we are tapping in empty space after the final row
94f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            View child = getChildOnPageAt(count - 1);
95f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            int bottom = child.getBottom();
96f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            result = result || (event.getY() < bottom);
97f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        }
98f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        return result;
994e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    }
1004e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
1014e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    @Override
1024e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    public void removeAllViewsOnPage() {
1034e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        removeAllViews();
1042a4b1a809c6bc0af9ae3ad974fe50e2a91569543Michael Jurka        mOnLayoutListener = null;
10547639b9c1db9a5d0d89ce6b4b36d6b3c0d489602Michael Jurka        setLayerType(LAYER_TYPE_NONE, null);
1064e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    }
1074e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
1084e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    @Override
1094e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    public void removeViewOnPageAt(int index) {
1104e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        removeViewAt(index);
1114e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    }
1124e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
1134e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    @Override
1144e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    public int getPageChildCount() {
1154e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        return getChildCount();
1164e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    }
1174e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
1184e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    @Override
1194e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    public View getChildOnPageAt(int i) {
1204e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        return getChildAt(i);
1214e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    }
1224e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
1234e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    @Override
1244e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    public int indexOfChildOnPage(View v) {
1254e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        return indexOfChild(v);
1264e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    }
1274e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung
1284e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    public static class LayoutParams extends FrameLayout.LayoutParams {
1294e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        public LayoutParams(int width, int height) {
1304e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung            super(width, height);
1314e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung        }
1324e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung    }
1334e6a976c2d85f7261ae4318a9ccffd2440f73124Winson Chung}
134