/* * Copyright (C) 2013 University of South Florida (sjbarbeau@gmail.com). * * 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 org.onebusaway.android.region; import org.onebusaway.android.R; import org.onebusaway.android.app.Application; import org.onebusaway.android.util.PreferenceUtils; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.res.TypedArray; import android.os.Parcel; import android.os.Parcelable; import android.preference.CheckBoxPreference; import android.preference.Preference; import android.util.AttributeSet; /** * Custom preference to handle enabling and disabling experimental * (i.e., non-production) OBA regions * <p/> * Code for saving/restoring state based on example at: * http://developer.android.com/guide/topics/ui/settings.html * <p/> * and Android internal YesNoPreference: * https://github.com/android/platform_frameworks_base/blob/master/core/java/com/android/internal/preference/YesNoPreference.java * * @author Sean Barbeau */ public class ExperimentalRegionsPreference extends CheckBoxPreference { private boolean mCurrentValue; private final boolean DEFAULT_VALUE = false; // // Needed constructors. // public ExperimentalRegionsPreference(Context context) { super(context); initCheckedState(); } public ExperimentalRegionsPreference(Context context, AttributeSet attrs) { super(context, attrs); initCheckedState(); } public ExperimentalRegionsPreference(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initCheckedState(); } protected void initCheckedState() { setChecked(Application.getPrefs() .getBoolean(getContext().getString(R.string.preference_key_experimental_regions), DEFAULT_VALUE)); } @Override public boolean isPersistent() { return true; } @Override protected void onClick() { if (!isChecked()) { /* Warn the user before enabling, since experimental regions may not have real-time info or may be unavailable. */ AlertDialog dialog = new AlertDialog.Builder(getContext()) .setMessage(R.string.preferences_experimental_regions_enable_warning) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); setValue(true); } }) .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } } ) .create(); dialog.show(); } else { if (Application.get().getCurrentRegion() != null && Application.get().getCurrentRegion().getExperimental()) { // If the user is currently using an experimental region, warn that it won't be available AlertDialog dialog = new AlertDialog.Builder(getContext()) .setMessage(R.string.preferences_experimental_regions_disable_warning) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); // Set the region info to null, so we no longer use the current experimental region Application.get().setCurrentRegion(null); setValue(false); } } ) .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } } ) .create(); dialog.show(); } else { setValue(false); } } } /** * Sets the experimental regions preference (both user interface and shared preference value) * to * the input value * * @param newValue true if the preference should be set to true, false if it should be set to * false */ public void setValue(boolean newValue) { mCurrentValue = newValue; setChecked(newValue); PreferenceUtils .saveBoolean(getContext().getString(R.string.preference_key_experimental_regions), newValue); } @Override protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { if (restorePersistedValue) { // Restore existing state mCurrentValue = this.getPersistedBoolean(mCurrentValue); } else { // Set default state from the XML attribute mCurrentValue = (Boolean) defaultValue; persistBoolean(mCurrentValue); } } @Override protected Object onGetDefaultValue(TypedArray a, int index) { return a.getBoolean(index, DEFAULT_VALUE); } @Override protected Parcelable onSaveInstanceState() { final Parcelable superState = super.onSaveInstanceState(); // Create instance of custom BaseSavedState final SavedState myState = new SavedState(superState); // Set the state's value with the class member that holds current setting value myState.value = mCurrentValue; return myState; } @Override protected void onRestoreInstanceState(Parcelable state) { // Check whether we saved the state in onSaveInstanceState if (state == null || !state.getClass().equals(SavedState.class)) { // Didn't save the state, so call superclass super.onRestoreInstanceState(state); return; } // Cast state to custom BaseSavedState and pass to superclass SavedState myState = (SavedState) state; super.onRestoreInstanceState(myState.getSuperState()); // Set this Preference to reflect the restored state setValue(myState.value); } /** * Used to handle onSaveInstanceState()/onRestoreInstanceState properly, based on example * at http://developer.android.com/guide/topics/ui/settings.html */ private static class SavedState extends Preference.BaseSavedState { // Member that holds the setting's value boolean value; public SavedState(Parcelable superState) { super(superState); } public SavedState(Parcel source) { super(source); // Get the current preference's value value = source.readByte() != 0; } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); // Write the preference's value dest.writeByte((byte) (value ? 1 : 0)); } // Standard creator object using an instance of this class public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } }