package com.xabber.android.ui.preferences; import android.net.Uri; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.EditTextPreference; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceFragment; import android.preference.PreferenceScreen; import android.preference.SwitchPreference; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.xabber.android.ui.activity.PreferenceSummaryHelperActivity; import com.xabber.android.ui.widget.RingtonePreference; import java.util.HashMap; import java.util.Map; public abstract class BaseSettingsFragment extends PreferenceFragment implements Preference.OnPreferenceChangeListener { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); onInflate(savedInstanceState); PreferenceSummaryHelperActivity.updateSummary(getPreferenceScreen()); if (savedInstanceState == null) operation(Operation.read); PreferenceScreen preferenceScreen = getPreferenceScreen(); for (int index = 0; index < preferenceScreen.getPreferenceCount(); index++) { Preference preference = preferenceScreen.getPreference(index); preference.setOnPreferenceChangeListener(this); if (preference instanceof EditTextPreference) onPreferenceChange(preference, ((EditTextPreference) preference).getText()); else if (preference instanceof CheckBoxPreference) onPreferenceChange(preference, ((CheckBoxPreference) preference).isChecked()); else if (preference instanceof ListPreference) onPreferenceChange(preference, ((ListPreference) preference).getValue()); } return view; } /** * Inflates layout. * * @param savedInstanceState */ protected abstract void onInflate(Bundle savedInstanceState); @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (preference instanceof EditTextPreference) preference.setSummary((String) newValue); return true; } /** * Possible operations. */ private enum Operation { save, discard, read } protected void putValue(Map<String, Object> map, int resoureId, Object value) { map.put(getString(resoureId), value); } protected String getString(Map<String, Object> map, int resoureId) { return (String) map.get(getString(resoureId)); } protected int getInt(Map<String, Object> map, int resoureId) { return (Integer) map.get(getString(resoureId)); } protected boolean getBoolean(Map<String, Object> map, int resoureId) { return (Boolean) map.get(getString(resoureId)); } protected Uri getUri(Map<String, Object> map, int resoureId) { return (Uri) map.get(getString(resoureId)); } /** * @param intent * @return Whether an operation succeed. */ private boolean operation(Operation selected) { Map<String, Object> source = getValues(); if (selected == Operation.read) setPreferences(source); else { Map<String, Object> result = getPreferences(source); for (Map.Entry<String, Object> entry : source.entrySet()) if (!result.containsKey(entry.getKey())) result.put(entry.getKey(), entry.getValue()); if (selected == Operation.save) return setValues(source, result); else if (selected == Operation.discard) { for (String key : source.keySet()) if (hasChanges(source, result, key)) return false; } else throw new IllegalStateException(); } return true; } /** * @param source * @param result * @param key * @return Whether value has been changed. */ protected boolean hasChanges(Map<String, Object> source, Map<String, Object> result, String key) { Object sourceValue = source.get(key); Object targetValue = result.get(key); return (sourceValue == null && targetValue != null) || (sourceValue != null && !sourceValue.equals(targetValue)); } /** * @param source * @param result * @param resourceId * @return Whether value has been changed. */ protected boolean hasChanges(Map<String, Object> source, Map<String, Object> result, int resourceId) { return hasChanges(source, result, getString(resourceId)); } /** * @return Map with source values. */ protected abstract Map<String, Object> getValues(); /** * Set values to the UI elements. * * @param source */ protected void setPreferences(Map<String, Object> source) { PreferenceScreen preferenceScreen = getPreferenceScreen(); for (int index = 0; index < preferenceScreen.getPreferenceCount(); index++) { Preference preference = preferenceScreen.getPreference(index); Object value = source.get(preference.getKey()); setPreference(preference, value); } } /** * Set value to the UI element. * * @param preference * @param value */ protected void setPreference(Preference preference, Object value) { if (preference instanceof EditTextPreference) { ((EditTextPreference) preference) .setText(value instanceof Integer ? String.valueOf(value) : (String) value); } else if (preference instanceof CheckBoxPreference) { ((CheckBoxPreference) preference).setChecked((Boolean) value); } else if (preference instanceof SwitchPreference) { ((SwitchPreference) preference).setChecked((Boolean) value); } else if (preference instanceof ListPreference) { ((ListPreference) preference).setValueIndex((Integer) value); } else if (preference instanceof RingtonePreference) { ((RingtonePreference) preference).setUri((Uri) value); } } /** * Get values from the UI elements. * * @param source * @return */ protected Map<String, Object> getPreferences(Map<String, Object> source) { Map<String, Object> result = new HashMap<>(); PreferenceScreen preferenceScreen = getPreferenceScreen(); for (int index = 0; index < preferenceScreen.getPreferenceCount(); index++) { Preference preference = preferenceScreen.getPreference(index); result.put(preference.getKey(), getPreference(preference, source)); } return result; } /** * Get value from the UI element. * * @param preference * @param source * @return */ protected Object getPreference(Preference preference, Map<String, Object> source) { if (preference instanceof PreferenceScreen) { return null; } else if (preference instanceof EditTextPreference) { String value = ((EditTextPreference) preference).getText(); if (source.get(preference.getKey()) instanceof Integer) try { return Integer.parseInt(value); } catch (Exception NumberFormatException) { return null; } else return value; } else if (preference instanceof CheckBoxPreference) { return ((CheckBoxPreference) preference).isChecked(); } else if (preference instanceof SwitchPreference) { return ((SwitchPreference) preference).isChecked(); } else if (preference instanceof ListPreference) { return ((ListPreference) preference) .findIndexOfValue(((ListPreference) preference).getValue()); } else if (preference instanceof RingtonePreference) { return ((RingtonePreference) preference).getUri(); } throw new IllegalStateException(); } /** * Apply result values. * * @param source * @param result * @return Whether operation succeed. */ protected abstract boolean setValues(Map<String, Object> source, Map<String, Object> result); protected boolean saveChanges() { return operation(Operation.save); } }