19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.preference;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2335d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglioimport android.graphics.drawable.Drawable;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.preference.Preference.OnPreferenceChangeInternalListener;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.Adapter;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.BaseAdapter;
305f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglioimport android.widget.FrameLayout;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.ListView;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An adapter that returns the {@link Preference} contained in this group.
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In most cases, this adapter should be the base class for any custom
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * adapters from {@link Preference#getAdapter()}.
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This adapter obeys the
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Preference}'s adapter rule (the
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Adapter#getView(int, View, ViewGroup)} should be used instead of
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Preference#getView(ViewGroup)} if a {@link Preference} has an
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * adapter via {@link Preference#getAdapter()}).
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This adapter also propagates data change/invalidated notifications upward.
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This adapter does not include this {@link PreferenceGroup} in the returned
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * adapter, use {@link PreferenceCategoryAdapter} instead.
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see PreferenceCategoryAdapter
5053c2cf799fddfae7f6fc9ca1840ea345308b79eeFabrice Di Meglio *
5153c2cf799fddfae7f6fc9ca1840ea345308b79eeFabrice Di Meglio * @hide
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
5353c2cf799fddfae7f6fc9ca1840ea345308b79eeFabrice Di Megliopublic class PreferenceGroupAdapter extends BaseAdapter
5453c2cf799fddfae7f6fc9ca1840ea345308b79eeFabrice Di Meglio        implements OnPreferenceChangeInternalListener {
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "PreferenceGroupAdapter";
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The group that we are providing data from.
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PreferenceGroup mPreferenceGroup;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Maps a position into this adapter -> {@link Preference}. These
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link Preference}s don't have to be direct children of this
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link PreferenceGroup}, they can be grand children or younger)
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private List<Preference> mPreferenceList;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * List of unique Preference and its subclasses' names. This is used to find
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * out how many types of views this adapter can return. Once the count is
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned, this cannot be modified (since the ListView only checks the
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * count once--when the adapter is being set). We will not recycle views for
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Preference subclasses seen after the count has been returned.
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
77a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani    private ArrayList<PreferenceLayout> mPreferenceLayouts;
78a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani
79a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani    private PreferenceLayout mTempPreferenceLayout = new PreferenceLayout();
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Blocks the mPreferenceClassNames from being changed anymore.
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mHasReturnedViewTypeCount = false;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private volatile boolean mIsSyncing = false;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Handler mHandler = new Handler();
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Runnable mSyncRunnable = new Runnable() {
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            syncMyPreferences();
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9635d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio    private int mHighlightedPosition = -1;
9735d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio    private Drawable mHighlightedDrawable;
9853c2cf799fddfae7f6fc9ca1840ea345308b79eeFabrice Di Meglio
995f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio    private static ViewGroup.LayoutParams sWrapperLayoutParams = new ViewGroup.LayoutParams(
1005f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
1015f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio
102a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani    private static class PreferenceLayout implements Comparable<PreferenceLayout> {
103a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        private int resId;
104a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        private int widgetResId;
105a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        private String name;
106a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani
107a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        public int compareTo(PreferenceLayout other) {
108a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani            int compareNames = name.compareTo(other.name);
109a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani            if (compareNames == 0) {
110a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani                if (resId == other.resId) {
111a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani                    if (widgetResId == other.widgetResId) {
112a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani                        return 0;
113a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani                    } else {
114a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani                        return widgetResId - other.widgetResId;
115a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani                    }
116a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani                } else {
117a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani                    return resId - other.resId;
118a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani                }
119a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani            } else {
120a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani                return compareNames;
121a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani            }
122a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        }
123a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani    }
124a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PreferenceGroupAdapter(PreferenceGroup preferenceGroup) {
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreferenceGroup = preferenceGroup;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If this group gets or loses any children, let us know
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreferenceGroup.setOnPreferenceChangeInternalListener(this);
129a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreferenceList = new ArrayList<Preference>();
131a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        mPreferenceLayouts = new ArrayList<PreferenceLayout>();
132a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        syncMyPreferences();
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void syncMyPreferences() {
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(this) {
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIsSyncing) {
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
141a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIsSyncing = true;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Preference> newPreferenceList = new ArrayList<Preference>(mPreferenceList.size());
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        flattenPreferenceGroup(newPreferenceList, mPreferenceGroup);
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreferenceList = newPreferenceList;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        notifyDataSetChanged();
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(this) {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIsSyncing = false;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notifyAll();
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void flattenPreferenceGroup(List<Preference> preferences, PreferenceGroup group) {
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: shouldn't always?
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        group.sortPreferences();
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int groupSize = group.getPreferenceCount();
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < groupSize; i++) {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final Preference preference = group.getPreference(i);
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            preferences.add(preference);
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1674186b344d829e155feebf6797bd41576fccb5f16Filip Pavlis            if (!mHasReturnedViewTypeCount && preference.isRecycleEnabled()) {
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                addPreferenceClassName(preference);
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (preference instanceof PreferenceGroup) {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final PreferenceGroup preferenceAsGroup = (PreferenceGroup) preference;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (preferenceAsGroup.isOnSameScreenAsChildren()) {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    flattenPreferenceGroup(preferences, preferenceAsGroup);
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            preference.setOnPreferenceChangeInternalListener(this);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
182a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani    /**
183a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani     * Creates a string that includes the preference name, layout id and widget layout id.
184a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani     * If a particular preference type uses 2 different resources, they will be treated as
185a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani     * different view types.
186a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani     */
187a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani    private PreferenceLayout createPreferenceLayout(Preference preference, PreferenceLayout in) {
188a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        PreferenceLayout pl = in != null? in : new PreferenceLayout();
189a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        pl.name = preference.getClass().getName();
190a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        pl.resId = preference.getLayoutResource();
191a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        pl.widgetResId = preference.getWidgetLayoutResource();
192a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        return pl;
193a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani    }
194a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void addPreferenceClassName(Preference preference) {
196a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        final PreferenceLayout pl = createPreferenceLayout(preference, null);
197a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        int insertPos = Collections.binarySearch(mPreferenceLayouts, pl);
198a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Only insert if it doesn't exist (when it is negative).
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (insertPos < 0) {
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Convert to insert index
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            insertPos = insertPos * -1 - 1;
203a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani            mPreferenceLayouts.add(insertPos, pl);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getCount() {
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mPreferenceList.size();
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Preference getItem(int position) {
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (position < 0 || position >= getCount()) return null;
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mPreferenceList.get(position);
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getItemId(int position) {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (position < 0 || position >= getCount()) return ListView.INVALID_ROW_ID;
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this.getItem(position).getId();
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22135d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio    /**
22235d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio     * @hide
22335d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio     */
22435d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio    public void setHighlighted(int position) {
22535d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio        mHighlightedPosition = position;
22635d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio    }
22735d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio
22835d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio    /**
22935d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio     * @hide
23035d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio     */
23135d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio    public void setHighlightedDrawable(Drawable drawable) {
23235d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio        mHighlightedDrawable = drawable;
23353c2cf799fddfae7f6fc9ca1840ea345308b79eeFabrice Di Meglio    }
23453c2cf799fddfae7f6fc9ca1840ea345308b79eeFabrice Di Meglio
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View getView(int position, View convertView, ViewGroup parent) {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Preference preference = this.getItem(position);
237a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        // Build a PreferenceLayout to compare with known ones that are cacheable.
238a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        mTempPreferenceLayout = createPreferenceLayout(preference, mTempPreferenceLayout);
239a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani
240a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        // If it's not one of the cached ones, set the convertView to null so that
241a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        // the layout gets re-created by the Preference.
2425f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio        if (Collections.binarySearch(mPreferenceLayouts, mTempPreferenceLayout) < 0 ||
2435f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio                (getItemViewType(position) == getHighlightItemViewType())) {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            convertView = null;
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
24653c2cf799fddfae7f6fc9ca1840ea345308b79eeFabrice Di Meglio        View result = preference.getView(convertView, parent);
24735d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio        if (position == mHighlightedPosition && mHighlightedDrawable != null) {
2485f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio            ViewGroup wrapper = new FrameLayout(parent.getContext());
2495f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio            wrapper.setLayoutParams(sWrapperLayoutParams);
2505f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio            wrapper.setBackgroundDrawable(mHighlightedDrawable);
2515f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio            wrapper.addView(result);
2525f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio            result = wrapper;
25335d7b89b9f6151083001e3bae315a8e98882741fFabrice Di Meglio        }
25453c2cf799fddfae7f6fc9ca1840ea345308b79eeFabrice Di Meglio        return result;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isEnabled(int position) {
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (position < 0 || position >= getCount()) return true;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this.getItem(position).isSelectable();
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean areAllItemsEnabled() {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // There should always be a preference group, and these groups are always
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // disabled
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onPreferenceChange(Preference preference) {
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        notifyDataSetChanged();
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onPreferenceHierarchyChange(Preference preference) {
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler.removeCallbacks(mSyncRunnable);
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler.post(mSyncRunnable);
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasStableIds() {
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2845f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio    private int getHighlightItemViewType() {
2855f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio        return getViewTypeCount() - 1;
2865f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio    }
2875f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getItemViewType(int position) {
2905f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio        if (position == mHighlightedPosition) {
2915f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio            return getHighlightItemViewType();
2925f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio        }
2935f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mHasReturnedViewTypeCount) {
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHasReturnedViewTypeCount = true;
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Preference preference = this.getItem(position);
2994186b344d829e155feebf6797bd41576fccb5f16Filip Pavlis        if (!preference.isRecycleEnabled()) {
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return IGNORE_ITEM_VIEW_TYPE;
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
303a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        mTempPreferenceLayout = createPreferenceLayout(preference, mTempPreferenceLayout);
304a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani
305a98129b9110371aa036d8fcf23fff709595b16ffAmith Yamasani        int viewType = Collections.binarySearch(mPreferenceLayouts, mTempPreferenceLayout);
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (viewType < 0) {
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This is a class that was seen after we returned the count, so
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // don't recycle it.
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return IGNORE_ITEM_VIEW_TYPE;
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return viewType;
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getViewTypeCount() {
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mHasReturnedViewTypeCount) {
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHasReturnedViewTypeCount = true;
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3215f9f6c3936a8a266bb5dcd31e94d403917f1bbe8Fabrice Di Meglio        return Math.max(1, mPreferenceLayouts.size()) + 1;
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
325