/*
* Copyright (c) 2013 Menny Even-Danan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.anysoftkeyboard.ui.settings.widget;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.AbsSavedState;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.PopupWindow;
import android.widget.RadioButton;
import android.widget.TextView;
import com.anysoftkeyboard.addons.AddOn;
import com.anysoftkeyboard.addons.AddOnsFactory;
import com.anysoftkeyboard.addons.IconHolder;
import com.anysoftkeyboard.addons.ScreenshotHolder;
import com.menny.android.anysoftkeyboard.R;
import net.evendanan.pushingpixels.Banner;
import net.evendanan.pushingpixels.ListPreference;
import java.util.ArrayList;
import java.util.List;
/*using this import requires using the Android Library from https://github.com/menny/PushingPixels*/
public class AddOnListPreference extends ListPreference {
public static <E extends AddOn> void populateAddOnListPreference(AddOnListPreference preference,
List<E> list, AddOn selectedAddOn) {
AddOn[] addOns = new AddOn[list.size()];
list.toArray(addOns);
preference.setAddOnsList(addOns);
preference.setSelectedAddOn(selectedAddOn);
}
@Nullable
private AddOn[] mAddOns;
@Nullable
private AddOn mSelectedAddOn;
public AddOnListPreference(Context context) {
super(context);
}
public AddOnListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onPrepareDialogBuilder(Builder builder) {
if (mAddOns != null) {
// mAddOns is null happens when activity gets recreated, e.g. on
// rotating the device.
ListAdapter listAdapter = new AddOnArrayAdapter(getContext(),
R.layout.addon_list_item_pref, mAddOns);
builder.setAdapter(listAdapter, this);
}
super.onPrepareDialogBuilder(builder);
}
public void setAddOnsList(@NonNull AddOn[] addOns) {
mAddOns = addOns;
String[] ids = new String[mAddOns.length];
String[] names = new String[mAddOns.length];
int entryPos = 0;
for (AddOn addOn : mAddOns) {
ids[entryPos] = addOn.getId();
names[entryPos] = addOn.getName();
entryPos++;
}
setEntries(names);
setEntryValues(ids);
}
private class AddOnArrayAdapter extends ArrayAdapter<AddOn> implements
OnClickListener {
public AddOnArrayAdapter(Context context, int textViewResourceId,
AddOn[] objects) {
super(context, textViewResourceId, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final AddOn addOn = getItem(position);
final View row;
if (convertView == null) {
// inflate layout
LayoutInflater inflater = LayoutInflater.from(getContext());
row = inflater.inflate(R.layout.addon_list_item_pref, parent, false);
} else {
row = convertView;
}
row.setTag(addOn);
// set on click listener for row
row.setOnClickListener(this);
// set addon details
TextView title = (TextView) row.findViewById(R.id.addon_title);
title.setText(addOn.getName());
TextView description = (TextView) row
.findViewById(R.id.addon_description);
description.setText(addOn.getDescription());
Drawable icon = null;
if (addOn instanceof IconHolder) {
IconHolder iconHolder = (IconHolder) addOn;
icon = iconHolder.getIcon();
}
if (icon == null) {
try {
PackageManager packageManager = getContext().getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(addOn.getPackageName(), 0);
icon = packageInfo.applicationInfo.loadIcon(packageManager);
} catch (PackageManager.NameNotFoundException e) {
icon = null;
}
}
ImageView addOnIcon = (ImageView) row
.findViewById(R.id.addon_image);
addOnIcon.setImageDrawable(icon);
View more = row.findViewById(R.id.addon_image_more_overlay);
if (addOn instanceof ScreenshotHolder) {
if (((ScreenshotHolder) addOn).hasScreenshot()) {
addOnIcon.setOnClickListener(this);
addOnIcon.setTag(addOn);
more.setVisibility(View.VISIBLE);
} else {
more.setVisibility(View.GONE);
}
}
// set checkbox
RadioButton tb = (RadioButton) row
.findViewById(R.id.addon_checkbox);
tb.setClickable(false);
if (mSelectedAddOn != null)
tb.setChecked(addOn.getId().equals(mSelectedAddOn.getId()));
else
tb.setChecked(false);
return row;
}
public void onClick(View v) {
if (v.getId() == R.id.addon_list_item_layout) {
AddOn newSelectedAddOn = (AddOn) v.getTag();
setSelectedAddOn(newSelectedAddOn);
AddOnListPreference.this.setValue(newSelectedAddOn.getId());
Dialog dialog = getDialog();
if (dialog != null)
dialog.dismiss();// it is null if the dialog is not shown.
} else if (v.getId() == R.id.addon_image) {
// showing a screenshot (if available)
AddOn addOn = (AddOn) v.getTag();
Drawable screenshot = null;
if (addOn instanceof ScreenshotHolder) {
ScreenshotHolder holder = (ScreenshotHolder) addOn;
screenshot = holder.getScreenshot();
}
if (screenshot == null) {
screenshot = ((ImageView) v).getDrawable();
}
//
if (screenshot == null)
return;
// inflating the screenshot view
LayoutInflater inflator = LayoutInflater.from(getContext());
ViewGroup layout = (ViewGroup) inflator.inflate(R.layout.addon_screenshot, null);
final PopupWindow popup = new PopupWindow(getContext());
popup.setContentView(layout);
DisplayMetrics dm = getContext().getResources()
.getDisplayMetrics();
popup.setWidth(dm.widthPixels);
popup.setHeight(dm.heightPixels);
popup.setAnimationStyle(R.style.AddonScreenshotPopupAnimation);
layout.findViewById(R.id.addon_screenshot_close)
.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
popup.dismiss();
}
});
((Banner)layout.findViewById(R.id.addon_screenshot)).setImageDrawable(screenshot);
popup.showAtLocation(v, Gravity.CENTER, 0, 0);
}
}
}
public void setSelectedAddOn(AddOn currentSelectedAddOn) {
mSelectedAddOn = currentSelectedAddOn;
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superP = super.onSaveInstanceState();
if (mSelectedAddOn == null || mAddOns == null) {
//no state to save
return superP;
} else {
AddOnsListSavedState myState = new AddOnsListSavedState(superP);
//some add-ons can be none.
myState.selectedAddOnId = mSelectedAddOn.getId();
String[] addOns = new String[mAddOns.length];
for (int i = 0; i < addOns.length; i++)
addOns[i] = mAddOns[i].getId();
myState.addOnIds = addOns;
return myState;
}
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state == null || !(state instanceof AddOnsListSavedState)) {
// although, this should not happen
super.onRestoreInstanceState(state);
} else {
AddOnsListSavedState myState = (AddOnsListSavedState) state;
String selectedAddOnId = myState.selectedAddOnId;
String[] addOnIds = myState.addOnIds;
//now, this is tricky: it is possible that by the time we need to restore the state
//some of the add-ons (and even the default) will no longer exist!
//this can happen when going out of the App to uninstall an add-on, and then returning to the App.
List<AddOn> validAddOns = new ArrayList<>(addOnIds.length);
for (String addOnId : addOnIds) {
AddOn addOn = AddOnsFactory.locateAddOn(addOnId, getContext().getApplicationContext());
if (addOn != null) {
validAddOns.add(addOn);
}
}
AddOn[] addOns = new AddOn[validAddOns.size()];
validAddOns.toArray(addOns);
setAddOnsList(addOns);
AddOn selectedAddOn = AddOnsFactory.locateAddOn(selectedAddOnId, getContext().getApplicationContext());
if (selectedAddOn == null && validAddOns.size() > 0) {
selectedAddOn = validAddOns.get(0);
}
setSelectedAddOn(selectedAddOn);
super.onRestoreInstanceState(myState.getSuperState());
}
}
private static class AddOnsListSavedState extends AbsSavedState {
String selectedAddOnId;
String[] addOnIds;
public AddOnsListSavedState(Parcel source) {
super(source);
selectedAddOnId = source.readString();
int addOnCount = source.readInt();
addOnIds = new String[addOnCount];
source.readStringArray(addOnIds);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(selectedAddOnId);
dest.writeInt(addOnIds.length);
dest.writeStringArray(addOnIds);
}
public AddOnsListSavedState(Parcelable superState) {
super(superState);
}
public static final Parcelable.Creator<AddOnsListSavedState> CREATOR = new Parcelable.Creator<AddOnsListSavedState>() {
public AddOnsListSavedState createFromParcel(Parcel in) {
return new AddOnsListSavedState(in);
}
public AddOnsListSavedState[] newArray(int size) {
return new AddOnsListSavedState[size];
}
};
}
}