/*
* Copyright (C) 2014-2017 VersoBit
*
* This file is part of Weather Doge.
*
* Weather Doge is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Weather Doge is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Weather Doge. If not, see <http://www.gnu.org/licenses/>.
*/
package com.versobit.weatherdoge;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.v7.widget.AppCompatCheckBox;
import android.support.v7.widget.AppCompatCheckedTextView;
import android.support.v7.widget.AppCompatEditText;
import android.support.v7.widget.AppCompatRadioButton;
import android.support.v7.widget.AppCompatSpinner;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import com.versobit.weatherdoge.dialogs.AboutDialog;
import com.versobit.weatherdoge.dialogs.ContributeDialog;
import com.versobit.weatherdoge.dialogs.DropShadowDialog;
import com.versobit.weatherdoge.dialogs.OtherShibesDialog;
import com.versobit.weatherdoge.ui.DogeEditTextPreference;
import java.util.ArrayList;
import java.util.List;
/**
* A {@link PreferenceActivity} that presents a set of application settings. On
* handset devices, settings are presented as a single list. On tablets,
* settings are split by category, with category headers shown to the left of
* the list of settings.
* <p>
* See <a href="http://developer.android.com/design/patterns/settings.html">
* Android Design: Settings</a> for design guidelines and the <a
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
* API Guide</a> for more information on developing a Settings UI.
*/
final public class OptionsActivity extends PreferenceActivity {
static final String EXTRA_SHORTCUT = "shortcut";
static final int EXTRA_SHORTCUT_NONE = -1;
static final int EXTRA_SHORTCUT_FORCE_LOCATION = 0;
static final String PREF_FORCE_METRIC = "pref_force_metric";
static final String PREF_FORCE_LOCATION = "pref_force_location";
static final String PREF_WEATHER_SOURCE = "pref_weather_source";
public static final String PREF_APP_USE_COMIC_NEUE = "pref_use_comic_neue";
public static final String PREF_APP_DROP_SHADOW = "pref_drop_shadow";
static final String PREF_APP_TEXT_ON_TOP = "pref_text_on_top";
static final String PREF_APP_ENABLE_PARTICLES = "pref_enable_particles";
static final String PREF_WIDGET_REFRESH = "pref_widget_refresh";
static final String PREF_WIDGET_TAP_TO_REFRESH = "pref_widget_tap_refresh";
static final String PREF_WIDGET_USE_COMIC_NEUE = "pref_widget_use_comic_neue";
static final String PREF_WIDGET_SHOW_WOWTEXT = "pref_widget_show_wowtext";
static final String PREF_WIDGET_SHOW_DATE = "pref_widget_show_date";
static final String PREF_WIDGET_BACKGROUND_FIX = "pref_widget_background_fix";
static final String PREF_ABOUT_VERSION = "pref_about_version";
static final String PREF_ABOUT_CONTRIBUTE = "pref_about_contribute";
static final String PREF_ABOUT_ADD_CREDITS = "pref_about_additional_credits";
static final String PREF_INTERNAL_LAST_VERSION = "pref_internal_last_version";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Thanks to David Passmore http://stackoverflow.com/a/27455330/238374
LinearLayout root = (LinearLayout)findViewById(android.R.id.content).getParent();
AppBarLayout bar = (AppBarLayout) LayoutInflater.from(this).inflate(R.layout.toolbar_options, root, false);
root.addView(bar, 0);
Toolbar toolbar = (Toolbar)bar.getChildAt(0);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
getFragmentManager().beginTransaction().replace(android.R.id.content, new OptionsFragment()).commit();
}
@Nullable
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
final View result = super.onCreateView(name, context, attrs);
if (result != null) {
return result;
}
// Provide colorized/tinted widgets on non-Material devices
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
switch (name) {
case "EditText":
return new AppCompatEditText(this, attrs);
case "Spinner":
return new AppCompatSpinner(this, attrs);
case "CheckBox":
return new AppCompatCheckBox(this, attrs);
case "RadioButton":
return new AppCompatRadioButton(this, attrs);
case "CheckedTextView":
return new AppCompatCheckedTextView(this, attrs);
}
}
return null;
}
public static final class OptionsFragment extends PreferenceFragment {
boolean genForceMetric = false;
String genForceLocation = "";
WeatherUtil.Source genWeatherSource = WeatherUtil.Source.OPEN_WEATHER_MAP;
String widgetRefreshInterval = "1800";
boolean widgetTapToRefresh = false;
boolean widgetComicNeue = false;
boolean widgetShowWowText = true;
boolean widgetShowDate = false;
boolean widgetBackgroundFix = false;
@Override
public void onResume() {
super.onResume();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
genForceMetric = prefs.getBoolean(PREF_FORCE_METRIC, genForceMetric);
genForceLocation = prefs.getString(PREF_FORCE_LOCATION, genForceLocation);
String strSource = prefs.getString(PREF_WEATHER_SOURCE, "0");
genWeatherSource = WeatherUtil.Source.OPEN_WEATHER_MAP;
if ("1".equals(strSource)) {
genWeatherSource = WeatherUtil.Source.YAHOO;
}
widgetRefreshInterval = prefs.getString(PREF_WIDGET_REFRESH, widgetRefreshInterval);
widgetTapToRefresh = prefs.getBoolean(PREF_WIDGET_TAP_TO_REFRESH, widgetTapToRefresh);
widgetComicNeue = prefs.getBoolean(PREF_WIDGET_USE_COMIC_NEUE, widgetComicNeue);
widgetShowWowText = prefs.getBoolean(PREF_WIDGET_SHOW_WOWTEXT, widgetShowWowText);
widgetShowDate = prefs.getBoolean(PREF_WIDGET_SHOW_DATE, widgetShowDate);
widgetBackgroundFix = prefs.getBoolean(PREF_WIDGET_BACKGROUND_FIX, widgetBackgroundFix);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add 'general' preferences.
addPreferencesFromResource(R.xml.pref_general);
// Add 'app' preferences, and a corresponding header.
PreferenceCategory fakeHeader = new PreferenceCategory(getActivity());
fakeHeader.setTitle(R.string.pref_app_header);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_app);
findPreference(PREF_APP_DROP_SHADOW).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
new DropShadowDialog().show(getFragmentManager(), DropShadowDialog.FRAGMENT_TAG);
return true;
}
});
// Make certain we do not show weather sources that are not configured
ListPreference srcPref = (ListPreference) findPreference(PREF_WEATHER_SOURCE);
CharSequence[] oldSrcEntries = srcPref.getEntries();
CharSequence[] oldSrcValues = srcPref.getEntryValues();
List<CharSequence> newSrcEntries = new ArrayList<>(oldSrcEntries.length);
List<CharSequence> newSrcValues = new ArrayList<>(oldSrcValues.length);
for (int i = 0; i < oldSrcValues.length; i++) {
//noinspection ConstantConditions
if (WeatherUtil.Source.OPEN_WEATHER_MAP.getKey().equals(oldSrcValues[i]) && TextUtils.isEmpty(BuildConfig.OWM_APPID)) {
continue;
}
//noinspection ConstantConditions
if (WeatherUtil.Source.ACCUWEATHER.getKey().equals(oldSrcValues[i]) && TextUtils.isEmpty(BuildConfig.ACCUWEATHER_KEY)) {
continue;
}
newSrcEntries.add(oldSrcEntries[i]);
newSrcValues.add(oldSrcValues[i]);
}
if (newSrcEntries.size() != oldSrcEntries.length) {
String oldValue = srcPref.getValue();
srcPref.setValueIndex(0);
srcPref.setEntries(newSrcEntries.toArray(new CharSequence[newSrcEntries.size()]));
srcPref.setEntryValues(newSrcValues.toArray(new CharSequence[newSrcValues.size()]));
if (newSrcValues.contains(oldValue)) {
// Restore the preference since it's still available
srcPref.setValue(oldValue);
} else {
// Default to the first entry whatever that may be
srcPref.setValueIndex(0);
}
}
// Add 'widget' preferences, and a corresponding header.
fakeHeader = new PreferenceCategory(getActivity());
fakeHeader.setTitle(R.string.pref_widget_header);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_widget);
// Add 'about' preferences, and a corresponding header.
fakeHeader = new PreferenceCategory(getActivity());
fakeHeader.setTitle(R.string.about);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_about);
Preference aboutVersion = findPreference(PREF_ABOUT_VERSION);
aboutVersion.setTitle(getString(R.string.app_name) + " v" + BuildConfig.VERSION_NAME.split("-")[0]);
aboutVersion.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
new AboutDialog().show(getFragmentManager(), AboutDialog.FRAGMENT_TAG);
return true;
}
});
findPreference(PREF_ABOUT_CONTRIBUTE).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
new ContributeDialog().show(getFragmentManager(), ContributeDialog.FRAGMENT_TAG);
return true;
}
});
findPreference(PREF_ABOUT_ADD_CREDITS).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
new OtherShibesDialog().show(getFragmentManager(), OtherShibesDialog.FRAGMENT_TAG);
return true;
}
});
// Bind the summaries of EditText/List/Dialog/Ringtone preferences to
// their values. When their values change, their summaries are updated
// to reflect the new value, per the Android Design guidelines.
bindPreferenceSummaryToValue(findPreference(PREF_FORCE_LOCATION));
bindPreferenceSummaryToValue(findPreference(PREF_WEATHER_SOURCE));
bindPreferenceSummaryToValue(findPreference(PREF_WIDGET_REFRESH));
// Disable the ability to switch fonts for FOSS flavor
if(BuildConfig.FLAVOR.equals(BuildConfig.FLAVOR_FOSS)) {
CheckBoxPreference appNeue = (CheckBoxPreference)findPreference(PREF_APP_USE_COMIC_NEUE);
CheckBoxPreference widgetNeue = (CheckBoxPreference)findPreference(PREF_WIDGET_USE_COMIC_NEUE);
appNeue.setChecked(true);
appNeue.setEnabled(false);
widgetNeue.setChecked(true);
widgetNeue.setEnabled(false);
}
// Apply a shortcut
if (getActivity() != null) {
Intent i = getActivity().getIntent();
switch (i.getIntExtra(EXTRA_SHORTCUT, EXTRA_SHORTCUT_NONE)) {
case EXTRA_SHORTCUT_FORCE_LOCATION:
((DogeEditTextPreference)findPreference(PREF_FORCE_LOCATION)).showDialog();
default:
// Prevent it from displaying again
i.removeExtra(EXTRA_SHORTCUT);
}
}
}
@Override
public void onStop() {
// Refresh widget options if they've changed
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
boolean newGenForceMetric = prefs.getBoolean(PREF_FORCE_METRIC, genForceMetric);
String newGenForceLocation = prefs.getString(PREF_FORCE_LOCATION, genForceLocation);
String strSource = prefs.getString(PREF_WEATHER_SOURCE, "0");
WeatherUtil.Source newGenWeatherSource = WeatherUtil.Source.OPEN_WEATHER_MAP;
if ("1".equals(strSource)) {
newGenWeatherSource = WeatherUtil.Source.YAHOO;
}
String newWidgetRefreshInterval = prefs.getString(PREF_WIDGET_REFRESH, widgetRefreshInterval);
boolean newWidgetTapToRefresh = prefs.getBoolean(PREF_WIDGET_TAP_TO_REFRESH, widgetTapToRefresh);
boolean newWidgetComicNeue = prefs.getBoolean(PREF_WIDGET_USE_COMIC_NEUE, widgetComicNeue);
boolean newWidgetShowWowText = prefs.getBoolean(PREF_WIDGET_SHOW_WOWTEXT, widgetShowWowText);
boolean newWidgetShowDate = prefs.getBoolean(PREF_WIDGET_SHOW_DATE, widgetShowDate);
boolean newWidgetBackgroundFix = prefs.getBoolean(PREF_WIDGET_BACKGROUND_FIX, widgetBackgroundFix);
if (newGenForceMetric != genForceMetric ||
!genForceLocation.equals(newGenForceLocation) ||
newGenWeatherSource != genWeatherSource ||
newWidgetTapToRefresh != widgetTapToRefresh ||
newWidgetComicNeue != widgetComicNeue ||
newWidgetShowWowText != widgetShowWowText ||
newWidgetShowDate != widgetShowDate ||
newWidgetBackgroundFix != widgetBackgroundFix) {
getActivity().startService(new Intent(getActivity(), WidgetService.class)
.setAction(WidgetService.ACTION_REFRESH_ALL));
}
if (!widgetRefreshInterval.equals(newWidgetRefreshInterval)) {
WidgetProvider.resetAlarm(getActivity());
}
super.onStop();
}
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: null);
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue.isEmpty() ? preference.getContext().getString(R.string.unset) : stringValue);
}
return true;
}
};
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* @see #sBindPreferenceSummaryToValueListener
*/
private static void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), preference.getContext().getString(R.string.unset)));
}
}
}