13f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song/*
23f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Copyright (C) 2015 The Android Open Source Project
33f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song *
43f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Licensed under the Apache License, Version 2.0 (the "License");
53f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * you may not use this file except in compliance with the License.
63f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * You may obtain a copy of the License at
73f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song *
83f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song *      http://www.apache.org/licenses/LICENSE-2.0
93f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song *
103f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Unless required by applicable law or agreed to in writing, software
113f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * distributed under the License is distributed on an "AS IS" BASIS,
123f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * See the License for the specific language governing permissions and
143f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * limitations under the License.
153f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */
163f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songpackage com.android.launcher3.widget;
173f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
18abef55a1c1f1fda4f42e4b4223534dd21f3dc19fAndrew Sappersteinimport android.content.Context;
190e08f166fafd5e2a0d32e27ea510516e3f762221Sunny Goyalimport android.support.v7.widget.RecyclerView;
203f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.support.v7.widget.RecyclerView.Adapter;
213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.util.Log;
223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.view.LayoutInflater;
233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.view.View;
248e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Songimport android.view.View.OnClickListener;
258e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Songimport android.view.View.OnLongClickListener;
263f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.view.ViewGroup;
27f52abd7758b8f245522936e941336e574debabf5Sunny Goyal
283f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.R;
293f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.WidgetPreviewLoader;
30d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyalimport com.android.launcher3.compat.AlphabeticIndexCompat;
31d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyalimport com.android.launcher3.model.PackageItemInfo;
324ddc40130aa0460924364eab3557088421eebe0cSunny Goyalimport com.android.launcher3.model.WidgetItem;
33d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyalimport com.android.launcher3.util.LabelComparator;
34d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyalimport com.android.launcher3.util.MultiHashMap;
3526b1746593851e239bfff65ae7a69b809ad87b99Tony Wickhamimport com.android.launcher3.util.PackageUserKey;
36f52abd7758b8f245522936e941336e574debabf5Sunny Goyal
37d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyalimport java.util.ArrayList;
38d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyalimport java.util.Collections;
39d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyalimport java.util.Comparator;
4026b1746593851e239bfff65ae7a69b809ad87b99Tony Wickhamimport java.util.Iterator;
413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport java.util.List;
42d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyalimport java.util.Map;
433f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
443f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song/**
453f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * List view adapter for the widget tray.
463f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song *
473f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * <p>Memory vs. Performance:
483f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * The less number of types of views are inserted into a {@link RecyclerView}, the more recycling
493f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * happens and less memory is consumed. {@link #getItemViewType} was not overridden as there is
503f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * only a single type of view.
513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song */
523f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songpublic class WidgetsListAdapter extends Adapter<WidgetsRowViewHolder> {
533f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
543f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    private static final String TAG = "WidgetsListAdapter";
55289ec3af9a1cd121a221235e0a27d4455e85efdfHyunyoung Song    private static final boolean DEBUG = false;
563f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
5781259cd086f8d7a0451f32d6e09cbda26f85ee38Sunny Goyal    private final WidgetPreviewLoader mWidgetPreviewLoader;
5881259cd086f8d7a0451f32d6e09cbda26f85ee38Sunny Goyal    private final LayoutInflater mLayoutInflater;
59d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal    private final AlphabeticIndexCompat mIndexer;
603f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
618e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song    private final OnClickListener mIconClickListener;
628e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song    private final OnLongClickListener mIconLongClickListener;
63756cd26592dee6b956becdc24d60995c64de9153Sunny Goyal    private final int mIndent;
648e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song    private ArrayList<WidgetListRowEntry> mEntries = new ArrayList<>();
658e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song    private final WidgetsDiffReporter mDiffReporter;
668e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song
678e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song    public WidgetsListAdapter(Context context, LayoutInflater layoutInflater,
688e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            WidgetPreviewLoader widgetPreviewLoader, AlphabeticIndexCompat indexCompat,
698e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            OnClickListener iconClickListener, OnLongClickListener iconLongClickListener,
708e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            WidgetsDiffReporter diffReporter) {
718e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song        mLayoutInflater = layoutInflater;
728e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song        mWidgetPreviewLoader = widgetPreviewLoader;
738e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song        mIndexer = indexCompat;
743f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        mIconClickListener = iconClickListener;
753f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        mIconLongClickListener = iconLongClickListener;
76abef55a1c1f1fda4f42e4b4223534dd21f3dc19fAndrew Sapperstein        mIndent = context.getResources().getDimensionPixelSize(R.dimen.widget_section_indent);
778e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song        mDiffReporter = diffReporter;
783f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    }
793f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
808e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song    public void setNotifyListener() {
818e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song        mDiffReporter.setListener(new WidgetsDiffReporter.NotifyListener() {
828e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            @Override
838e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            public void notifyDataSetChanged() {
848e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song                WidgetsListAdapter.this.notifyDataSetChanged();
858e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            }
868e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song
878e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            @Override
888e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            public void notifyItemChanged(int index) {
898e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song                WidgetsListAdapter.this.notifyItemChanged(index);
908e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            }
918e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song
928e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            @Override
938e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            public void notifyItemInserted(int index) {
948e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song                WidgetsListAdapter.this.notifyItemInserted(index);
958e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            }
968e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song
978e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            @Override
988e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            public void notifyItemRemoved(int index) {
998e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song                WidgetsListAdapter.this.notifyItemRemoved(index);
1008e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            }
1018e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song        });
1028e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song    }
1038e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song
1048e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song    /**
1058e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song     * Update the widget list.
1068e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song     */
107d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal    public void setWidgets(MultiHashMap<PackageItemInfo, WidgetItem> widgets) {
1088e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song        ArrayList<WidgetListRowEntry> tempEntries = new ArrayList<>();
109d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal
1108e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song        WidgetItemComparator widgetComparator = new WidgetItemComparator();
111d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        for (Map.Entry<PackageItemInfo, ArrayList<WidgetItem>> entry : widgets.entrySet()) {
112d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal            WidgetListRowEntry row = new WidgetListRowEntry(entry.getKey(), entry.getValue());
113d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal            row.titleSectionName = mIndexer.computeSectionName(row.pkgItem.title);
114d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal            Collections.sort(row.widgets, widgetComparator);
1158e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song            tempEntries.add(row);
116d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        }
1178e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song        WidgetListRowEntryComparator rowComparator = new WidgetListRowEntryComparator();
1188e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song        Collections.sort(tempEntries, rowComparator);
1198e5464b544a54813fc2492dd6f916c596effb676Hyunyoung Song        mDiffReporter.process(mEntries, tempEntries, rowComparator);
1203f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    }
1213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
1223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    @Override
1233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    public int getItemCount() {
124d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        return mEntries.size();
125d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal    }
126d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal
127d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal    public String getSectionName(int pos) {
128d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        return mEntries.get(pos).titleSectionName;
1293f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    }
1303f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
13126b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham    /**
13226b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham     * Copies and returns the widgets associated with the package and user of the ComponentKey.
13326b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham     */
13426b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham    public List<WidgetItem> copyWidgetsForPackageUser(PackageUserKey packageUserKey) {
13526b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham        for (WidgetListRowEntry entry : mEntries) {
13626b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham            if (entry.pkgItem.packageName.equals(packageUserKey.mPackageName)) {
13726b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham                ArrayList<WidgetItem> widgets = new ArrayList<>(entry.widgets);
13826b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham                // Remove widgets not associated with the correct user.
13926b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham                Iterator<WidgetItem> iterator = widgets.iterator();
14026b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham                while (iterator.hasNext()) {
14126b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham                    if (!iterator.next().user.equals(packageUserKey.mUser)) {
14226b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham                        iterator.remove();
14326b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham                    }
14426b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham                }
14526b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham                return widgets.isEmpty() ? null : widgets;
14626b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham            }
14726b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham        }
14826b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham        return null;
14926b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham    }
15026b1746593851e239bfff65ae7a69b809ad87b99Tony Wickham
1513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    @Override
1523f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    public void onBindViewHolder(WidgetsRowViewHolder holder, int pos) {
153d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        WidgetListRowEntry entry = mEntries.get(pos);
154d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        List<WidgetItem> infoList = entry.widgets;
1553f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
15681259cd086f8d7a0451f32d6e09cbda26f85ee38Sunny Goyal        ViewGroup row = holder.cellContainer;
1573f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        if (DEBUG) {
1583f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song            Log.d(TAG, String.format(
1594e8fb91cf19b7d621de8cbed2bde2c8dac734121Hyunyoung Song                    "onBindViewHolder [pos=%d, widget#=%d, row.getChildCount=%d]",
1604e8fb91cf19b7d621de8cbed2bde2c8dac734121Hyunyoung Song                    pos, infoList.size(), row.getChildCount()));
1613f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        }
1623f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
1633f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        // Add more views.
1643f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        // if there are too many, hide them.
165d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal        int expectedChildCount = infoList.size() + Math.max(0, infoList.size() - 1);
166d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal        int childCount = row.getChildCount();
167d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal
168d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal        if (expectedChildCount > childCount) {
169d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal            for (int i = childCount ; i < expectedChildCount; i++) {
170d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                if ((i & 1) == 1) {
171d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                    // Add a divider for odd index
172d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                    mLayoutInflater.inflate(R.layout.widget_list_divider, row);
173d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                } else {
174d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                    // Add cell for even index
175d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                    WidgetCell widget = (WidgetCell) mLayoutInflater.inflate(
176d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                            R.layout.widget_cell, row, false);
177d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal
178d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                    // set up touch.
179d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                    widget.setOnClickListener(mIconClickListener);
180d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                    widget.setOnLongClickListener(mIconLongClickListener);
181d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                    row.addView(widget);
182d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                }
1833f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song            }
184d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal        } else if (expectedChildCount < childCount) {
185d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal            for (int i = expectedChildCount ; i < childCount; i++) {
1863f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song                row.getChildAt(i).setVisibility(View.GONE);
1873f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song            }
1883f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        }
1893f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
1903f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        // Bind the views in the application info section.
191d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        holder.title.applyFromPackageItemInfo(entry.pkgItem);
1923f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
1933f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        // Bind the view in the widget horizontal tray region.
1943f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        for (int i=0; i < infoList.size(); i++) {
195d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal            WidgetCell widget = (WidgetCell) row.getChildAt(2*i);
1964ddc40130aa0460924364eab3557088421eebe0cSunny Goyal            widget.applyFromCellItem(infoList.get(i), mWidgetPreviewLoader);
1973f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song            widget.ensurePreview();
1986babf2e27e6260f02751413b8f7a55e46659af27Hyunyoung Song            widget.setVisibility(View.VISIBLE);
199d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal
200d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal            if (i > 0) {
201d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal                row.getChildAt(2*i - 1).setVisibility(View.VISIBLE);
202d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal            }
2033f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        }
2043f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    }
2053f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
2063f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    @Override
2073f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    public WidgetsRowViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
2083f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        if (DEBUG) {
209559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song            Log.v(TAG, "\nonCreateViewHolder");
2103f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        }
2113f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
2123f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        ViewGroup container = (ViewGroup) mLayoutInflater.inflate(
2133f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song                R.layout.widgets_list_row_view, parent, false);
2146fdc2035ea04aefc09d54a1943eef168ca270d6dHyunyoung Song
2156fdc2035ea04aefc09d54a1943eef168ca270d6dHyunyoung Song        // if the end padding is 0, then container view (horizontal scroll view) doesn't respect
2166fdc2035ea04aefc09d54a1943eef168ca270d6dHyunyoung Song        // the end of the linear layout width + the start padding and doesn't allow scrolling.
217d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal        container.findViewById(R.id.widgets_cell_list).setPaddingRelative(mIndent, 0, 1, 0);
2186fdc2035ea04aefc09d54a1943eef168ca270d6dHyunyoung Song
2193f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        return new WidgetsRowViewHolder(container);
2203f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    }
2213f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
2223f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    @Override
223f17a1c9ad99d46a65de797422fd439382114b348Hyunyoung Song    public void onViewRecycled(WidgetsRowViewHolder holder) {
22481259cd086f8d7a0451f32d6e09cbda26f85ee38Sunny Goyal        int total = holder.cellContainer.getChildCount();
225d5d5e22715c19c361d264693929c15c4325e80faSunny Goyal        for (int i = 0; i < total; i+=2) {
22681259cd086f8d7a0451f32d6e09cbda26f85ee38Sunny Goyal            WidgetCell widget = (WidgetCell) holder.cellContainer.getChildAt(i);
227559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song            widget.clear();
228f17a1c9ad99d46a65de797422fd439382114b348Hyunyoung Song        }
229f17a1c9ad99d46a65de797422fd439382114b348Hyunyoung Song    }
230f17a1c9ad99d46a65de797422fd439382114b348Hyunyoung Song
2312d58471e8d3da621e209cec58a43d159778f8a0eWinson Chung    public boolean onFailedToRecycleView(WidgetsRowViewHolder holder) {
2322d58471e8d3da621e209cec58a43d159778f8a0eWinson Chung        // If child views are animating, then the RecyclerView may choose not to recycle the view,
2332d58471e8d3da621e209cec58a43d159778f8a0eWinson Chung        // causing extraneous onCreateViewHolder() calls.  It is safe in this case to continue
2342d58471e8d3da621e209cec58a43d159778f8a0eWinson Chung        // recycling this view, and take care in onViewRecycled() to cancel any existing
2352d58471e8d3da621e209cec58a43d159778f8a0eWinson Chung        // animations.
2362d58471e8d3da621e209cec58a43d159778f8a0eWinson Chung        return true;
2372d58471e8d3da621e209cec58a43d159778f8a0eWinson Chung    }
2382d58471e8d3da621e209cec58a43d159778f8a0eWinson Chung
2392d58471e8d3da621e209cec58a43d159778f8a0eWinson Chung    @Override
2403f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    public long getItemId(int pos) {
2413f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        return pos;
2423f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    }
243d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal
244d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal    /**
245d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal     * Comparator for sorting WidgetListRowEntry based on package title
246d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal     */
247d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal    public static class WidgetListRowEntryComparator implements Comparator<WidgetListRowEntry> {
248d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal
249d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        private final LabelComparator mComparator = new LabelComparator();
250d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal
251d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        @Override
252d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        public int compare(WidgetListRowEntry a, WidgetListRowEntry b) {
253d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal            return mComparator.compare(a.pkgItem.title.toString(), b.pkgItem.title.toString());
254d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        }
255d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal    }
256d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal
2573f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song}
258