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.v17.leanback.R;
17import android.support.v17.leanback.transition.TransitionHelper;
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.VerticalGridPresenter;
26import android.support.v17.leanback.widget.ObjectAdapter;
27import android.os.Bundle;
28import android.util.Log;
29import android.view.LayoutInflater;
30import android.view.View;
31import android.view.ViewGroup;
32
33/**
34 * A fragment for creating leanback vertical grids.
35 *
36 * <p>Renders a vertical grid of objects given a {@link VerticalGridPresenter} and
37 * an {@link ObjectAdapter}.
38 */
39public class VerticalGridFragment extends BaseFragment {
40    private static final String TAG = "VerticalGridFragment";
41    private static boolean DEBUG = false;
42
43    private ObjectAdapter mAdapter;
44    private VerticalGridPresenter mGridPresenter;
45    private VerticalGridPresenter.ViewHolder mGridViewHolder;
46    private OnItemViewSelectedListener mOnItemViewSelectedListener;
47    private OnItemViewClickedListener mOnItemViewClickedListener;
48    private Object mSceneAfterEntranceTransition;
49    private int mSelectedPosition = -1;
50
51    /**
52     * Sets the grid presenter.
53     */
54    public void setGridPresenter(VerticalGridPresenter gridPresenter) {
55        if (gridPresenter == null) {
56            throw new IllegalArgumentException("Grid presenter may not be null");
57        }
58        mGridPresenter = gridPresenter;
59        mGridPresenter.setOnItemViewSelectedListener(mViewSelectedListener);
60        if (mOnItemViewClickedListener != null) {
61            mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener);
62        }
63    }
64
65    /**
66     * Returns the grid presenter.
67     */
68    public VerticalGridPresenter getGridPresenter() {
69        return mGridPresenter;
70    }
71
72    /**
73     * Sets the object adapter for the fragment.
74     */
75    public void setAdapter(ObjectAdapter adapter) {
76        mAdapter = adapter;
77        updateAdapter();
78    }
79
80    /**
81     * Returns the object adapter.
82     */
83    public ObjectAdapter getAdapter() {
84        return mAdapter;
85    }
86
87    final private OnItemViewSelectedListener mViewSelectedListener =
88            new OnItemViewSelectedListener() {
89        @Override
90        public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
91                RowPresenter.ViewHolder rowViewHolder, Row row) {
92            int position = mGridViewHolder.getGridView().getSelectedPosition();
93            if (DEBUG) Log.v(TAG, "grid selected position " + position);
94            gridOnItemSelected(position);
95            if (mOnItemViewSelectedListener != null) {
96                mOnItemViewSelectedListener.onItemSelected(itemViewHolder, item,
97                        rowViewHolder, row);
98            }
99        }
100    };
101
102    final private OnChildLaidOutListener mChildLaidOutListener =
103            new OnChildLaidOutListener() {
104        @Override
105        public void onChildLaidOut(ViewGroup parent, View view, int position, long id) {
106            if (position == 0) {
107                showOrHideTitle();
108            }
109        }
110    };
111
112    /**
113     * Sets an item selection listener.
114     */
115    public void setOnItemViewSelectedListener(OnItemViewSelectedListener listener) {
116        mOnItemViewSelectedListener = listener;
117    }
118
119    private void gridOnItemSelected(int position) {
120        if (position != mSelectedPosition) {
121            mSelectedPosition = position;
122            showOrHideTitle();
123        }
124    }
125
126    private void showOrHideTitle() {
127        if (mGridViewHolder.getGridView().findViewHolderForAdapterPosition(mSelectedPosition)
128                == null) {
129            return;
130        }
131        if (!mGridViewHolder.getGridView().hasPreviousViewInSameRow(mSelectedPosition)) {
132            showTitle(true);
133        } else {
134            showTitle(false);
135        }
136    }
137
138    /**
139     * Sets an item clicked listener.
140     */
141    public void setOnItemViewClickedListener(OnItemViewClickedListener listener) {
142        mOnItemViewClickedListener = listener;
143        if (mGridPresenter != null) {
144            mGridPresenter.setOnItemViewClickedListener(mOnItemViewClickedListener);
145        }
146    }
147
148    /**
149     * Returns the item clicked listener.
150     */
151    public OnItemViewClickedListener getOnItemViewClickedListener() {
152        return mOnItemViewClickedListener;
153    }
154
155    @Override
156    public View onCreateView(LayoutInflater inflater, ViewGroup container,
157            Bundle savedInstanceState) {
158        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_vertical_grid_fragment,
159                container, false);
160        ViewGroup gridFrame = (ViewGroup) root.findViewById(R.id.grid_frame);
161        installTitleView(inflater, gridFrame, savedInstanceState);
162        getProgressBarManager().setRootView(root);
163        return root;
164    }
165
166    @Override
167    public void onViewCreated(View view, Bundle savedInstanceState) {
168        super.onViewCreated(view, savedInstanceState);
169        ViewGroup gridDock = (ViewGroup) view.findViewById(R.id.browse_grid_dock);
170        mGridViewHolder = mGridPresenter.onCreateViewHolder(gridDock);
171        gridDock.addView(mGridViewHolder.view);
172        mGridViewHolder.getGridView().setOnChildLaidOutListener(mChildLaidOutListener);
173
174        mSceneAfterEntranceTransition = TransitionHelper.createScene(gridDock, new Runnable() {
175            @Override
176            public void run() {
177                setEntranceTransitionState(true);
178            }
179        });
180
181        updateAdapter();
182    }
183
184    private void setupFocusSearchListener() {
185        BrowseFrameLayout browseFrameLayout = (BrowseFrameLayout) getView().findViewById(
186                R.id.grid_frame);
187        browseFrameLayout.setOnFocusSearchListener(getTitleHelper().getOnFocusSearchListener());
188    }
189
190    @Override
191    public void onStart() {
192        super.onStart();
193        setupFocusSearchListener();
194        if (isEntranceTransitionEnabled()) {
195            setEntranceTransitionState(false);
196        }
197    }
198
199    @Override
200    public void onDestroyView() {
201        super.onDestroyView();
202        mGridViewHolder = null;
203    }
204
205    /**
206     * Sets the selected item position.
207     */
208    public void setSelectedPosition(int position) {
209        mSelectedPosition = position;
210        if(mGridViewHolder != null && mGridViewHolder.getGridView().getAdapter() != null) {
211            mGridViewHolder.getGridView().setSelectedPositionSmooth(position);
212        }
213    }
214
215    private void updateAdapter() {
216        if (mGridViewHolder != null) {
217            mGridPresenter.onBindViewHolder(mGridViewHolder, mAdapter);
218            if (mSelectedPosition != -1) {
219                mGridViewHolder.getGridView().setSelectedPosition(mSelectedPosition);
220            }
221        }
222    }
223
224    @Override
225    protected Object createEntranceTransition() {
226        return TransitionHelper.loadTransition(getActivity(),
227                R.transition.lb_vertical_grid_entrance_transition);
228    }
229
230    @Override
231    protected void runEntranceTransition(Object entranceTransition) {
232        TransitionHelper.runTransition(mSceneAfterEntranceTransition, entranceTransition);
233    }
234
235    void setEntranceTransitionState(boolean afterTransition) {
236        mGridPresenter.setEntranceTransitionState(mGridViewHolder, afterTransition);
237    }
238}
239