/* * Copyright (C) 2016 Tobias Bielefeld * This program 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 * any later version. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. * * If you want to contact me, send me an e-mail at [email protected] */ package de.tobiasbielefeld.solitaire.ui.settings; import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.Preference; import android.preference.PreferenceCategory; import android.preference.PreferenceFragment; import android.support.v7.app.ActionBar; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; import java.util.Locale; import de.tobiasbielefeld.solitaire.LoadGame; import de.tobiasbielefeld.solitaire.R; import de.tobiasbielefeld.solitaire.checkboxpreferences.CheckBoxPreferenceFourColorMode; import de.tobiasbielefeld.solitaire.checkboxpreferences.CheckBoxPreferenceHideAutoCompleteButton; import de.tobiasbielefeld.solitaire.checkboxpreferences.CheckBoxPreferenceHideMenuButton; import de.tobiasbielefeld.solitaire.checkboxpreferences.CheckBoxPreferenceHideScore; import de.tobiasbielefeld.solitaire.checkboxpreferences.CheckBoxPreferenceHideTime; import de.tobiasbielefeld.solitaire.classes.Card; import de.tobiasbielefeld.solitaire.classes.CustomPreferenceFragment; import de.tobiasbielefeld.solitaire.dialogs.DialogPreferenceBackgroundColor; import de.tobiasbielefeld.solitaire.dialogs.DialogPreferenceCardBackground; import de.tobiasbielefeld.solitaire.dialogs.DialogPreferenceCards; import de.tobiasbielefeld.solitaire.dialogs.DialogPreferenceOnlyForThisGame; import de.tobiasbielefeld.solitaire.dialogs.DialogPreferenceTextColor; import de.tobiasbielefeld.solitaire.helper.Sounds; import static de.tobiasbielefeld.solitaire.SharedData.*; import static de.tobiasbielefeld.solitaire.helper.Preferences.*; /** * Settings activity created with the "Create settings activity" tool from Android Studio. */ public class Settings extends AppCompatPreferenceActivity { private Preference preferenceMenuBarPosition; private Preference preferenceMenuColumns; private Preference preferenceBackgroundVolume; private Preference preferenceMaxNumberUndos; private Preference preferenceGameLayoutMargins; private CheckBoxPreference preferenceSingleTapAllGames; private CheckBoxPreference preferenceTapToSelect; private CheckBoxPreference preferenceImmersiveMode; private DialogPreferenceCards preferenceCards; private DialogPreferenceCardBackground preferenceCardBackground; private DialogPreferenceBackgroundColor preferenceBackgroundColor; private DialogPreferenceTextColor preferenceTextColor; private DialogPreferenceOnlyForThisGame dialogPreferenceOnlyForThisGame; private CheckBoxPreferenceFourColorMode preferenceFourColorMode; private CheckBoxPreferenceHideAutoCompleteButton preferenceHideAutoCompleteButton; private CheckBoxPreferenceHideMenuButton preferenceHideMenuButton; private CheckBoxPreferenceHideScore preferenceHideScore; private CheckBoxPreferenceHideTime preferenceHideTime; private PreferenceCategory categoryOnlyForThisGame; CustomizationPreferenceFragment customizationPreferenceFragment; private Sounds settingsSounds; //make this static so the preference fragments use the same intent //don't forget: Android 8 doesn't call onCreate for the fragments, so there only one intent is //created. Android 7 calls onCreate for each fragment and would create new intents static Intent returnIntent; @Override protected void onCreate(Bundle savedInstanceState) { reinitializeData(getApplicationContext()); super.onCreate(savedInstanceState); ((ViewGroup) getListView().getParent()).setPadding(0, 0, 0, 0); //remove huge padding in landscape ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); } prefs.setCriticalSettings(); settingsSounds = new Sounds(this); if (returnIntent == null) { returnIntent = new Intent(); } } @Override public boolean onIsMultiPane() { return isLargeTablet(this); } @Override public void onBuildHeaders(List<Header> target) { if (prefs.getShowAdvancedSettings()) { loadHeadersFromResource(R.xml.pref_headers_with_advanced_settings, target); } else { loadHeadersFromResource(R.xml.pref_headers, target); } } /* * Update settings when the shared preferences get new values. It uses a lot of if/else instead * of switch/case because only this way i can use getString() to get the xml values, otherwise * I would need to write the strings manually in the cases. */ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(PREF_KEY_SETTINGS_ONLY_FOR_THIS_GAME)) { if (preferenceFourColorMode != null) { preferenceFourColorMode.update(); } if (preferenceHideAutoCompleteButton != null) { preferenceHideAutoCompleteButton.update(); } if (preferenceHideMenuButton != null) { preferenceHideMenuButton.update(); } if (preferenceHideScore != null) { preferenceHideScore.update(); } if (preferenceHideTime != null) { preferenceHideTime.update(); } if (preferenceCards != null) { preferenceCards.updateSummary(); } if (preferenceCardBackground != null) { preferenceCardBackground.updateSummary(); } if (preferenceBackgroundColor != null) { preferenceBackgroundColor.updateSummary(); } if (preferenceTextColor != null) { preferenceTextColor.updateSummary(); } Card.updateCardDrawableChoice(); Card.updateCardBackgroundChoice(); updatePreferenceGameLayoutMarginsSummary(); updatePreferenceMenuBarPositionSummary(); returnIntent.putExtra(getString(R.string.intent_update_game_layout), true); returnIntent.putExtra(getString(R.string.intent_update_menu_bar), true); returnIntent.putExtra(getString(R.string.intent_background_color), true); returnIntent.putExtra(getString(R.string.intent_text_color), true); returnIntent.putExtra(getString(R.string.intent_update_score_visibility), true); returnIntent.putExtra(getString(R.string.intent_update_time_visibility), true); } if (key.equals(PREF_KEY_CARD_DRAWABLES)) { Card.updateCardDrawableChoice(); } else if (key.equals(PREF_KEY_CARD_BACKGROUND) || key.equals(PREF_KEY_CARD_BACKGROUND_COLOR)) { Card.updateCardBackgroundChoice(); } else if (key.equals(PREF_KEY_HIDE_STATUS_BAR)) { showOrHideStatusBar(); } else if (key.equals(PREF_KEY_ORIENTATION)) { setOrientation(); } else if (key.equals(PREF_KEY_LEFT_HANDED_MODE)) { if (gameLogic != null) { gameLogic.mirrorStacks(); } } else if (key.equals(PREF_KEY_MENU_COLUMNS_PORTRAIT) || key.equals(PREF_KEY_MENU_COLUMNS_LANDSCAPE)) { updatePreferenceMenuColumnsSummary(); } else if (key.equals(PREF_KEY_LANGUAGE)) { bitmaps.resetMenuPreviews(); restartApplication(); } else if (key.equals(PREF_KEY_MENU_BAR_POS_LANDSCAPE) || key.equals(PREF_KEY_MENU_BAR_POS_PORTRAIT)) { updatePreferenceMenuBarPositionSummary(); returnIntent.putExtra(getString(R.string.intent_update_menu_bar), true); } else if (key.equals(PREF_KEY_4_COLOR_MODE)) { Card.updateCardDrawableChoice(); if (preferenceCards != null) { preferenceCards.updateSummary(); } } else if (key.equals(PREF_KEY_MOVEMENT_SPEED)) { if (animate != null) { animate.updateMovementSpeed(); } } else if (key.equals(PREF_KEY_WIN_SOUND)) { settingsSounds.playWinSound(); } else if (key.equals(PREF_KEY_BACKGROUND_MUSIC) || key.equals(PREF_KEY_SOUND_ENABLED)) { backgroundSound.doInBackground(this); } else if (key.equals(PREF_KEY_BACKGROUND_VOLUME)) { updatePreferenceBackgroundVolumeSummary(); backgroundSound.doInBackground(this); } else if (key.equals(PREF_KEY_FORCE_TABLET_LAYOUT)) { restartApplication(); } else if (key.equals(PREF_KEY_SINGLE_TAP_ALL_GAMES)) { if (sharedPreferences.getBoolean(key, false) && preferenceTapToSelect != null) { preferenceTapToSelect.setChecked(false); } } else if (key.equals(PREF_KEY_TAP_TO_SELECT_ENABLED)) { if (sharedPreferences.getBoolean(key, false) && preferenceSingleTapAllGames != null) { preferenceSingleTapAllGames.setChecked(false); } } else if (key.equals(PREF_KEY_MAX_NUMBER_UNDOS)) { if (recordList != null) { recordList.setMaxRecords(); } updatePreferenceMaxNumberUndos(); } else if (key.equals(PREF_KEY_SHOW_ADVANCED_SETTINGS)) { final Intent intent = new Intent(getApplicationContext(), Settings.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); finish(); startActivity(intent); } else if (key.equals(PREF_KEY_GAME_LAYOUT_MARGINS_PORTRAIT) || key.equals(PREF_KEY_GAME_LAYOUT_MARGINS_LANDSCAPE)) { updatePreferenceGameLayoutMarginsSummary(); returnIntent.putExtra(getString(R.string.intent_update_game_layout), true); } else if (key.equals(PREF_KEY_HIDE_MENU_BUTTON)) { returnIntent.putExtra(getString(R.string.intent_update_menu_bar), true); } else if (key.equals(PREF_KEY_IMMERSIVE_MODE)) { returnIntent.putExtra(getString(R.string.intent_update_game_layout), true); } else if (key.equals(PREF_KEY_BACKGROUND_COLOR) || key.equals(PREF_KEY_BACKGROUND_COLOR_CUSTOM) || key.equals(PREF_KEY_BACKGROUND_COLOR_TYPE)) { returnIntent.putExtra(getString(R.string.intent_background_color), true); } else if (key.equals(PREF_KEY_TEXT_COLOR)) { returnIntent.putExtra(getString(R.string.intent_text_color), true); } else if (key.equals(PREF_KEY_HIDE_SCORE)) { returnIntent.putExtra(getString(R.string.intent_update_score_visibility), true); } else if (key.equals(PREF_KEY_HIDE_TIME)) { returnIntent.putExtra(getString(R.string.intent_update_time_visibility), true); } else if (key.equals(PREF_KEY_ENSURE_MOVABILITY)) { ArrayList<LoadGame.AllGameInformation> gameInfoList = lg.getOrderedGameInfoList(); for (int i = 0; i < lg.getGameCount(); i++) { SharedPreferences sharedPref = getSharedPreferences(gameInfoList.get(i).getSharedPrefName(), MODE_PRIVATE); sharedPref.edit().putInt(PREF_KEY_ENSURE_MOVABILITY_MIN_MOVES, sharedPref.getInt(PREF_KEY_ENSURE_MOVABILITY_MIN_MOVES, gameInfoList.get(i).getEnsureMovabilityMoves())).apply(); } } } @Override public void finish() { setResult(Activity.RESULT_OK, returnIntent); super.finish(); } /** * Tests if a loaded fragment is valid * * @param fragmentName The name of the fragment to test * @return True if it's valid, false otherwise */ protected boolean isValidFragment(String fragmentName) { return PreferenceFragment.class.getName().equals(fragmentName) || CustomizationPreferenceFragment.class.getName().equals(fragmentName) || OtherPreferenceFragment.class.getName().equals(fragmentName) || MenuPreferenceFragment.class.getName().equals(fragmentName) || AdditionalMovementsPreferenceFragment.class.getName().equals(fragmentName) || SoundPreferenceFragment.class.getName().equals(fragmentName) || DeveloperOptionsPreferenceFragment.class.getName().equals(fragmentName) || ExpertSettingsPreferenceFragment.class.getName().equals(fragmentName); } private void updatePreferenceMenuColumnsSummary() { int portraitValue = prefs.getSavedMenuColumnsPortrait(); int landscapeValue = prefs.getSavedMenuColumnsLandscape(); String text = String.format(Locale.getDefault(), "%s: %d\n%s: %d", getString(R.string.settings_portrait), portraitValue, getString(R.string.settings_landscape), landscapeValue); preferenceMenuColumns.setSummary(text); } private void updatePreferenceGameLayoutMarginsSummary() { String textPortrait = "", textLandscape = ""; switch (prefs.getSavedGameLayoutMarginsPortrait()) { case 0: textPortrait = getString(R.string.settings_game_layout_margins_none); break; case 1: textPortrait = getString(R.string.settings_game_layout_margins_small); break; case 2: textPortrait = getString(R.string.settings_game_layout_margins_medium); break; case 3: textPortrait = getString(R.string.settings_game_layout_margins_large); break; } switch (prefs.getSavedGameLayoutMarginsLandscape()) { case 0: textLandscape = getString(R.string.settings_game_layout_margins_none); break; case 1: textLandscape = getString(R.string.settings_game_layout_margins_small); break; case 2: textLandscape = getString(R.string.settings_game_layout_margins_medium); break; case 3: textLandscape = getString(R.string.settings_game_layout_margins_large); break; } String text = String.format(Locale.getDefault(), "%s: %s\n%s: %s", getString(R.string.settings_portrait), textPortrait, getString(R.string.settings_landscape), textLandscape); preferenceGameLayoutMargins.setSummary(text); } private void updatePreferenceMaxNumberUndos() { int amount = prefs.getSavedMaxNumberUndos(); preferenceMaxNumberUndos.setSummary(Integer.toString(amount)); } private void updatePreferenceMenuBarPositionSummary() { String portrait, landscape; if (prefs.getSavedMenuBarPosPortrait().equals(DEFAULT_MENU_BAR_POSITION_PORTRAIT)) { portrait = getString(R.string.settings_menu_bar_position_bottom); } else { portrait = getString(R.string.settings_menu_bar_position_top); } if (prefs.getSavedMenuBarPosLandscape().equals(DEFAULT_MENU_BAR_POSITION_LANDSCAPE)) { landscape = getString(R.string.settings_menu_bar_position_right); } else { landscape = getString(R.string.settings_menu_bar_position_left); } String text = String.format(Locale.getDefault(), "%s: %s\n%s: %s", getString(R.string.settings_portrait), portrait, getString(R.string.settings_landscape), landscape); preferenceMenuBarPosition.setSummary(text); } private void updatePreferenceBackgroundVolumeSummary() { int volume = prefs.getSavedBackgroundVolume(); preferenceBackgroundVolume.setSummary(String.format(Locale.getDefault(), "%s %%", volume)); } public static class CustomizationPreferenceFragment extends CustomPreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_customize); setHasOptionsMenu(true); Settings settings = (Settings) getActivity(); settings.customizationPreferenceFragment = this; settings.preferenceMenuBarPosition = findPreference(getString(R.string.pref_key_menu_bar_position)); settings.preferenceCards = (DialogPreferenceCards) findPreference(getString(R.string.pref_key_cards)); settings.preferenceGameLayoutMargins = findPreference(getString(R.string.pref_key_game_layout_margins)); settings.preferenceCardBackground = (DialogPreferenceCardBackground) findPreference(getString(R.string.pref_key_cards_background)); settings.preferenceBackgroundColor = (DialogPreferenceBackgroundColor) findPreference(getString(R.string.pref_key_background_color)); settings.preferenceTextColor = (DialogPreferenceTextColor) findPreference(getString(R.string.pref_key_text_color)); settings.preferenceFourColorMode = (CheckBoxPreferenceFourColorMode) findPreference(getString(R.string.dummy_pref_key_4_color_mode)); settings.preferenceHideAutoCompleteButton = (CheckBoxPreferenceHideAutoCompleteButton) findPreference(getString(R.string.dummy_pref_key_hide_auto_complete_button)); settings.preferenceHideMenuButton = (CheckBoxPreferenceHideMenuButton) findPreference(getString(R.string.dummy_pref_key_hide_menu_button)); settings.preferenceHideScore = (CheckBoxPreferenceHideScore) findPreference(getString(R.string.dummy_pref_key_hide_score)); settings.preferenceHideTime = (CheckBoxPreferenceHideTime) findPreference(getString(R.string.dummy_pref_key_hide_time)); settings.dialogPreferenceOnlyForThisGame = (DialogPreferenceOnlyForThisGame) findPreference(getString(R.string.pref_key_settings_only_for_this_game)); //the preferenceCategory for the dialogPreferenceOnlyForThisGame is only used to make //the widget update on Android 8+ devices (otherwise it wouldn't due to a bug) //So remove the title with an empty layout of the category to make it (nearly) disappear settings.categoryOnlyForThisGame = (PreferenceCategory) findPreference(getString(R.string.pref_cat_key_only_for_this_game)); settings.categoryOnlyForThisGame.setLayoutResource(R.layout.empty); settings.preferenceFourColorMode.update(); settings.preferenceHideAutoCompleteButton.update(); settings.preferenceHideMenuButton.update(); settings.preferenceHideScore.update(); settings.preferenceHideTime.update(); settings.updatePreferenceGameLayoutMarginsSummary(); settings.updatePreferenceMenuBarPositionSummary(); settings.hidePreferenceOnlyForThisGame(); } } public void hidePreferenceOnlyForThisGame() { if (dialogPreferenceOnlyForThisGame.canBeHidden()) { customizationPreferenceFragment.getPreferenceScreen().removePreference(categoryOnlyForThisGame); } } public static class OtherPreferenceFragment extends CustomPreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_other); setHasOptionsMenu(true); Settings settings = (Settings) getActivity(); settings.preferenceImmersiveMode = (CheckBoxPreference) findPreference(getString(R.string.pref_key_immersive_mode)); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { settings.preferenceImmersiveMode.setEnabled(false); } } } public static class SoundPreferenceFragment extends CustomPreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_sounds); setHasOptionsMenu(true); Settings settings = (Settings) getActivity(); settings.preferenceBackgroundVolume = findPreference(getString(R.string.pref_key_background_volume)); settings.updatePreferenceBackgroundVolumeSummary(); } } public static class MenuPreferenceFragment extends CustomPreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_menu); setHasOptionsMenu(true); Settings settings = (Settings) getActivity(); settings.preferenceMenuColumns = findPreference(getString(R.string.pref_key_menu_columns)); settings.updatePreferenceMenuColumnsSummary(); } } public static class AdditionalMovementsPreferenceFragment extends CustomPreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_movement_methods); setHasOptionsMenu(true); Settings settings = (Settings) getActivity(); settings.preferenceSingleTapAllGames = (CheckBoxPreference) findPreference(getString(R.string.pref_key_single_tap_all_games)); settings.preferenceTapToSelect = (CheckBoxPreference) findPreference(getString(R.string.pref_key_tap_to_select_enable)); } } public static class DeveloperOptionsPreferenceFragment extends CustomPreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_developer_options); setHasOptionsMenu(true); } } public static class ExpertSettingsPreferenceFragment extends CustomPreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_expert_settings); setHasOptionsMenu(true); Settings settings = (Settings) getActivity(); settings.preferenceMaxNumberUndos = findPreference(getString(R.string.pref_key_max_number_undos)); settings.updatePreferenceMaxNumberUndos(); } } }