17ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout/*
27ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Copyright (C) 2014 The Android Open Source Project
37ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout *
47ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
57ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * in compliance with the License. You may obtain a copy of the License at
67ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout *
77ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * http://www.apache.org/licenses/LICENSE-2.0
87ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout *
97ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Unless required by applicable law or agreed to in writing, software distributed under the License
107ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
117ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * or implied. See the License for the specific language governing permissions and limitations under
127ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * the License.
137ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout */
147ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutpackage android.support.v17.leanback.widget;
157ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
16aa93f6777233b789feb14d95d900b158d0ac4841Craig Stoutimport android.content.Context;
177ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.support.v17.leanback.R;
187ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.util.SparseArray;
197ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.view.LayoutInflater;
207ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.view.View;
217ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.view.ViewGroup;
227ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.widget.LinearLayout;
237ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
247ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout/**
257ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * A presenter that assumes a LinearLayout container for a series
267ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * of control buttons backed by objects of type {@link Action}.
277ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout *
287ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Different layouts may be passed to the presenter constructor.
297ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * The layout must contain a view with id control_bar.
307ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout */
317ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutclass ControlBarPresenter extends Presenter {
327ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
337ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    private static final int MAX_CONTROLS = 7;
347ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
357ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
367ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * The data type expected by this presenter.
377ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
387ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    static class BoundData {
397ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        /**
407ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout         * Adapter containing objects of type {@link Action}.
417ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout         */
427ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        ObjectAdapter adapter;
437ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
447ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        /**
457ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout         * The presenter to be used for the adapter objects.
467ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout         */
477ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        Presenter presenter;
487ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
497ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
507ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
51cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout     * Listener for control selected events.
527ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
53cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    interface OnControlSelectedListener {
54cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        void onControlSelected(Presenter.ViewHolder controlViewHolder, Object item,
55cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                BoundData data);
56cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    }
57cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout
58cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    /**
59cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout     * Listener for control clicked events.
60cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout     */
61cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    interface OnControlClickedListener {
62cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        void onControlClicked(Presenter.ViewHolder controlViewHolder, Object item,
63cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                BoundData data);
64cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    }
65cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout
667ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    class ViewHolder extends Presenter.ViewHolder {
677ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        ObjectAdapter mAdapter;
68cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        BoundData mData;
697ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        Presenter mPresenter;
70aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        ControlBar mControlBar;
717ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        SparseArray<Presenter.ViewHolder> mViewHolders =
727ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                new SparseArray<Presenter.ViewHolder>();
737ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        ObjectAdapter.DataObserver mDataObserver;
747ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
757ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        /**
767ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout         * Constructor for the ViewHolder.
777ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout         */
787ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        ViewHolder(View rootView) {
797ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            super(rootView);
80aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout            mControlBar = (ControlBar) rootView.findViewById(R.id.control_bar);
817ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            if (mControlBar == null) {
827ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                throw new IllegalStateException("Couldn't find control_bar");
837ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            }
844cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout            mControlBar.setOnChildFocusedListener(new ControlBar.OnChildFocusedListener() {
854cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                @Override
864cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                public void onChildFocusedListener(View child, View focused) {
87cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    if (mOnControlSelectedListener == null) {
884cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                        return;
894cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                    }
904cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                    for (int position = 0; position < mViewHolders.size(); position++) {
914cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                        if (mViewHolders.get(position).view == child) {
92cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                            mOnControlSelectedListener.onControlSelected(
93cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                    mViewHolders.get(position),
94cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                    getDisplayedAdapter().get(position), mData);
954cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                            break;
964cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                        }
974cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                    }
984cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout                }
994cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout            });
1007ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            mDataObserver = new ObjectAdapter.DataObserver() {
1017ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                @Override
1027ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                public void onChanged() {
103aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                    if (mAdapter == getDisplayedAdapter()) {
104aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                        showControls(mPresenter);
105aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                    }
1067ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                }
1077ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                @Override
1087ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                public void onItemRangeChanged(int positionStart, int itemCount) {
109aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                    if (mAdapter == getDisplayedAdapter()) {
110aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                        for (int i = 0; i < itemCount; i++) {
111aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                            bindControlToAction(positionStart + i, mPresenter);
112aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                        }
1137ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                    }
1147ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                }
1157ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            };
1167ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
1177ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
118aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        int getChildMarginFromCenter(Context context, int numControls) {
119aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout            // Includes margin between icons plus two times half the icon width.
120aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout            return getChildMarginDefault(context) + getControlIconWidth(context);
121aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        }
122aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout
123aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        void showControls(Presenter presenter) {
124aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            ObjectAdapter adapter = getDisplayedAdapter();
1255dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout            int adapterSize = adapter == null ? 0 : adapter.size();
126cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            // Shrink the number of attached views
127cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            View focusedView = mControlBar.getFocusedChild();
1285dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout            if (focusedView != null && adapterSize > 0 &&
1295dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout                    mControlBar.indexOfChild(focusedView) >= adapterSize) {
130cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                mControlBar.getChildAt(adapter.size() - 1).requestFocus();
131cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            }
1325dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout            for (int i = mControlBar.getChildCount() - 1; i >= adapterSize; i--) {
133cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                mControlBar.removeViewAt(i);
134cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            }
1355dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout            for (int position = 0; position < adapterSize && position < MAX_CONTROLS;
1367ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                    position++) {
1377ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                bindControlToAction(position, adapter, presenter);
1387ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            }
139aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout            mControlBar.setChildMarginFromCenter(
1405dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout                    getChildMarginFromCenter(mControlBar.getContext(), adapterSize));
1417ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
1427ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
143aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        void bindControlToAction(int position, Presenter presenter) {
144aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            bindControlToAction(position, getDisplayedAdapter(), presenter);
145aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        }
146aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout
147aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        private void bindControlToAction(final int position,
148aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                ObjectAdapter adapter, Presenter presenter) {
1497ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            Presenter.ViewHolder vh = mViewHolders.get(position);
1507ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            Object item = adapter.get(position);
1517ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            if (vh == null) {
1527ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                vh = presenter.onCreateViewHolder(mControlBar);
1537ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                mViewHolders.put(position, vh);
154cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout
155cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                final Presenter.ViewHolder itemViewHolder = vh;
1567ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                presenter.setOnClickListener(vh, new View.OnClickListener() {
1577ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                    @Override
1587ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                    public void onClick(View v) {
159aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                        Object item = getDisplayedAdapter().get(position);
160cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                        if (mOnControlClickedListener != null) {
161cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                            mOnControlClickedListener.onControlClicked(itemViewHolder, item,
162cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                    mData);
1637ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                        }
1647ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                    }
1657ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                });
1667ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            }
1677ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            if (vh.view.getParent() == null) {
1687ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout                mControlBar.addView(vh.view);
1697ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            }
1707ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            presenter.onBindViewHolder(vh, item);
1717ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
1727ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
173aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        /**
174aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout         * Returns the adapter currently bound to the displayed controls.
175aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout         * May be overridden in a subclass.
176aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout         */
177aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        ObjectAdapter getDisplayedAdapter() {
1787ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            return mAdapter;
1797ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
1807ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
1817ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
182cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    private OnControlClickedListener mOnControlClickedListener;
183cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    private OnControlSelectedListener mOnControlSelectedListener;
1847ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    private int mLayoutResourceId;
185aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout    private static int sChildMarginDefault;
186aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout    private static int sControlIconWidth;
1877ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
1887ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
1897ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * Constructor for a ControlBarPresenter.
1907ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     *
1917ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * @param layoutResourceId The resource id of the layout for this presenter.
1927ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
1937ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public ControlBarPresenter(int layoutResourceId) {
1947ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        mLayoutResourceId = layoutResourceId;
1957ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
1967ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
1977ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
1987ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * Returns the layout resource id.
1997ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
2007ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public int getLayoutResourceId() {
2017ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        return mLayoutResourceId;
2027ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
2037ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
2047ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
205cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout     * Sets the listener for control clicked events.
2067ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
207cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    public void setOnControlClickedListener(OnControlClickedListener listener) {
208cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        mOnControlClickedListener = listener;
2097ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
2107ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
2117ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
212cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout     * Returns the listener for control clicked events.
2137ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
214cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    public OnControlClickedListener getOnItemViewClickedListener() {
215cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        return mOnControlClickedListener;
2167ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
2177ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
2184cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout    /**
219cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout     * Sets the listener for control selection.
2204cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout     */
221cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    public void setOnControlSelectedListener(OnControlSelectedListener listener) {
222cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        mOnControlSelectedListener = listener;
2234cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout    }
2244cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout
2254cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout    /**
226cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout     * Returns the listener for control selection.
2274cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout     */
228cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    public OnControlSelectedListener getOnItemControlListener() {
229cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        return mOnControlSelectedListener;
2304cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout    }
2314cc255c1c9ce5f3a718970b6e0be2c3ae6abf9edCraig Stout
2327ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
2337ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) {
2347ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        View v = LayoutInflater.from(parent.getContext())
2357ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            .inflate(getLayoutResourceId(), parent, false);
2367ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        return new ViewHolder(v);
2377ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
2387ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
2397ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
2407ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public void onBindViewHolder(Presenter.ViewHolder holder, Object item) {
2417ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        ViewHolder vh = (ViewHolder) holder;
2427ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        BoundData data = (BoundData) item;
2437ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        if (vh.mAdapter != data.adapter) {
2447ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            vh.mAdapter = data.adapter;
2455dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout            if (vh.mAdapter != null) {
2465dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout                vh.mAdapter.registerObserver(vh.mDataObserver);
2475dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout            }
2487ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
2497ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        vh.mPresenter = data.presenter;
250cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        vh.mData = data;
251aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        vh.showControls(vh.mPresenter);
2527ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
2537ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
2547ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
2557ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public void onUnbindViewHolder(Presenter.ViewHolder holder) {
2567ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        ViewHolder vh = (ViewHolder) holder;
2575dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout        if (vh.mAdapter != null) {
2585dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout            vh.mAdapter.unregisterObserver(vh.mDataObserver);
2595dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout            vh.mAdapter = null;
2605dac2c723e1d50da356170a6f372dcbab1a7d83cCraig Stout        }
261cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        vh.mData = null;
2627ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
263aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout
264aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout    int getChildMarginDefault(Context context) {
265aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        if (sChildMarginDefault == 0) {
266aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout            sChildMarginDefault = context.getResources().getDimensionPixelSize(
267aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout                    R.dimen.lb_playback_controls_child_margin_default);
268aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        }
269aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        return sChildMarginDefault;
270aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout    }
271aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout
272aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout    int getControlIconWidth(Context context) {
273aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        if (sControlIconWidth == 0) {
274aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout            sControlIconWidth = context.getResources().getDimensionPixelSize(
275aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout                    R.dimen.lb_control_icon_width);
276aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        }
277aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout        return sControlIconWidth;
278aa93f6777233b789feb14d95d900b158d0ac4841Craig Stout    }
2797ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout}
280