package interdroid.swan.sensors;
import interdroid.swan.swansong.ExpressionFactory;
import interdroid.swan.swansong.ExpressionParseException;
import interdroid.swan.swansong.HistoryReductionMode;
import interdroid.swan.swansong.SensorValueExpression;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceManager;
import android.util.Log;
/**
* Base for ConfigurationActivities for configuring sensors.
*
* @author nick <palmer@cs.vu.nl>
*
*/
public abstract class AbstractConfigurationActivity extends PreferenceActivity
implements OnPreferenceChangeListener {
private static final String TAG = AbstractConfigurationActivity.class
.getSimpleName();
private static final long SECOND = 1000;
private static final long MINUTE = 60 * SECOND;
private static final long HOUR = 60 * MINUTE;
/**
* Returns the id for the sensors preferences XML setup.
*
* @return the id for the preferences XML
*/
public abstract int getPreferencesXML();
private List<String> keys = new ArrayList<String>();
private BroadcastReceiver mNameReceiver = new BroadcastReceiver() {
@SuppressWarnings("deprecation")
@Override
public void onReceive(Context context, Intent intent) {
List<String> names = intent.getStringArrayListExtra("names");
names.add(0, "self");
((ListPreference) findPreference("swan_location")).setEntries(names
.toArray(new String[names.size()]));
((ListPreference) findPreference("swan_location"))
.setEntryValues(names.toArray(new String[names.size()]));
intentToPrefs();
}
};
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
private void intentToPrefs() {
if (getIntent().hasExtra("expression")) {
try {
SensorValueExpression sensor = (SensorValueExpression) ExpressionFactory
.parse(getIntent().getStringExtra("expression"));
updatePref("swan_location", sensor.getLocation());
updatePref("history_window", "" + sensor.getHistoryLength());
updatePref("history_reduction_mode", sensor
.getHistoryReductionMode().toParseString());
updatePref("valuepath", sensor.getValuePath());
for (String key : sensor.getConfiguration().keySet()) {
updatePref(key, sensor.getConfiguration().getString(key));
}
} catch (ExpressionParseException e) {
Log.d(TAG, "supplied expression cannot be parsed.", e);
} catch (ClassCastException e) {
Log.d(TAG, "supplied expression wrong type.", e);
}
} else {
Log.d(TAG, "no edit");
}
}
@SuppressWarnings("deprecation")
private void updatePref(String key, String value) {
findPreference(key).getEditor().putString(key, value).apply();
findPreference(key).getOnPreferenceChangeListener().onPreferenceChange(
findPreference(key), value);
}
@SuppressWarnings("deprecation")
@Override
protected void onResume() {
addPreferencesFromIntent(new Intent(
"interdroid.swan.DEFAULT_PREFERENCES"));
reAddPrefs(getPreferenceScreen());
addPreferencesFromResource(getPreferencesXML());
setupPrefs();
setResult(RESULT_CANCELED);
registerReceiver(mNameReceiver, new IntentFilter(
"interdroid.swan.NAMES"));
sendBroadcast(new Intent("interdroid.swan.GET_NAMES"));
super.onResume();
}
@Override
protected void onPause() {
unregisterReceiver(mNameReceiver);
super.onPause();
}
private void reAddPrefs(PreferenceGroup group) {
// re add the preferences from the intent so that they will be bound
// with the current context, rather than the context from the intent,
// which leads to:
// android.view.WindowManager$BadTokenException: Unable to add window --
// token null is not for an application
List<Preference> oldPrefs = new ArrayList<Preference>();
List<Preference> newPrefs = new ArrayList<Preference>();
for (int i = 0; i < group.getPreferenceCount(); i++) {
Preference preference = group.getPreference(i);
if (preference instanceof EditTextPreference) {
oldPrefs.add(preference);
EditTextPreference oldPref = (EditTextPreference) preference;
EditTextPreference newPref = new EditTextPreference(this);
newPref.getEditText().setInputType(
oldPref.getEditText().getInputType());
newPref.setDialogMessage(oldPref.getDialogMessage());
newPref.setDialogIcon(oldPref.getDialogIcon());
newPref.setDependency(oldPref.getDependency());
newPref.setDialogTitle(oldPref.getDialogTitle());
newPref.setEnabled(oldPref.isEnabled());
newPref.setIntent(oldPref.getIntent());
newPref.setKey(oldPref.getKey());
newPref.setOrder(oldPref.getOrder());
newPref.setSummary(oldPref.getSummary());
newPref.setText(oldPref.getText());
newPref.setTitle(oldPref.getTitle());
newPrefs.add(newPref);
} else if (preference instanceof ListPreference) {
oldPrefs.add(preference);
ListPreference oldPref = (ListPreference) preference;
ListPreference newPref = new ListPreference(this);
newPref.setDialogMessage(oldPref.getDialogMessage());
newPref.setDialogIcon(oldPref.getDialogIcon());
newPref.setDependency(oldPref.getDependency());
newPref.setDialogTitle(oldPref.getDialogTitle());
newPref.setEnabled(oldPref.isEnabled());
newPref.setIntent(oldPref.getIntent());
newPref.setKey(oldPref.getKey());
newPref.setOrder(oldPref.getOrder());
newPref.setSummary(oldPref.getSummary());
newPref.setTitle(oldPref.getTitle());
newPref.setEntries(oldPref.getEntries());
newPref.setEntryValues(oldPref.getEntryValues());
newPrefs.add(newPref);
} else if (preference instanceof PreferenceGroup) {
reAddPrefs((PreferenceGroup) preference);
} else {
group.removePreference(preference);
Log.d(TAG, "not re adding preference: '" + preference.getKey()
+ "' not supported");
}
}
for (Preference oldPref : oldPrefs) {
group.removePreference(oldPref);
}
for (Preference newPref : newPrefs) {
group.addPreference(newPref);
}
}
/**
* Sets up this activity.
*/
@SuppressWarnings("deprecation")
private void setupPrefs() {
setupPref(null, getPreferenceScreen());
}
/**
* Sets up using the given preferences.
*
* @param preference
* the preferences for the sensor.
*/
private void setupPref(final PreferenceGroup parent,
final Preference preference) {
if (preference instanceof PreferenceGroup) {
int nrPrefs = ((PreferenceGroup) preference).getPreferenceCount();
for (int i = nrPrefs - 1; i >= 0; i--) {
// setup all sub prefs
setupPref(((PreferenceGroup) preference),
((PreferenceGroup) preference).getPreference(i));
}
// update nr prefs
nrPrefs = ((PreferenceGroup) preference).getPreferenceCount();
if (nrPrefs == 0) {
parent.removePreference(preference);
}
} else {
keys.add(preference.getKey());
// setup the listener
preference.setOnPreferenceChangeListener(this);
// set the summary
String summary = null;
// setup location pref
if (preference instanceof ListPreference) {
try {
summary = ((ListPreference) preference).getValue()
.toString();
} catch (NullPointerException e) {
Log.d(TAG, "Got null pointer while getting summary.", e);
}
} else if (preference instanceof EditTextPreference) {
summary = ((EditTextPreference) preference).getText();
}
if (summary != null) {
preference.setSummary(summary);
}
if (preference instanceof ListPreference) {
if (((ListPreference) preference).getEntries() == null) {
return;
}
if (((ListPreference) preference).getEntries().length == 1) {
preference.setEnabled(false);
}
((ListPreference) preference)
.setValue(((ListPreference) preference)
.getEntryValues()[0].toString());
preference.setSummary(((ListPreference) preference)
.getEntries()[0]);
}
if (getIntent().hasExtra(preference.getKey())) {
PreferenceManager
.getDefaultSharedPreferences(getBaseContext())
.edit()
.putString(
preference.getKey(),
""
+ getIntent().getExtras().get(
preference.getKey())).commit();
// hide the pref.
// parent.removePreference(preference);
preference.setEnabled(false);
}
}
}
@Override
public final void onBackPressed() {
setResult(RESULT_OK,
getIntent()
.putExtra("Expression", prefsToConfigurationString()));
finish();
}
/**
* Converts the prefs to a parseable configuration string.
*
* @return the prefs as a string.
*/
private String prefsToConfigurationString() {
Map<String, ?> map = PreferenceManager.getDefaultSharedPreferences(
getBaseContext()).getAll();
String location = map.remove("swan_location").toString();
String path = map.remove("valuepath").toString();
HistoryReductionMode mode = HistoryReductionMode.parse(map.remove(
"history_reduction_mode").toString());
long timespan = Long.parseLong(map.remove("history_window").toString());
String timeUnits = (String) map.remove("time_units");
if (timeUnits.equals("h")) {
timespan = timespan * HOUR;
} else if (timeUnits.equals("m")) {
timespan = timespan * MINUTE;
} else if (timeUnits.equals("s")) {
timespan = timespan * SECOND;
}
// String storage = map.remove("storage").toString();
// Log.d(TAG, "Selected storage: " + storage);
// Log.d(TAG, storage);
// setSelectedStorage(storage);
String entityId = getIntent().getStringExtra("entityId");
Bundle configuration = new Bundle();
for (String key : keys) {
if (map.containsKey(key)) {
configuration.putString(key, map.get(key).toString());
}
}
SensorValueExpression sensor = new SensorValueExpression(location,
entityId, path, configuration, mode, timespan);
return sensor.toParseString();
}
@Override
public final boolean onPreferenceChange(final Preference preference,
final Object newValue) {
if (preference instanceof ListPreference) {
for (int i = 0; i < ((ListPreference) preference).getEntryValues().length; i++) {
if (((ListPreference) preference).getEntryValues()[i]
.toString().equals(newValue.toString())) {
preference.setSummary(((ListPreference) preference)
.getEntries()[i]);
return true;
}
}
} else {
preference.setSummary(newValue.toString());
}
return true;
}
}