package com.transitwidget;
import java.util.ArrayList;
import java.util.List;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import com.transitwidget.prefs.NextBusAgency;
import com.transitwidget.prefs.NextBusDirection;
import com.transitwidget.prefs.NextBusField;
import com.transitwidget.prefs.NextBusObserverConfig;
import com.transitwidget.prefs.NextBusRoute;
import com.transitwidget.prefs.NextBusStop;
import com.transitwidget.prefs.NextBusValue;
public class TransitWidgetConfiguration extends PreferenceActivity {
protected NextBusObserverConfig config;
private int mAppWidgetId;
private AgencyConfigurationField agencyField;
private RouteConfigurationField routeField;
private DirectionConfigurationField directionField;
private StopConfigurationField stopField;
protected TransitConfigurationField<?> lastChangedField = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Find the widget id from the intent.
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
// If they gave us an intent without the widget id, just bail.
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
return;
}
config = new NextBusObserverConfig(getApplicationContext(), mAppWidgetId);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.widget_preferences);
agencyField = new AgencyConfigurationField("which_agency_preference");
routeField = new RouteConfigurationField("which_route_preference");
directionField = new DirectionConfigurationField("which_direction_preference");
stopField = new StopConfigurationField("which_stop_preference");
agencyField.loadChoices();
}
@Override
public void onContentChanged () {
super.onContentChanged(); // Called from super.onCreate().
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
}
/**
* Called when the screen is rotated, or when this Activity *might* need
* to be ejected from memory (e.g. when screen locked). The instance may
* not be deleted after this.
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
/**
* Called if restoring the UI, such as when the phone is rotated.
* Called after onCreate and after onPostCreate are called.
*/
@Override
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
@Override
protected void onPostResume() {
// TODO Auto-generated method stub
super.onPostResume();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
@Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
super.onWindowFocusChanged(hasFocus);
if (lastChangedField != null) {
lastChangedField.updateConfigFromValue();
lastChangedField = null;
}
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
}
private abstract class TransitConfigurationField<T extends NextBusValue> {
private final TransitConfigurationField<?> previous;
private TransitConfigurationField<?> next;
private final ListPreference preference;
private final NextBusField<T> configField;
private final CharSequence summary;
public TransitConfigurationField(
String preferenceName,
TransitConfigurationField<?> previous,
NextBusField<T> configField) {
if (configField == null)
throw new IllegalStateException();
this.configField = configField;
PreferenceManager preferenceManager = getPreferenceManager();
Preference p = preferenceManager.findPreference(preferenceName);
if (p == null || !(p instanceof ListPreference)) {
throw new IllegalStateException();
}
this.preference = (ListPreference)p;
this.summary = p.getSummary();
this.previous = previous;
if (previous != null) {
previous.setNext(this);
}
updateListFromConfig();
updateValueFromConfig();
this.preference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference p, Object newValue) {
lastChangedField = TransitConfigurationField.this;
String v = preference.getValue();
int i = preference.findIndexOfValue(v);
return true;
}
});
}
private void updateValueFromConfig() {
// Set the preference to a default value, unless the config is set.
preference.setValue("");
preference.setSummary(summary);
if (configField.isSet()) {
T v = configField.get();
if (configField.hasValidValuesLoaded()) {
int ndx = configField.indexOf(v);
if (ndx >= 0) {
preference.setValueIndex(ndx);
List<T> vv = configField.getValidValues();
preference.setSummary(vv.get(ndx).getItemLabel());
}
}
}
if (next != null) {
next.loadChoices();
}
}
private void updateConfigFromValue() {
String v = preference.getValue();
preference.setSummary(summary);
T newT = null;
if (v != null && v.length() > 0) {
if (configField.hasValidValuesLoaded()) {
List<T> vv = configField.getValidValues();
for (T t : vv) {
if (v.equals(t.getTag())) {
newT = t;
preference.setSummary(newT.getItemLabel());
break;
}
}
} else {
newT = createNextBusField();
newT.setTag(v);
}
}
if (newT == null) {
configField.clear();
} else {
configField.set(newT);
}
if (next != null) {
next.loadChoices();
}
}
private void updateListFromConfig() {
if (configField.hasValidValuesLoaded()) {
List<T> vv = configField.getValidValues();
List<String> names = new ArrayList<String>();
List<String> tags = new ArrayList<String>();
for (T t : vv) {
names.add(t.getItemLabel());
tags.add(t.getTag());
}
preference.setEntries(names.toArray(new String[0]));
preference.setEntryValues(tags.toArray(new String[0]));
preference.setEnabled(true);
} else {
preference.setEnabled(false);
}
if (next != null) {
next.loadChoices();
}
}
public void setNext(TransitConfigurationField<?> next) {
this.next = next;
}
/**
* Must only be called from an {@link AsyncTask}.
* @param config
* @return
*/
List<T> getChoices() {
return configField.loadValidValues();
}
public ListPreference getPreference() {
return preference;
}
public void loadChoices() {
new LoadChoices().execute();
}
private class LoadChoices extends AsyncTask<Object, Object, Object> {
@Override
protected Object doInBackground(Object... params) {
getChoices();
return null;
}
@Override
protected void onPostExecute(Object result) {
updateListFromConfig();
}
}
public abstract T createNextBusField();
}
private class AgencyConfigurationField extends TransitConfigurationField<NextBusAgency> {
public AgencyConfigurationField(String preferenceName) {
super(preferenceName, null, config.getAgencyField());
// TODO: want to be able to use preference store to initialize a new
// widget based on the selections for the last widget configured.
getPreference().setDefaultValue("mbta");
}
@Override
public NextBusAgency createNextBusField() {
return new NextBusAgency();
}
}
private class RouteConfigurationField extends TransitConfigurationField<NextBusRoute> {
public RouteConfigurationField(String preferenceName) {
super(preferenceName, agencyField, config.getRouteField());
}
@Override
public NextBusRoute createNextBusField() {
return new NextBusRoute();
}
}
private class DirectionConfigurationField extends TransitConfigurationField<NextBusDirection> {
public DirectionConfigurationField(String preferenceName) {
super(preferenceName, routeField, config.getDirectionField());
}
@Override
public NextBusDirection createNextBusField() {
return new NextBusDirection();
}
}
private class StopConfigurationField extends TransitConfigurationField<NextBusStop> {
public StopConfigurationField(String preferenceName) {
super(preferenceName, directionField, config.getStopField());
}
@Override
public NextBusStop createNextBusField() {
return new NextBusStop();
}
}
}