1739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout/*
2739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Copyright (C) 2014 The Android Open Source Project
3739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout *
4739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * in compliance with the License. You may obtain a copy of the License at
6739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout *
7739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * http://www.apache.org/licenses/LICENSE-2.0
8739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout *
9739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * Unless required by applicable law or agreed to in writing, software distributed under the License
10739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * or implied. See the License for the specific language governing permissions and limitations under
12739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * the License.
13739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */
14739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutpackage android.support.v17.leanback.widget;
15739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
16f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stoutimport android.content.Context;
17739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.support.v17.leanback.R;
18f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stoutimport android.support.v17.leanback.system.Settings;
19afb203b71421cb0d477d4d470e852cc9647dde48Dake Guimport android.support.v17.leanback.transition.TransitionHelper;
20739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.view.LayoutInflater;
21739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.view.View;
22739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.view.ViewGroup;
230d734cb6671b314f84cb4911cd37631177d07fbaCraig Stoutimport android.view.ViewGroup.LayoutParams;
24739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutimport android.util.Log;
25739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
26739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout/**
27a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * A presenter that renders objects in a {@link VerticalGridView}.
28739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout */
29739e3805bf2785e6773aede5e2e1643f537305f9Craig Stoutpublic class VerticalGridPresenter extends Presenter {
30739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private static final String TAG = "GridPresenter";
31739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private static final boolean DEBUG = false;
32739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
3371fddded48048acfa744ac352166770c91a1c2b1Dake Gu    class VerticalGridItemBridgeAdapter extends ItemBridgeAdapter {
3471fddded48048acfa744ac352166770c91a1c2b1Dake Gu        @Override
354d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu        protected void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) {
36afb203b71421cb0d477d4d470e852cc9647dde48Dake Gu            if (viewHolder.itemView instanceof ViewGroup) {
378403619efebe94666c0615c3fc85080a303acf80Dake Gu                TransitionHelper.setTransitionGroup((ViewGroup) viewHolder.itemView,
38afb203b71421cb0d477d4d470e852cc9647dde48Dake Gu                        true);
39afb203b71421cb0d477d4d470e852cc9647dde48Dake Gu            }
404d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu            if (mShadowOverlayHelper != null) {
414d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu                mShadowOverlayHelper.onViewCreated(viewHolder.itemView);
424d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu            }
434d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu        }
444d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu
454d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu        @Override
4671fddded48048acfa744ac352166770c91a1c2b1Dake Gu        public void onBind(final ItemBridgeAdapter.ViewHolder itemViewHolder) {
4771fddded48048acfa744ac352166770c91a1c2b1Dake Gu            // Only when having an OnItemClickListner, we attach the OnClickListener.
488df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu            if (getOnItemViewClickedListener() != null) {
4971fddded48048acfa744ac352166770c91a1c2b1Dake Gu                final View itemView = itemViewHolder.mHolder.view;
5071fddded48048acfa744ac352166770c91a1c2b1Dake Gu                itemView.setOnClickListener(new View.OnClickListener() {
5171fddded48048acfa744ac352166770c91a1c2b1Dake Gu                    @Override
5271fddded48048acfa744ac352166770c91a1c2b1Dake Gu                    public void onClick(View view) {
5371fddded48048acfa744ac352166770c91a1c2b1Dake Gu                        if (getOnItemViewClickedListener() != null) {
5471fddded48048acfa744ac352166770c91a1c2b1Dake Gu                            // Row is always null
5571fddded48048acfa744ac352166770c91a1c2b1Dake Gu                            getOnItemViewClickedListener().onItemClicked(
5671fddded48048acfa744ac352166770c91a1c2b1Dake Gu                                    itemViewHolder.mHolder, itemViewHolder.mItem, null, null);
5771fddded48048acfa744ac352166770c91a1c2b1Dake Gu                        }
5871fddded48048acfa744ac352166770c91a1c2b1Dake Gu                    }
5971fddded48048acfa744ac352166770c91a1c2b1Dake Gu                });
6071fddded48048acfa744ac352166770c91a1c2b1Dake Gu            }
6171fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
6271fddded48048acfa744ac352166770c91a1c2b1Dake Gu
6371fddded48048acfa744ac352166770c91a1c2b1Dake Gu        @Override
6471fddded48048acfa744ac352166770c91a1c2b1Dake Gu        public void onUnbind(ItemBridgeAdapter.ViewHolder viewHolder) {
658df88a1ead9ea62456fc3bbda41657ccf61d5721Dake Gu            if (getOnItemViewClickedListener() != null) {
6671fddded48048acfa744ac352166770c91a1c2b1Dake Gu                viewHolder.mHolder.view.setOnClickListener(null);
6771fddded48048acfa744ac352166770c91a1c2b1Dake Gu            }
6871fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
6971fddded48048acfa744ac352166770c91a1c2b1Dake Gu
7071fddded48048acfa744ac352166770c91a1c2b1Dake Gu        @Override
7171fddded48048acfa744ac352166770c91a1c2b1Dake Gu        public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
7271fddded48048acfa744ac352166770c91a1c2b1Dake Gu            viewHolder.itemView.setActivated(true);
7371fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
7471fddded48048acfa744ac352166770c91a1c2b1Dake Gu    }
7571fddded48048acfa744ac352166770c91a1c2b1Dake Gu
76a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout    /**
77a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * ViewHolder for the VerticalGridPresenter.
78a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     */
79739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public static class ViewHolder extends Presenter.ViewHolder {
8071fddded48048acfa744ac352166770c91a1c2b1Dake Gu        ItemBridgeAdapter mItemBridgeAdapter;
81739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        final VerticalGridView mGridView;
82739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        boolean mInitialized;
83739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
84739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        public ViewHolder(VerticalGridView view) {
85739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            super(view);
86739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mGridView = view;
87739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
88739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
89739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        public VerticalGridView getGridView() {
90739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            return mGridView;
91739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
92739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
93739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
94739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private int mNumColumns = -1;
9541ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    private int mFocusZoomFactor;
9641ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    private boolean mUseFocusDimmer;
970d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout    private boolean mShadowEnabled = true;
9885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    private boolean mKeepChildForeground = true;
99947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    private OnItemViewSelectedListener mOnItemViewSelectedListener;
100947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    private OnItemViewClickedListener mOnItemViewClickedListener;
1014f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    private boolean mRoundedCornersEnabled = true;
1024d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu    private ShadowOverlayHelper mShadowOverlayHelper;
10385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    private ItemBridgeAdapter.Wrapper mShadowOverlayWrapper;
104739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
10541ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    /**
10641ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     * Constructs a VerticalGridPresenter with defaults.
10741ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     * Uses {@link FocusHighlight#ZOOM_FACTOR_MEDIUM} for focus zooming and
10841ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     * enabled dimming on focus.
10941ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     */
110739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public VerticalGridPresenter() {
111a37118706af7d79adeb8b3918fb52fad99ece361Dake Gu        this(FocusHighlight.ZOOM_FACTOR_LARGE);
112739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
113739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
11441ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    /**
11541ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     * Constructs a VerticalGridPresenter with the given parameters.
11641ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     *
11741ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     * @param focusZoomFactor Controls the zoom factor used when an item view is focused. One of
11841ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     *         {@link FocusHighlight#ZOOM_FACTOR_NONE},
11941ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     *         {@link FocusHighlight#ZOOM_FACTOR_SMALL},
12041ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     *         {@link FocusHighlight#ZOOM_FACTOR_XSMALL},
12141ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     *         {@link FocusHighlight#ZOOM_FACTOR_MEDIUM},
12241ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     *         {@link FocusHighlight#ZOOM_FACTOR_LARGE}
12341ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     * enabled dimming on focus.
12441ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     */
12541ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    public VerticalGridPresenter(int focusZoomFactor) {
12641ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield        this(focusZoomFactor, true);
12741ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    }
12841ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield
12941ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    /**
13041ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     * Constructs a VerticalGridPresenter with the given parameters.
13141ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     *
13241ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     * @param focusZoomFactor Controls the zoom factor used when an item view is focused. One of
13341ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     *         {@link FocusHighlight#ZOOM_FACTOR_NONE},
13441ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     *         {@link FocusHighlight#ZOOM_FACTOR_SMALL},
13541ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     *         {@link FocusHighlight#ZOOM_FACTOR_XSMALL},
13641ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     *         {@link FocusHighlight#ZOOM_FACTOR_MEDIUM},
13741ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     *         {@link FocusHighlight#ZOOM_FACTOR_LARGE}
13841ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     * @param useFocusDimmer determines if the FocusHighlighter will use the dimmer
13941ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     */
14041ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    public VerticalGridPresenter(int focusZoomFactor, boolean useFocusDimmer) {
14141ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield        mFocusZoomFactor = focusZoomFactor;
14241ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield        mUseFocusDimmer = useFocusDimmer;
143739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
144739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
145739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
146739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Sets the number of columns in the vertical grid.
147739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
148739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void setNumberOfColumns(int numColumns) {
149739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (numColumns < 0) {
150739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            throw new IllegalArgumentException("Invalid number of columns");
151739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
152739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (mNumColumns != numColumns) {
153739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            mNumColumns = numColumns;
154739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
155739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
156739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
157739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
158739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Returns the number of columns in the vertical grid.
159739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
160739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public int getNumberOfColumns() {
161739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        return mNumColumns;
162739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
163739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
1640d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout    /**
1650d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout     * Enable or disable child shadow.
1660d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout     * This is not only for enable/disable default shadow implementation but also subclass must
1670d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout     * respect this flag.
1680d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout     */
1690d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout    public final void setShadowEnabled(boolean enabled) {
1700d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout        mShadowEnabled = enabled;
1710d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout    }
1720d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout
1730d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout    /**
1740d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout     * Returns true if child shadow is enabled.
1750d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout     * This is not only for enable/disable default shadow implementation but also subclass must
1760d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout     * respect this flag.
1770d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout     */
1780d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout    public final boolean getShadowEnabled() {
1790d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout        return mShadowEnabled;
1800d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout    }
1810d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout
1820d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout    /**
1830d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout     * Returns true if opticalBounds is supported (SDK >= 18) so that default shadow
1840d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout     * is applied to each individual child of {@link VerticalGridView}.
1850d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout     * Subclass may return false to disable.
1860d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout     */
1870d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout    public boolean isUsingDefaultShadow() {
1884d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu        return ShadowOverlayHelper.supportsShadow();
1890d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout    }
1900d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout
19174ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu    /**
1924f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout     * Enables or disabled rounded corners on children of this row.
1934f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout     * Supported on Android SDK >= L.
1944f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout     */
1954f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    public final void enableChildRoundedCorners(boolean enable) {
1964f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout        mRoundedCornersEnabled = enable;
1974f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    }
1984f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout
1994f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    /**
2004f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout     * Returns true if rounded corners are enabled for children of this row.
2014f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout     */
2024f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    public final boolean areChildRoundedCornersEnabled() {
2034f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout        return mRoundedCornersEnabled;
2044f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    }
2054f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout
2064f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    /**
20774ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu     * Returns true if SDK >= L, where Z shadow is enabled so that Z order is enabled
20874ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu     * on each child of vertical grid.   If subclass returns false in isUsingDefaultShadow()
20974ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu     * and does not use Z-shadow on SDK >= L, it should override isUsingZOrder() return false.
21074ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu     */
211f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stout    public boolean isUsingZOrder(Context context) {
2124d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu        return !Settings.getInstance(context).preferStaticShadows();
21374ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu    }
21474ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu
2150d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout    final boolean needsDefaultShadow() {
2160d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout        return isUsingDefaultShadow() && getShadowEnabled();
2170d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout    }
2180d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout
21941ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    /**
22041ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     * Returns the zoom factor used for focus highlighting.
22141ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     */
22241ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    public final int getFocusZoomFactor() {
22341ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield        return mFocusZoomFactor;
22441ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    }
22541ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield
22641ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    /**
22741ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     * Returns true if the focus dimmer is used for focus highlighting; false otherwise.
22841ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield     */
22941ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    public final boolean isFocusDimmerUsed() {
23041ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield        return mUseFocusDimmer;
23141ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield    }
23241ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield
233739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    @Override
234739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public final ViewHolder onCreateViewHolder(ViewGroup parent) {
235739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        ViewHolder vh = createGridViewHolder(parent);
236739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        vh.mInitialized = false;
23771fddded48048acfa744ac352166770c91a1c2b1Dake Gu        vh.mItemBridgeAdapter = new VerticalGridItemBridgeAdapter();
238739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        initializeGridViewHolder(vh);
239739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (!vh.mInitialized) {
240739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            throw new RuntimeException("super.initializeGridViewHolder() must be called");
241739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
242739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        return vh;
243739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
244739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
245739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
246739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Subclass may override this to inflate a different layout.
247739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     */
248739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    protected ViewHolder createGridViewHolder(ViewGroup parent) {
249739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        View root = LayoutInflater.from(parent.getContext()).inflate(
250cb13a318e577e14461eb008071dddf762847de42Dake Gu                R.layout.lb_vertical_grid, parent, false);
251739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        return new ViewHolder((VerticalGridView) root.findViewById(R.id.browse_grid));
252739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
253739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
25474ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu    /**
25574ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu     * Called after a {@link VerticalGridPresenter.ViewHolder} is created.
25674ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu     * Subclasses may override this method and start by calling
25774ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu     * super.initializeGridViewHolder(ViewHolder).
25874ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu     *
25974ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu     * @param vh The ViewHolder to initialize for the vertical grid.
26074ecd2848a6ceaed6a4dcaed4748b4fb688de020Dake Gu     */
261739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    protected void initializeGridViewHolder(ViewHolder vh) {
262739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (mNumColumns == -1) {
263739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            throw new IllegalStateException("Number of columns must be set");
264739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        }
265739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (DEBUG) Log.v(TAG, "mNumColumns " + mNumColumns);
266739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        vh.getGridView().setNumColumns(mNumColumns);
267739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        vh.mInitialized = true;
268739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
2694d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu        Context context = vh.mGridView.getContext();
2704d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu        if (mShadowOverlayHelper == null) {
27185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            mShadowOverlayHelper = new ShadowOverlayHelper.Builder()
27285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    .needsOverlay(mUseFocusDimmer)
27385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    .needsShadow(needsDefaultShadow())
27485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    .needsRoundedCorner(areChildRoundedCornersEnabled())
27585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    .preferZOrder(isUsingZOrder(context))
27685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    .keepForegroundDrawable(mKeepChildForeground)
27785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    .options(createShadowOverlayOptions())
27885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                    .build(context);
27985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            if (mShadowOverlayHelper.needsWrapper()) {
28085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                mShadowOverlayWrapper = new ItemBridgeAdapterShadowOverlayWrapper(
28185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu                        mShadowOverlayHelper);
28285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu            }
2830d734cb6671b314f84cb4911cd37631177d07fbaCraig Stout        }
28485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        vh.mItemBridgeAdapter.setWrapper(mShadowOverlayWrapper);
2854d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu        mShadowOverlayHelper.prepareParentForShadow(vh.mGridView);
2864d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu        vh.getGridView().setFocusDrawingOrderEnabled(mShadowOverlayHelper.getShadowType()
2874d14fb53ebf304ad989afbc57baa71cfcafa4e7aDake Gu                == ShadowOverlayHelper.SHADOW_STATIC);
28846e7de54775fc37dc51041629c79249e6dae3242Dake Gu        FocusHighlightHelper.setupBrowseItemFocusHighlight(vh.mItemBridgeAdapter,
28941ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield                mFocusZoomFactor, mUseFocusDimmer);
290739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
291739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        final ViewHolder gridViewHolder = vh;
292739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        vh.getGridView().setOnChildSelectedListener(new OnChildSelectedListener() {
293739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            @Override
294739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            public void onChildSelected(ViewGroup parent, View view, int position, long id) {
295739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout                selectChildView(gridViewHolder, view);
296739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout            }
297739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        });
298739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
299739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
30085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    /**
30185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * Set if keeps foreground of child of this grid, the foreground will not
30285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * be used for overlay color.  Default value is true.
30385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     *
30485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * @param keep   True if keep foreground of child of this grid.
30585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     */
30685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    public final void setKeepChildForeground(boolean keep) {
30785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        mKeepChildForeground = keep;
30885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    }
30985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
31085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    /**
31185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * Returns true if keeps foreground of child of this grid, the foreground will not
31285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * be used for overlay color.  Default value is true.
31385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     *
31485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * @return   True if keeps foreground of child of this grid.
31585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     */
31685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    public final boolean getKeepChildForeground() {
31785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        return mKeepChildForeground;
31885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    }
31985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
32085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    /**
32185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * Create ShadowOverlayHelper Options.  Subclass may override.
32285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * e.g.
32385833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * <code>
32485833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * return new ShadowOverlayHelper.Options().roundedCornerRadius(10);
32585833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * </code>
32685833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     *
32785833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     * @return   The options to be used for shadow, overlay and rouded corner.
32885833087b2288e0f002de6b4ebcbc0564839a217Dake Gu     */
32985833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    protected ShadowOverlayHelper.Options createShadowOverlayOptions() {
33085833087b2288e0f002de6b4ebcbc0564839a217Dake Gu        return ShadowOverlayHelper.Options.DEFAULT;
33185833087b2288e0f002de6b4ebcbc0564839a217Dake Gu    }
33285833087b2288e0f002de6b4ebcbc0564839a217Dake Gu
333739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    @Override
334739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
335739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (DEBUG) Log.v(TAG, "onBindViewHolder " + item);
336739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        ViewHolder vh = (ViewHolder) viewHolder;
337739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        vh.mItemBridgeAdapter.setAdapter((ObjectAdapter) item);
338739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        vh.getGridView().setAdapter(vh.mItemBridgeAdapter);
339739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
340739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
341739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    @Override
342739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
343739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        if (DEBUG) Log.v(TAG, "onUnbindViewHolder");
344739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        ViewHolder vh = (ViewHolder) viewHolder;
345739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        vh.mItemBridgeAdapter.setAdapter(null);
346739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        vh.getGridView().setAdapter(null);
347739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    }
348739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout
349739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    /**
350739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Sets the item selected listener.
351739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Since this is a grid the row parameter is always null.
352947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu     */
353947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    public final void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) {
354947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu        mOnItemViewSelectedListener = listener;
355947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    }
356947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu
357947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    /**
358947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu     * Returns the item selected listener.
359947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu     */
360947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    public final OnItemViewSelectedListener getOnItemViewSelectedListener() {
361947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu        return mOnItemViewSelectedListener;
362947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    }
363947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu
364947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    /**
365739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Sets the item clicked listener.
366947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu     * OnItemViewClickedListener will override {@link View.OnClickListener} that
367947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu     * item presenter sets during {@link Presenter#onCreateViewHolder(ViewGroup)}.
368947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu     * So in general, developer should choose one of the listeners but not both.
369947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu     */
370947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    public final void setOnItemViewClickedListener(OnItemViewClickedListener listener) {
371947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu        mOnItemViewClickedListener = listener;
372947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    }
373947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu
374947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    /**
375739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Returns the item clicked listener.
376947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu     */
377947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    public final OnItemViewClickedListener getOnItemViewClickedListener() {
378947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu        return mOnItemViewClickedListener;
379947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    }
380947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu
381739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout    private void selectChildView(ViewHolder vh, View view) {
382947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu        if (getOnItemViewSelectedListener() != null) {
383947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu            ItemBridgeAdapter.ViewHolder ibh = (view == null) ? null :
384947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu                    (ItemBridgeAdapter.ViewHolder) vh.getGridView().getChildViewHolder(view);
385947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu            if (ibh == null) {
386947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu                getOnItemViewSelectedListener().onItemSelected(null, null, null, null);
387947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu            } else {
388947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu                getOnItemViewSelectedListener().onItemSelected(ibh.mHolder, ibh.mItem, null, null);
389947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu            }
390947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu        }
391947dbf076cd019e3c26217fbc7aa21e860d68044Dake Gu    }
392786ba352397f44022617411936515fc9eb28d23fDake Gu
393786ba352397f44022617411936515fc9eb28d23fDake Gu    /**
394786ba352397f44022617411936515fc9eb28d23fDake Gu     * Changes the visibility of views.  The entrance transition will be run against the views that
395786ba352397f44022617411936515fc9eb28d23fDake Gu     * change visibilities.  This method is called by the fragment, it should not be called
396786ba352397f44022617411936515fc9eb28d23fDake Gu     * directly by the application.
397786ba352397f44022617411936515fc9eb28d23fDake Gu     *
398786ba352397f44022617411936515fc9eb28d23fDake Gu     * @param holder         The ViewHolder for the vertical grid.
399786ba352397f44022617411936515fc9eb28d23fDake Gu     * @param afterEntrance  true if children of vertical grid participating in entrance transition
400786ba352397f44022617411936515fc9eb28d23fDake Gu     *                       should be set to visible, false otherwise.
401786ba352397f44022617411936515fc9eb28d23fDake Gu     */
402786ba352397f44022617411936515fc9eb28d23fDake Gu    public void setEntranceTransitionState(VerticalGridPresenter.ViewHolder holder,
403786ba352397f44022617411936515fc9eb28d23fDake Gu            boolean afterEntrance) {
404786ba352397f44022617411936515fc9eb28d23fDake Gu        holder.mGridView.setChildrenVisibility(afterEntrance? View.VISIBLE : View.INVISIBLE);
405786ba352397f44022617411936515fc9eb28d23fDake Gu    }
406739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout}
407