package me.barrasso.android.volume.activities;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.preference.ListPreference;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.LruCache;
import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import me.barrasso.android.volume.LogUtils;
import me.barrasso.android.volume.R;
/**
* {@link android.preference.ListPreference} but with the the following additions:
* <br />
* <ul>
* <li>It supports an images (centered, top) that's full width.</li>
* <li>It supports a "pro" banner to inform the user of an IAP.</li>
* </ul>
*/
public class ImageListPreference extends ListPreference implements View.OnClickListener {
protected int mLayout;
protected int[] mImageResources;
public ImageListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ImageListPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs, defStyle);
}
private void init(AttributeSet attrs, int defStyle) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ImageListPreference, defStyle, 0);
try {
Resources res = getContext().getResources();
int images = a.getResourceId(R.styleable.ImageListPreference_pics, 0);
if (images <= 0) throw new IllegalArgumentException(getClass().getSimpleName() + " must set `pics` attribute.");
TypedArray imageRes = res.obtainTypedArray(images);
int[] imageResIds = new int[imageRes.length()];
for (int i = 0; i < imageResIds.length; ++i)
imageResIds[i] = imageRes.getResourceId(i, 0);
imageRes.recycle();
mImageResources = imageResIds;
int layout = a.getResourceId(R.styleable.ImageListPreference_listItemLayout, 0);
if (layout <= 0) throw new IllegalArgumentException(getClass().getSimpleName() + " must set `layout` attribute.");
mLayout = layout;
} finally {
a.recycle();
}
}
/**
* @return The list of Google Play In-App Billing SKUs.
*/
public CharSequence[] getSkus() {
// TODO: update this method as new themes are added (locked via IN-APP Purchases).
CharSequence[] skus = new CharSequence[mImageResources.length];
return skus;
}
protected List<Pair<CharSequence, Integer>> makePairList() {
List<Pair<CharSequence, Integer>> list = new ArrayList<Pair<CharSequence, Integer>>();
CharSequence[] entries = getEntries();
if (entries.length != mImageResources.length)
throw new IllegalArgumentException(getClass().getSimpleName() +
" must have an equal number of `images` and `entries`.");
for (int i = 0; i < entries.length; ++i) {
list.add(new Pair<CharSequence, Integer>(entries[i], mImageResources[i]));
}
return list;
}
ImageListPreferenceScreenAdapter adapter;
@Override
protected void onBindDialogView(View view) {
ListView list = (ListView) view.findViewById(android.R.id.list);
int selection = getSelection();
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
list.setItemChecked(selection, true);
}
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
LogUtils.LOGI(getClass().getSimpleName(), "onPrepareDialogBuilder()");
// Accountant.getInstance(getContext()).connect();
adapter = new ImageListPreferenceScreenAdapter(
getContext(), mLayout, makePairList());
adapter.setOnClickListener(this);
adapter.setSkus(getSkus());
int selectedEntry = getSelection();
adapter.setSelected(selectedEntry);
builder.setAdapter(adapter, null);
}
protected int getSelection() {
int selectedEntry = 0;
String selectedValue = getValue();
if (TextUtils.isEmpty(selectedValue)) return 0;
CharSequence[] entries = getEntryValues();
for (int i = 0; i < entries.length; ++i) {
if (selectedValue.compareTo((String) entries[i]) == 0) {
selectedEntry = i;
break;
}
}
return selectedEntry;
}
@Override
public void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
LogUtils.LOGI(getClass().getSimpleName(), "onDialogClosed(" + positiveResult + ')');
if (null != adapter) adapter.destroy();
}
@Override
public void onClick(View v) {
Dialog mDialog = getDialog();
mDialog.dismiss();
ViewHolder holder = (ViewHolder) v.getTag();
// CharSequence[] skus = getSkus();
// CharSequence sku = skus[holder.position];
CharSequence value = getEntryValues()[holder.position];
//if (TextUtils.isEmpty(sku)) {
// LogUtils.LOGI(getClass().getSimpleName(), "setValue(" + value + ')');
setValue(value.toString());
/*} else {
LogUtils.LOGI(getClass().getSimpleName(), "Item " +
holder.position + " has sku: " + sku);
Accountant mAccountant = Accountant.getInstance(getContext());
if (!mAccountant.inAppPurchasesSupported()) {
LogUtils.LOGI(getClass().getSimpleName(), "In-app purchases not supported.");
Crouton.showText((Activity) getContext(), R.string.inapp_error, Style.ALERT);
} else {
if (mAccountant.has(sku.toString())) {
LogUtils.LOGI(getClass().getSimpleName(), "Already owns: " + sku);
setValue(value.toString());
} else {
LogUtils.LOGI(getClass().getSimpleName(), "Buy in-app: " + sku);
mAccountant.buy((Activity) getContext(), sku.toString());
}
}
}*/
}
static class ViewHolder {
TextView title;
ImageView icon, banner;
int position;
ViewHolder(View row, int position) {
title = (TextView) row.findViewById(android.R.id.title);
icon = (ImageView) row.findViewById(android.R.id.icon);
banner = (ImageView) row.findViewById(R.id.pro_ribbon);
this.position = position;
}
}
protected static class ImageListPreferenceScreenAdapter
extends ArrayAdapter<Pair<CharSequence, Integer>> {
private final int layout;
private final LruCache<Integer, Drawable> cache;
private final CharSequence[] skus;
private View.OnClickListener listener;
private int selected;
public ImageListPreferenceScreenAdapter(Context context,
int layout, List<Pair<CharSequence, Integer>> items) {
super(context, layout, items);
skus = new CharSequence[items.size()];
cache = new LruCache<Integer, Drawable>(items.size());
this.layout = layout;
preload();
}
protected void preload() {
Resources res = getContext().getResources();
for (int i = 0, e = getCount(); i < e; ++i) {
Pair<CharSequence, Integer> item = getItem(i);
cache.put(item.second, res.getDrawable(item.second));
}
}
public void setOnClickListener(View.OnClickListener listener) {
this.listener = listener;
}
protected boolean[] ownedSkus;
public void setSkus(CharSequence[] newSkus) {
if (null == newSkus || newSkus.length != skus.length) return;
ownedSkus = new boolean[newSkus.length];
for (int i = 0; i < newSkus.length; ++i)
skus[i] = newSkus[i];
}
public void setSelected(int selected) {
this.selected = selected;
}
public void destroy() {
cache.evictAll();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
ViewHolder holder;
if (null == convertView) {
row = View.inflate(getContext(), layout, null);
holder = new ViewHolder(row, position);
row.setTag(holder);
} else {
row = convertView;
holder = (ViewHolder) row.getTag();
}
row.setOnClickListener(listener);
Resources res = getContext().getResources();
Pair<CharSequence, Integer> item = getItem(position);
holder.position = position;
holder.title.setText(item.first);
Drawable pic = cache.get(item.second);
if (null == pic) {
pic = res.getDrawable(item.second);
cache.put(item.second, pic);
}
holder.icon.setImageDrawable(pic);
synchronized (skus) {
CharSequence sku = skus[position];
boolean hasSku = (null != sku && !TextUtils.isEmpty(sku));
holder.banner.setVisibility((hasSku) ? View.VISIBLE : View.GONE);
if (hasSku && ownedSkus[position]) {
holder.banner.setVisibility(View.GONE);
}
}
if (position == selected) {
row.setClickable(false);
row.setFocusable(false);
}
return row;
}
}
}