1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14package android.support.v17.leanback.app;
15
16import android.support.annotation.ColorInt;
17import android.support.v17.leanback.R;
18import android.support.v17.leanback.widget.BrowseFrameLayout;
19import android.support.v17.leanback.widget.OnChildLaidOutListener;
20import android.support.v17.leanback.widget.OnItemViewClickedListener;
21import android.support.v17.leanback.widget.OnItemViewSelectedListener;
22import android.support.v17.leanback.widget.Presenter;
23import android.support.v17.leanback.widget.Row;
24import android.support.v17.leanback.widget.RowPresenter;
25import android.support.v17.leanback.widget.TitleHelper;
26import android.support.v17.leanback.widget.TitleView;
27import android.support.v17.leanback.widget.VerticalGridPresenter;
28import android.support.v17.leanback.widget.ObjectAdapter;
29import android.os.Bundle;
30import android.util.Log;
31import android.view.LayoutInflater;
32import android.view.View;
33import android.view.ViewGroup;
34
35/**
36 * A fragment for creating leanback vertical grids.
37 *
38 * <p>Renders a vertical grid of objects given a {@link VerticalGridPresenter} and
39 * an {@link ObjectAdapter}.
40 */
41public class VerticalGridFragment extends BrandedFragment {
42    private static final String TAG = "VerticalGridFragment";
43    private static boolean DEBUG = false;
44
45    private ObjectAdapter mAdapter;
46    private VerticalGridPresenter mGridPresenter;
47    private VerticalGridPresenter.ViewHolder mGridViewHolder;
48    private OnItemViewSelectedListener mOnItemViewSelectedListener;
49    private OnItemViewClickedListener mOnItemViewClickedListener;
50    private int mSelectedPosition = -1;
51
52    /**
53     * Sets the grid presenter.
54     */
55    public void setGridPresenter(VerticalGridPresenter gridPresenter) {
56        if (gridPresenter == null) {
57            throw new IllegalArgumentException("Grid presenter may not be null");
58        }
59        mGridPresenter = gridPresenter;
60        mGridPresenter.setOnItemViewSelectedListener(mViewSelectedListener);
61        if (mOnItemViewClickedListener != null) {
62            mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener);
63        }
64    }
65
66    /**
67     * Returns the grid presenter.
68     */
69    public VerticalGridPresenter getGridPresenter() {
70        return mGridPresenter;
71    }
72
73    /**
74     * Sets the object adapter for the fragment.
75     */
76    public void setAdapter(ObjectAdapter adapter) {
77        mAdapter = adapter;
78        updateAdapter();
79    }
80
81    /**
82     * Returns the object adapter.
83     */
84    public ObjectAdapter getAdapter() {
85        return mAdapter;
86    }
87
88    final private OnItemViewSelectedListener mViewSelectedListener =
89            new OnItemViewSelectedListener() {
90        @Override
91        public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
92                RowPresenter.ViewHolder rowViewHolder, Row row) {
93            int position = mGridViewHolder.getGridView().getSelectedPosition();
94            if (DEBUG) Log.v(TAG, "grid selected position " + position);
95            gridOnItemSelected(position);
96            if (mOnItemViewSelectedListener != null) {
97                mOnItemViewSelectedListener.onItemSelected(itemViewHolder, item,
98                        rowViewHolder, row);
99            }
100        }
101    };
102
103    final private OnChildLaidOutListener mChildLaidOutListener =
104            new OnChildLaidOutListener() {
105        @Override
106        public void onChildLaidOut(ViewGroup parent, View view, int position, long id) {
107            if (position == 0) {
108                showOrHideTitle();
109            }
110        }
111    };
112
113    /**
114     * Sets an item selection listener.
115     */
116    public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) {
117        mOnItemViewSelectedListener = listener;
118    }
119
120    private void gridOnItemSelected(int position) {
121        if (position != mSelectedPosition) {
122            mSelectedPosition = position;
123            showOrHideTitle();
124        }
125    }
126
127    private void showOrHideTitle() {
128        if (mGridViewHolder.getGridView().findViewHolderForAdapterPosition(mSelectedPosition)
129                == null) {
130            return;
131        }
132        if (!mGridViewHolder.getGridView().hasPreviousViewInSameRow(mSelectedPosition)) {
133            showTitle(true);
134        } else {
135            showTitle(false);
136        }
137    }
138
139    /**
140     * Sets an item clicked listener.
141     */
142    public void setOnItemViewClickedListener(OnItemViewClickedListener listener) {
143        mOnItemViewClickedListener = listener;
144        if (mGridPresenter != null) {
145            mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener);
146        }
147    }
148
149    /**
150     * Returns the item clicked listener.
151     */
152    public OnItemViewClickedListener getOnItemViewClickedListener() {
153        return mOnItemViewClickedListener;
154    }
155
156    @Override
157    public View onCreateView(LayoutInflater inflater, ViewGroup container,
158            Bundle savedInstanceState) {
159        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_vertical_grid_fragment,
160                container, false);
161        setTitleView((TitleView) root.findViewById(R.id.browse_title_group));
162        return root;
163    }
164
165    @Override
166    public void onViewCreated(View view, Bundle savedInstanceState) {
167        super.onViewCreated(view, savedInstanceState);
168        ViewGroup gridDock = (ViewGroup) view.findViewById(R.id.browse_grid_dock);
169        mGridViewHolder = mGridPresenter.onCreateViewHolder(gridDock);
170        gridDock.addView(mGridViewHolder.view);
171        mGridViewHolder.getGridView().setOnChildLaidOutListener(mChildLaidOutListener);
172
173        updateAdapter();
174    }
175
176    private void setupFocusSearchListener() {
177        BrowseFrameLayout browseFrameLayout = (BrowseFrameLayout) getView().findViewById(
178                R.id.grid_frame);
179        browseFrameLayout.setOnFocusSearchListener(getTitleHelper().getOnFocusSearchListener());
180    }
181
182    @Override
183    public void onStart() {
184        super.onStart();
185        setupFocusSearchListener();
186        mGridViewHolder.getGridView().requestFocus();
187    }
188
189    @Override
190    public void onDestroyView() {
191        super.onDestroyView();
192        mGridViewHolder = null;
193    }
194
195    /**
196     * Sets the selected item position.
197     */
198    public void setSelectedPosition(int position) {
199        mSelectedPosition = position;
200        if(mGridViewHolder != null && mGridViewHolder.getGridView().getAdapter() != null) {
201            mGridViewHolder.getGridView().setSelectedPositionSmooth(position);
202        }
203    }
204
205    private void updateAdapter() {
206        if (mGridViewHolder != null) {
207            mGridPresenter.onBindViewHolder(mGridViewHolder, mAdapter);
208            if (mSelectedPosition != -1) {
209                mGridViewHolder.getGridView().setSelectedPosition(mSelectedPosition);
210            }
211        }
212    }
213}
214