package org.holoeverywhere.preference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.holoeverywhere.preference.Preference.OnPreferenceChangeInternalListener;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
class PreferenceGroupAdapter extends BaseAdapter implements
OnPreferenceChangeInternalListener {
private static class PreferenceLayout implements
Comparable<PreferenceLayout> {
private String name;
private int resId;
private int widgetResId;
@Override
public int compareTo(PreferenceLayout other) {
int compareNames = name.compareTo(other.name);
if (compareNames == 0) {
if (resId == other.resId) {
if (widgetResId == other.widgetResId) {
return 0;
} else {
return widgetResId - other.widgetResId;
}
} else {
return resId - other.resId;
}
} else {
return compareNames;
}
}
}
private Handler mHandler = new Handler();
private boolean mHasReturnedViewTypeCount = false;
private volatile boolean mIsSyncing = false;
private PreferenceGroup mPreferenceGroup;
private List<PreferenceLayout> mPreferenceLayouts;
private List<Preference> mPreferenceList;
private Runnable mSyncRunnable = new Runnable() {
@Override
public void run() {
syncMyPreferences();
}
};
private PreferenceLayout mTempPreferenceLayout = new PreferenceLayout();
public PreferenceGroupAdapter(PreferenceGroup preferenceGroup) {
mPreferenceGroup = preferenceGroup;
mPreferenceGroup.setOnPreferenceChangeInternalListener(this);
int c = preferenceGroup.getPreferenceCount();
mPreferenceList = new ArrayList<Preference>(c);
mPreferenceLayouts = new ArrayList<PreferenceLayout>(c);
syncMyPreferences();
}
private void addPreferenceClassName(Preference preference) {
final PreferenceLayout pl = createPreferenceLayout(preference, null);
int insertPos = Collections.binarySearch(mPreferenceLayouts, pl);
if (insertPos < 0) {
insertPos = insertPos * -1 - 1;
mPreferenceLayouts.add(insertPos, pl);
}
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
private PreferenceLayout createPreferenceLayout(Preference preference,
PreferenceLayout in) {
PreferenceLayout pl = in != null ? in : new PreferenceLayout();
pl.name = preference.getClass().getName();
pl.resId = preference.getLayoutResource();
pl.widgetResId = preference.getWidgetLayoutResource();
return pl;
}
private void flattenPreferenceGroup(List<Preference> preferences,
PreferenceGroup group) {
group.sortPreferences();
final int groupSize = group.getPreferenceCount();
for (int i = 0; i < groupSize; i++) {
final Preference preference = group.getPreference(i);
preferences.add(preference);
if (!mHasReturnedViewTypeCount && !preference.hasSpecifiedLayout()) {
addPreferenceClassName(preference);
}
if (preference instanceof PreferenceGroup) {
final PreferenceGroup preferenceAsGroup = (PreferenceGroup) preference;
if (preferenceAsGroup.isOnSameScreenAsChildren()) {
flattenPreferenceGroup(preferences, preferenceAsGroup);
}
}
preference.setOnPreferenceChangeInternalListener(this);
}
}
@Override
public int getCount() {
return mPreferenceList.size();
}
@Override
public Preference getItem(int position) {
if (position < 0 || position >= getCount()) {
return null;
}
return mPreferenceList.get(position);
}
@Override
public long getItemId(int position) {
if (position < 0 || position >= getCount()) {
return AdapterView.INVALID_ROW_ID;
}
return getItem(position).getId();
}
@Override
public int getItemViewType(int position) {
if (!mHasReturnedViewTypeCount) {
mHasReturnedViewTypeCount = true;
}
final Preference preference = getItem(position);
if (!preference.hasSpecifiedLayout()) {
return Adapter.IGNORE_ITEM_VIEW_TYPE;
}
mTempPreferenceLayout = createPreferenceLayout(preference,
mTempPreferenceLayout);
int viewType = Collections.binarySearch(mPreferenceLayouts,
mTempPreferenceLayout);
if (viewType < 0) {
return Adapter.IGNORE_ITEM_VIEW_TYPE;
} else {
return viewType;
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final Preference preference = getItem(position);
mTempPreferenceLayout = createPreferenceLayout(preference,
mTempPreferenceLayout);
if (Collections.binarySearch(mPreferenceLayouts, mTempPreferenceLayout) < 0) {
convertView = null;
}
return preference.getView(convertView, parent);
}
@Override
public int getViewTypeCount() {
if (!mHasReturnedViewTypeCount) {
mHasReturnedViewTypeCount = true;
}
return Math.max(1, mPreferenceLayouts.size());
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public boolean isEnabled(int position) {
if (position < 0 || position >= getCount()) {
return true;
}
return getItem(position).isSelectable();
}
@Override
public void onPreferenceChange(Preference preference) {
notifyDataSetChanged();
}
@Override
public void onPreferenceHierarchyChange(Preference preference) {
mHandler.removeCallbacks(mSyncRunnable);
mHandler.post(mSyncRunnable);
}
private void syncMyPreferences() {
synchronized (this) {
if (mIsSyncing) {
return;
}
mIsSyncing = true;
}
List<Preference> newPreferenceList = new ArrayList<Preference>(
mPreferenceList.size());
flattenPreferenceGroup(newPreferenceList, mPreferenceGroup);
mPreferenceList = newPreferenceList;
notifyDataSetChanged();
synchronized (this) {
mIsSyncing = false;
notifyAll();
}
}
}