Android: Specify ini file for every setting

Load all the inis at once, choose which one to write to, and save them all
at the same time. This allows us to modify settings from different files
on the same settings page.
This commit is contained in:
Sean Maas 2016-11-07 21:49:06 -05:00
parent 017ab71fcf
commit 128c1f04ad
20 changed files with 293 additions and 323 deletions

View File

@ -4,9 +4,9 @@ public final class BooleanSetting extends Setting
{ {
private boolean mValue; private boolean mValue;
public BooleanSetting(String key, String section, boolean value) public BooleanSetting(String key, String section, int file, boolean value)
{ {
super(key, section); super(key, section, file);
mValue = value; mValue = value;
} }

View File

@ -4,9 +4,9 @@ public final class FloatSetting extends Setting
{ {
private float mValue; private float mValue;
public FloatSetting(String key, String section, float value) public FloatSetting(String key, String section, int file, float value)
{ {
super(key, section); super(key, section, file);
mValue = value; mValue = value;
} }

View File

@ -4,9 +4,9 @@ public final class IntSetting extends Setting
{ {
private int mValue; private int mValue;
public IntSetting(String key, String section, int value) public IntSetting(String key, String section, int file, int value)
{ {
super(key, section); super(key, section, file);
mValue = value; mValue = value;
} }

View File

@ -10,17 +10,20 @@ public abstract class Setting
{ {
private String mKey; private String mKey;
private String mSection; private String mSection;
private int mFile;
/** /**
* Base constructor. * Base constructor.
* *
* @param key Everything to the left of the = in a line from the ini file. * @param key Everything to the left of the = in a line from the ini file.
* @param section The corresponding recent section header; e.g. [Core] or [Enhancements] without the brackets. * @param section The corresponding recent section header; e.g. [Core] or [Enhancements] without the brackets.
* @param file The ini file the Setting is stored in.
*/ */
public Setting(String key, String section) public Setting(String key, String section, int file)
{ {
mKey = key; mKey = key;
mSection = section; mSection = section;
mFile = file;
} }
/** /**
@ -41,6 +44,15 @@ public abstract class Setting
return mSection; return mSection;
} }
/**
*
* @return The ini file the Setting is stored in.
*/
public int getFile()
{
return mFile;
}
/** /**
* @return A representation of this Setting's backing value converted to a String (e.g. for serialization). * @return A representation of this Setting's backing value converted to a String (e.g. for serialization).
*/ */

View File

@ -4,7 +4,7 @@ import java.util.HashMap;
/** /**
* A semantically-related group of Settings objects. These Settings are * A semantically-related group of Settings objects. These Settings are
* internally stored as a Hashmap. * internally stored as a HashMap.
*/ */
public final class SettingSection public final class SettingSection
{ {
@ -28,18 +28,17 @@ public final class SettingSection
} }
/** /**
* Convenience method; inserts a value directly into the backing Hashmap. * Convenience method; inserts a value directly into the backing HashMap.
* *
* @param key The key where the Setting will be inserted.
* @param setting The Setting to be inserted. * @param setting The Setting to be inserted.
*/ */
public void putSetting(String key, Setting setting) public void putSetting(Setting setting)
{ {
mSettings.put(key, setting); mSettings.put(setting.getKey(), setting);
} }
/** /**
* Convenience method; gets a value directly from the backing Hashmap. * Convenience method; gets a value directly from the backing HashMap.
* *
* @param key Used to retrieve the Setting. * @param key Used to retrieve the Setting.
* @return A Setting object (you should probably cast this before using) * @return A Setting object (you should probably cast this before using)

View File

@ -4,9 +4,9 @@ public final class StringSetting extends Setting
{ {
private String mValue; private String mValue;
public StringSetting(String key, String section, String value) public StringSetting(String key, String section, int file, String value)
{ {
super(key, section); super(key, section, file);
mValue = value; mValue = value;
} }

View File

@ -7,9 +7,9 @@ public final class CheckBoxSetting extends SettingsItem
{ {
private boolean mDefaultValue; private boolean mDefaultValue;
public CheckBoxSetting(String key, String section, int titleId, int descriptionId, boolean defaultValue, Setting setting) public CheckBoxSetting(String key, String section, int file, int titleId, int descriptionId, boolean defaultValue, Setting setting)
{ {
super(key, section, setting, titleId, descriptionId); super(key, section, file, setting, titleId, descriptionId);
mDefaultValue = defaultValue; mDefaultValue = defaultValue;
} }
@ -35,7 +35,7 @@ public final class CheckBoxSetting extends SettingsItem
{ {
if (getSetting() == null) if (getSetting() == null)
{ {
BooleanSetting setting = new BooleanSetting(getKey(), getSection(), checked); BooleanSetting setting = new BooleanSetting(getKey(), getSection(), getFile(), checked);
setSetting(setting); setSetting(setting);
return setting; return setting;
} }

View File

@ -6,7 +6,7 @@ public final class HeaderSetting extends SettingsItem
{ {
public HeaderSetting(String key, Setting setting, int titleId, int descriptionId) public HeaderSetting(String key, Setting setting, int titleId, int descriptionId)
{ {
super(key, null, setting, titleId, descriptionId); super(key, null, 0, setting, titleId, descriptionId);
} }
@Override @Override

View File

@ -19,6 +19,7 @@ public abstract class SettingsItem
private String mKey; private String mKey;
private String mSection; private String mSection;
private int mFile;
private Setting mSetting; private Setting mSetting;
@ -35,10 +36,11 @@ public abstract class SettingsItem
* @param nameId Resource ID for a text string to be displayed as this setting's name. * @param nameId Resource ID for a text string to be displayed as this setting's name.
* @param descriptionId Resource ID for a text string to be displayed as this setting's description. * @param descriptionId Resource ID for a text string to be displayed as this setting's description.
*/ */
public SettingsItem(String key, String section, Setting setting, int nameId, int descriptionId) public SettingsItem(String key, String section, int file, Setting setting, int nameId, int descriptionId)
{ {
mKey = key; mKey = key;
mSection = section; mSection = section;
mFile = file;
mSetting = setting; mSetting = setting;
mNameId = nameId; mNameId = nameId;
mDescriptionId = descriptionId; mDescriptionId = descriptionId;
@ -62,6 +64,15 @@ public abstract class SettingsItem
return mSection; return mSection;
} }
/**
*
* @return The file the backing Setting is saved to.
*/
public int getFile()
{
return mFile;
}
/** /**
* *
* @return The backing Setting, possibly null. * @return The backing Setting, possibly null.

View File

@ -10,9 +10,9 @@ public final class SingleChoiceSetting extends SettingsItem
private int mChoicesId; private int mChoicesId;
private int mValuesId; private int mValuesId;
public SingleChoiceSetting(String key, String section, int titleId, int descriptionId, int choicesId, int valuesId, int defaultValue, Setting setting) public SingleChoiceSetting(String key, String section, int file, int titleId, int descriptionId, int choicesId, int valuesId, int defaultValue, Setting setting)
{ {
super(key, section, setting, titleId, descriptionId); super(key, section, file, setting, titleId, descriptionId);
mValuesId = valuesId; mValuesId = valuesId;
mChoicesId = choicesId; mChoicesId = choicesId;
mDefaultValue = defaultValue; mDefaultValue = defaultValue;
@ -52,7 +52,7 @@ public final class SingleChoiceSetting extends SettingsItem
{ {
if (getSetting() == null) if (getSetting() == null)
{ {
IntSetting setting = new IntSetting(getKey(), getSection(), selection); IntSetting setting = new IntSetting(getKey(), getSection(), getFile(), selection);
setSetting(setting); setSetting(setting);
return setting; return setting;
} }

View File

@ -13,9 +13,9 @@ public final class SliderSetting extends SettingsItem
private String mUnits; private String mUnits;
public SliderSetting(String key, String section, int titleId, int descriptionId, int max, String units, int defaultValue, Setting setting) public SliderSetting(String key, String section, int file, int titleId, int descriptionId, int max, String units, int defaultValue, Setting setting)
{ {
super(key, section, setting, titleId, descriptionId); super(key, section, file, setting, titleId, descriptionId);
mMax = max; mMax = max;
mUnits = units; mUnits = units;
mDefaultValue = defaultValue; mDefaultValue = defaultValue;
@ -70,7 +70,7 @@ public final class SliderSetting extends SettingsItem
{ {
if (getSetting() == null) if (getSetting() == null)
{ {
IntSetting setting = new IntSetting(getKey(), getSection(), selection); IntSetting setting = new IntSetting(getKey(), getSection(), getFile(), selection);
setSetting(setting); setSetting(setting);
return setting; return setting;
} }
@ -93,7 +93,7 @@ public final class SliderSetting extends SettingsItem
{ {
if (getSetting() == null) if (getSetting() == null)
{ {
FloatSetting setting = new FloatSetting(getKey(), getSection(), selection); FloatSetting setting = new FloatSetting(getKey(), getSection(), getFile(), selection);
setSetting(setting); setSetting(setting);
return setting; return setting;
} }

View File

@ -8,7 +8,7 @@ public final class SubmenuSetting extends SettingsItem
public SubmenuSetting(String key, Setting setting, int titleId, int descriptionId, String menuKey) public SubmenuSetting(String key, Setting setting, int titleId, int descriptionId, String menuKey)
{ {
super(key, null, setting, titleId, descriptionId); super(key, null, 0, setting, titleId, descriptionId);
mMenuKey = menuKey; mMenuKey = menuKey;
} }

View File

@ -14,6 +14,7 @@ import org.dolphinemu.dolphinemu.BuildConfig;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.model.settings.SettingSection; import org.dolphinemu.dolphinemu.model.settings.SettingSection;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
public final class SettingsActivity extends AppCompatActivity implements SettingsActivityView public final class SettingsActivity extends AppCompatActivity implements SettingsActivityView
@ -98,19 +99,19 @@ public final class SettingsActivity extends AppCompatActivity implements Setting
} }
@Override @Override
public HashMap<String, SettingSection> getSettings() public HashMap<String, SettingSection> getSettings(int file)
{ {
return mPresenter.getSettings(); return mPresenter.getSettings(file);
} }
@Override @Override
public void setSettings(HashMap<String, SettingSection> settings) public void setSettings(ArrayList<HashMap<String, SettingSection>> settings)
{ {
mPresenter.setSettings(settings); mPresenter.setSettings(settings);
} }
@Override @Override
public void onSettingsFileLoaded(HashMap<String, SettingSection> settings) public void onSettingsFileLoaded(ArrayList<HashMap<String, SettingSection>> settings)
{ {
SettingsFragmentView fragment = getFragment(); SettingsFragmentView fragment = getFragment();

View File

@ -8,20 +8,16 @@ import org.dolphinemu.dolphinemu.model.settings.SettingSection;
import org.dolphinemu.dolphinemu.utils.Log; import org.dolphinemu.dolphinemu.utils.Log;
import org.dolphinemu.dolphinemu.utils.SettingsFile; import org.dolphinemu.dolphinemu.utils.SettingsFile;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
public final class SettingsActivityPresenter public final class SettingsActivityPresenter
{ {
private static final String SHOULD_SAVE = BuildConfig.APPLICATION_ID + ".should_save"; private static final String SHOULD_SAVE = BuildConfig.APPLICATION_ID + ".should_save";
private SettingsActivityView mView; private SettingsActivityView mView;
private String mFileName; private ArrayList<HashMap<String, SettingSection>> mSettings = new ArrayList<>();
private HashMap<String, SettingSection> mSettingsBySection;
private int mStackCount; private int mStackCount;
@ -32,48 +28,16 @@ public final class SettingsActivityPresenter
mView = view; mView = view;
} }
public void onCreate(Bundle savedInstanceState, final String filename) public void onCreate(Bundle savedInstanceState, String menuTag)
{ {
mFileName = filename;
if (savedInstanceState == null) if (savedInstanceState == null)
{ {
// TODO DI should be able to get rid of this hack mView.showSettingsFragment(menuTag, false);
if (filename.equals(SettingsFile.FILE_NAME_GCPAD))
{
// Psyche! Don't actually load that file (yet).
mFileName = SettingsFile.FILE_NAME_DOLPHIN;
// But do display its fragment, as if we had. mSettings.add(SettingsFile.SETTINGS_DOLPHIN, SettingsFile.readFile(SettingsFile.FILE_NAME_DOLPHIN, mView));
mView.showSettingsFragment(SettingsFile.FILE_NAME_GCPAD, false); mSettings.add(SettingsFile.SETTINGS_GFX, SettingsFile.readFile(SettingsFile.FILE_NAME_GFX, mView));
} mSettings.add(SettingsFile.SETTINGS_WIIMOTE, SettingsFile.readFile(SettingsFile.FILE_NAME_WIIMOTE, mView));
else mView.onSettingsFileLoaded(mSettings);
{
mFileName = filename;
mView.showSettingsFragment(mFileName, false);
}
SettingsFile.readFile(mFileName)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<HashMap<String, SettingSection>>()
{
@Override
public void call(HashMap<String, SettingSection> settingsBySection)
{
mSettingsBySection = settingsBySection;
mView.onSettingsFileLoaded(settingsBySection);
}
},
new Action1<Throwable>()
{
@Override
public void call(Throwable throwable)
{
Log.error("[SettingsActivityPresenter] Error reading file " + filename + ".ini: "+ throwable.getMessage());
mView.onSettingsFileNotFound();
}
});
} }
else else
{ {
@ -81,40 +45,25 @@ public final class SettingsActivityPresenter
} }
} }
public void setSettings(HashMap<String, SettingSection> settings) public void setSettings(ArrayList<HashMap<String, SettingSection>> settings)
{ {
mSettingsBySection = settings; mSettings = settings;
} }
public HashMap<String, SettingSection> getSettings() public HashMap<String, SettingSection> getSettings(int file)
{ {
return mSettingsBySection; return mSettings.get(file);
} }
public void onStop(boolean finishing) public void onStop(boolean finishing)
{ {
if (mSettingsBySection != null && finishing && mShouldSave) if (mSettings != null && finishing && mShouldSave)
{ {
Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI..."); Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...");
SettingsFile.saveFile(mFileName, mSettingsBySection) SettingsFile.saveFile(SettingsFile.FILE_NAME_DOLPHIN, mSettings.get(SettingsFile.SETTINGS_DOLPHIN), mView);
.subscribeOn(Schedulers.io()) SettingsFile.saveFile(SettingsFile.FILE_NAME_GFX, mSettings.get(SettingsFile.SETTINGS_GFX), mView);
.observeOn(AndroidSchedulers.mainThread()) SettingsFile.saveFile(SettingsFile.FILE_NAME_WIIMOTE, mSettings.get(SettingsFile.SETTINGS_WIIMOTE), mView);
.subscribe(new Action1<Boolean>() mView.showToastMessage("Saved settings to INI files");
{
@Override
public void call(Boolean aBoolean)
{
mView.showToastMessage("Saved successfully to " + mFileName + ".ini");
}
},
new Action1<Throwable>()
{
@Override
public void call(Throwable throwable)
{
mView.showToastMessage("Error saving " + mFileName + ".ini: " + throwable.getMessage());
}
});
} }
} }

View File

@ -2,6 +2,7 @@ package org.dolphinemu.dolphinemu.ui.settings;
import org.dolphinemu.dolphinemu.model.settings.SettingSection; import org.dolphinemu.dolphinemu.model.settings.SettingSection;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
/** /**
@ -18,29 +19,30 @@ public interface SettingsActivityView
void showSettingsFragment(String menuTag, boolean addToStack); void showSettingsFragment(String menuTag, boolean addToStack);
/** /**
* Called by a contained Fragment to get access to the Setting Hashmap * Called by a contained Fragment to get access to the Setting HashMap
* loaded from disk, so that each Fragment doesn't need to perform its own * loaded from disk, so that each Fragment doesn't need to perform its own
* read operation. * read operation.
* *
* @return A possibly null Hashmap of Settings. * @param file The settings file to load.
* @return A possibly null HashMap of Settings.
*/ */
HashMap<String, SettingSection> getSettings(); HashMap<String, SettingSection> getSettings(int file);
/** /**
* Used to provide the Activity with a Settings Hashmap if a Fragment already * Used to provide the Activity with Settings HashMaps if a Fragment already
* has one; for example, if a rotation occurs, the Fragment will not be killed, * has one; for example, if a rotation occurs, the Fragment will not be killed,
* but the Activity will, so the Activity needs to have its Hashmap resupplied. * but the Activity will, so the Activity needs to have its HashMaps resupplied.
* *
* @param settings The Fragment's Settings hashmap. * @param settings The ArrayList of all the Settings HashMaps.
*/ */
void setSettings(HashMap<String, SettingSection> settings); void setSettings(ArrayList<HashMap<String, SettingSection>> settings);
/** /**
* Called when an asynchronous load operation completes. * Called when an asynchronous load operation completes.
* *
* @param settings The (possibly null) result of the load operation. * @param settings The (possibly null) result of the ini load operation.
*/ */
void onSettingsFileLoaded(HashMap<String, SettingSection> settings); void onSettingsFileLoaded(ArrayList<HashMap<String, SettingSection>> settings);
/** /**
* Called when an asynchronous load operation fails. * Called when an asynchronous load operation fails.

View File

@ -132,7 +132,7 @@ public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolde
if (item.getKey().equals(SettingsFile.KEY_SKIP_EFB) || item.getKey().equals(SettingsFile.KEY_IGNORE_FORMAT)) if (item.getKey().equals(SettingsFile.KEY_SKIP_EFB) || item.getKey().equals(SettingsFile.KEY_IGNORE_FORMAT))
{ {
mView.putSetting(new BooleanSetting(item.getKey(), item.getSection(), !checked)); mView.putSetting(new BooleanSetting(item.getKey(), item.getSection(), item.getFile(), !checked));
} }
mView.onSettingChanged(); mView.onSettingChanged();
@ -334,19 +334,19 @@ public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolde
switch (which) switch (which)
{ {
case 0: case 0:
gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, SettingsFile.SECTION_CORE, "OGL"); gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, "OGL");
break; break;
case 1: case 1:
gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, SettingsFile.SECTION_CORE, "Vulkan"); gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, "Vulkan");
break; break;
case 2: case 2:
gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, SettingsFile.SECTION_CORE, "SW"); gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, "SW");
break; break;
case 3: case 3:
gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, SettingsFile.SECTION_CORE, "Null"); gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, "Null");
break; break;
} }
@ -361,18 +361,18 @@ public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolde
switch (which) switch (which)
{ {
case 0: case 0:
xfbEnable = new BooleanSetting(SettingsFile.KEY_XFB, SettingsFile.SECTION_GFX_SETTINGS, false); xfbEnable = new BooleanSetting(SettingsFile.KEY_XFB, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, false);
xfbReal = new BooleanSetting(SettingsFile.KEY_XFB_REAL, SettingsFile.SECTION_GFX_SETTINGS, false); xfbReal = new BooleanSetting(SettingsFile.KEY_XFB_REAL, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, false);
break; break;
case 1: case 1:
xfbEnable = new BooleanSetting(SettingsFile.KEY_XFB, SettingsFile.SECTION_GFX_SETTINGS, true); xfbEnable = new BooleanSetting(SettingsFile.KEY_XFB, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, true);
xfbReal = new BooleanSetting(SettingsFile.KEY_XFB_REAL, SettingsFile.SECTION_GFX_SETTINGS, false); xfbReal = new BooleanSetting(SettingsFile.KEY_XFB_REAL, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, false);
break; break;
case 2: case 2:
xfbEnable = new BooleanSetting(SettingsFile.KEY_XFB, SettingsFile.SECTION_GFX_SETTINGS, true); xfbEnable = new BooleanSetting(SettingsFile.KEY_XFB, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, true);
xfbReal = new BooleanSetting(SettingsFile.KEY_XFB_REAL, SettingsFile.SECTION_GFX_SETTINGS, true); xfbReal = new BooleanSetting(SettingsFile.KEY_XFB_REAL, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, true);
break; break;
} }

View File

@ -17,6 +17,7 @@ import org.dolphinemu.dolphinemu.model.settings.Setting;
import org.dolphinemu.dolphinemu.model.settings.SettingSection; import org.dolphinemu.dolphinemu.model.settings.SettingSection;
import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem;
import org.dolphinemu.dolphinemu.ui.DividerItemDecoration; import org.dolphinemu.dolphinemu.ui.DividerItemDecoration;
import org.dolphinemu.dolphinemu.utils.SettingsFile;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -83,7 +84,11 @@ public final class SettingsFragment extends Fragment implements SettingsFragment
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), null)); recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), null));
SettingsActivityView activity = (SettingsActivityView) getActivity(); SettingsActivityView activity = (SettingsActivityView) getActivity();
HashMap<String, SettingSection> settings = activity.getSettings();
ArrayList<HashMap<String, SettingSection>> settings = new ArrayList<>();
settings.add(SettingsFile.SETTINGS_DOLPHIN, activity.getSettings(SettingsFile.SETTINGS_DOLPHIN));
settings.add(SettingsFile.SETTINGS_GFX, activity.getSettings(SettingsFile.SETTINGS_GFX));
settings.add(SettingsFile.SETTINGS_WIIMOTE, activity.getSettings(SettingsFile.SETTINGS_WIIMOTE));
mPresenter.onViewCreated(settings); mPresenter.onViewCreated(settings);
} }
@ -101,13 +106,13 @@ public final class SettingsFragment extends Fragment implements SettingsFragment
} }
@Override @Override
public void onSettingsFileLoaded(HashMap<String, SettingSection> settings) public void onSettingsFileLoaded(ArrayList<HashMap<String, SettingSection>> settings)
{ {
mPresenter.setSettings(settings); mPresenter.setSettings(settings);
} }
@Override @Override
public void passSettingsToActivity(HashMap<String, SettingSection> settings) public void passSettingsToActivity(ArrayList<HashMap<String, SettingSection>> settings)
{ {
if (mActivity != null) if (mActivity != null)
{ {

View File

@ -24,7 +24,7 @@ public final class SettingsFragmentPresenter
private String mMenuTag; private String mMenuTag;
private HashMap<String, SettingSection> mSettings; private ArrayList<HashMap<String, SettingSection>> mSettings;
private ArrayList<SettingsItem> mSettingsList; private ArrayList<SettingsItem> mSettingsList;
private int mGcPadNumber; private int mGcPadNumber;
@ -47,7 +47,7 @@ public final class SettingsFragmentPresenter
} }
} }
public void onViewCreated(HashMap<String, SettingSection> settings) public void onViewCreated(ArrayList<HashMap<String, SettingSection>> settings)
{ {
setSettings(settings); setSettings(settings);
} }
@ -67,7 +67,7 @@ public final class SettingsFragmentPresenter
public void putSetting(Setting setting) public void putSetting(Setting setting)
{ {
mSettings.get(setting.getSection()).putSetting(setting.getKey(), setting); mSettings.get(setting.getFile()).get(setting.getSection()).putSetting(setting);
} }
public void loadDefaultSettings() public void loadDefaultSettings()
@ -75,7 +75,7 @@ public final class SettingsFragmentPresenter
loadSettingsList(); loadSettingsList();
} }
public void setSettings(HashMap<String, SettingSection> settings) public void setSettings(ArrayList<HashMap<String, SettingSection>> settings)
{ {
if (mSettingsList == null && settings != null) if (mSettingsList == null && settings != null)
{ {
@ -138,89 +138,80 @@ public final class SettingsFragmentPresenter
Setting dualCore = null; Setting dualCore = null;
Setting overclockEnable = null; Setting overclockEnable = null;
Setting overclock = null; Setting overclock = null;
IntSetting videoBackend = new IntSetting(SettingsFile.KEY_VIDEO_BACKEND_INDEX, SettingsFile.SECTION_CORE, getVideoBackendValue());
Setting continuousScan = null; Setting continuousScan = null;
Setting wiimoteSpeaker = null; Setting wiimoteSpeaker = null;
if (mSettings != null) if (!mSettings.get(SettingsFile.SETTINGS_DOLPHIN).isEmpty())
{ {
cpuCore = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_CPU_CORE); cpuCore = mSettings.get(SettingsFile.SETTINGS_DOLPHIN).get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_CPU_CORE);
dualCore = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_DUAL_CORE); dualCore = mSettings.get(SettingsFile.SETTINGS_DOLPHIN).get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_DUAL_CORE);
overclockEnable = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_OVERCLOCK_ENABLE); overclockEnable = mSettings.get(SettingsFile.SETTINGS_DOLPHIN).get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_OVERCLOCK_ENABLE);
overclock = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_OVERCLOCK_PERCENT); overclock = mSettings.get(SettingsFile.SETTINGS_DOLPHIN).get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_OVERCLOCK_PERCENT);
continuousScan = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_WIIMOTE_SCAN); continuousScan = mSettings.get(SettingsFile.SETTINGS_DOLPHIN).get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_WIIMOTE_SCAN);
wiimoteSpeaker = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_WIIMOTE_SPEAKER); wiimoteSpeaker = mSettings.get(SettingsFile.SETTINGS_DOLPHIN).get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_WIIMOTE_SPEAKER);
} }
else else
{ {
mSettings = new HashMap<>(); mSettings.get(SettingsFile.SETTINGS_DOLPHIN).put(SettingsFile.SECTION_CORE, new SettingSection(SettingsFile.SECTION_CORE));
mSettings.put(SettingsFile.SECTION_CORE, new SettingSection(SettingsFile.SECTION_CORE));
mView.passSettingsToActivity(mSettings); mView.passSettingsToActivity(mSettings);
} }
// TODO Set default value for cpuCore based on arch. // TODO Set default value for cpuCore based on arch.
sl.add(new SingleChoiceSetting(SettingsFile.KEY_CPU_CORE, SettingsFile.SECTION_CORE, R.string.cpu_core, 0, R.array.emuCoresEntries, R.array.emuCoresValues, 4, cpuCore)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_CPU_CORE, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.cpu_core, 0, R.array.emuCoresEntries, R.array.emuCoresValues, 4, cpuCore));
sl.add(new CheckBoxSetting(SettingsFile.KEY_DUAL_CORE, SettingsFile.SECTION_CORE, R.string.dual_core, R.string.dual_core_descrip, true, dualCore)); sl.add(new CheckBoxSetting(SettingsFile.KEY_DUAL_CORE, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.dual_core, R.string.dual_core_descrip, true, dualCore));
sl.add(new CheckBoxSetting(SettingsFile.KEY_OVERCLOCK_ENABLE, SettingsFile.SECTION_CORE, R.string.overclock_enable, R.string.overclock_enable_description, false, overclockEnable)); sl.add(new CheckBoxSetting(SettingsFile.KEY_OVERCLOCK_ENABLE, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.overclock_enable, R.string.overclock_enable_description, false, overclockEnable));
sl.add(new SliderSetting(SettingsFile.KEY_OVERCLOCK_PERCENT, SettingsFile.SECTION_CORE, R.string.overclock_title, 0, 400, "%", 100, overclock)); sl.add(new SliderSetting(SettingsFile.KEY_OVERCLOCK_PERCENT, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.overclock_title, 0, 400, "%", 100, overclock));
sl.add(new CheckBoxSetting(SettingsFile.KEY_WIIMOTE_SCAN, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.wiimote_scanning, R.string.wiimote_scanning_description, true, continuousScan));
// While it doesn't seem appropriate to store the video backend with the CPU settings, the video sl.add(new CheckBoxSetting(SettingsFile.KEY_WIIMOTE_SPEAKER, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.wiimote_speaker, R.string.wiimote_speaker_description, true, wiimoteSpeaker));
// backend is stored in the main INI, which can't be changed by the graphics settings page, so
// we have to put it here.
sl.add(new SingleChoiceSetting(SettingsFile.KEY_VIDEO_BACKEND_INDEX, SettingsFile.SECTION_CORE, R.string.video_backend, R.string.video_backend_descrip,
R.array.videoBackendEntries, R.array.videoBackendValues, 0, videoBackend));
sl.add(new CheckBoxSetting(SettingsFile.KEY_WIIMOTE_SCAN, SettingsFile.SECTION_CORE, R.string.wiimote_scanning, R.string.wiimote_scanning_description, true, continuousScan));
sl.add(new CheckBoxSetting(SettingsFile.KEY_WIIMOTE_SPEAKER, SettingsFile.SECTION_CORE, R.string.wiimote_speaker, R.string.wiimote_speaker_description, true, wiimoteSpeaker));
} }
private void addGcPadSettings(ArrayList<SettingsItem> sl) private void addGcPadSettings(ArrayList<SettingsItem> sl)
{ {
if (mSettings != null) if (!mSettings.get(SettingsFile.SETTINGS_DOLPHIN).isEmpty())
{ {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
// TODO This controller_0 + i business is quite the hack. It should work, but only if the definitions are kept together and in order. // TODO This controller_0 + i business is quite the hack. It should work, but only if the definitions are kept together and in order.
Setting gcPadSetting = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_GCPAD_TYPE + i); Setting gcPadSetting = mSettings.get(SettingsFile.SETTINGS_DOLPHIN).get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_GCPAD_TYPE + i);
sl.add(new SingleChoiceSetting(SettingsFile.KEY_GCPAD_TYPE + i, SettingsFile.SECTION_CORE, R.string.controller_0 + i, 0, R.array.gcpadTypeEntries, R.array.gcpadTypeValues, 0, gcPadSetting)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_GCPAD_TYPE + i, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.controller_0 + i, 0, R.array.gcpadTypeEntries, R.array.gcpadTypeValues, 0, gcPadSetting));
} }
} }
} }
private void addWiimoteSettings(ArrayList<SettingsItem> sl) private void addWiimoteSettings(ArrayList<SettingsItem> sl)
{ {
if (mSettings != null) if (!mSettings.get(SettingsFile.SETTINGS_WIIMOTE).isEmpty())
{ {
for (int i = 1; i <= 4; i++) for (int i = 1; i <= 4; i++)
{ {
// TODO This wiimote_0 + i business is quite the hack. It should work, but only if the definitions are kept together and in order. // TODO This wiimote_0 + i business is quite the hack. It should work, but only if the definitions are kept together and in order.
Setting wiimoteSetting = mSettings.get(SettingsFile.SECTION_WIIMOTE + i).getSetting(SettingsFile.KEY_WIIMOTE_TYPE); Setting wiimoteSetting = mSettings.get(SettingsFile.SETTINGS_WIIMOTE).get(SettingsFile.SECTION_WIIMOTE + i).getSetting(SettingsFile.KEY_WIIMOTE_TYPE);
sl.add(new SingleChoiceSetting(SettingsFile.KEY_WIIMOTE_TYPE, SettingsFile.SECTION_WIIMOTE + i, R.string.wiimote_0 + i - 1, 0, R.array.wiimoteTypeEntries, R.array.wiimoteTypeValues, 0, wiimoteSetting)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_WIIMOTE_TYPE, SettingsFile.SECTION_WIIMOTE + i, SettingsFile.SETTINGS_WIIMOTE, R.string.wiimote_0 + i - 1, 0, R.array.wiimoteTypeEntries, R.array.wiimoteTypeValues, 0, wiimoteSetting));
} }
} }
} }
private void addGraphicsSettings(ArrayList<SettingsItem> sl) private void addGraphicsSettings(ArrayList<SettingsItem> sl)
{ {
IntSetting videoBackend = new IntSetting(SettingsFile.KEY_VIDEO_BACKEND_INDEX, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, getVideoBackendValue());
Setting showFps = null; Setting showFps = null;
if (mSettings != null) if (!mSettings.get(SettingsFile.SETTINGS_GFX).isEmpty())
{ {
showFps = mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_SHOW_FPS); showFps = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_SHOW_FPS);
} }
else else
{ {
mSettings = new HashMap<>(); mSettings.get(SettingsFile.SETTINGS_GFX).put(SettingsFile.SECTION_GFX_SETTINGS, new SettingSection(SettingsFile.SECTION_GFX_SETTINGS));
mSettings.get(SettingsFile.SETTINGS_GFX).put(SettingsFile.SECTION_GFX_ENHANCEMENTS, new SettingSection(SettingsFile.SECTION_GFX_ENHANCEMENTS));
mSettings.put(SettingsFile.SECTION_GFX_SETTINGS, new SettingSection(SettingsFile.SECTION_GFX_SETTINGS)); mSettings.get(SettingsFile.SETTINGS_GFX).put(SettingsFile.SECTION_GFX_HACKS, new SettingSection(SettingsFile.SECTION_GFX_HACKS));
mSettings.put(SettingsFile.SECTION_GFX_ENHANCEMENTS, new SettingSection(SettingsFile.SECTION_GFX_ENHANCEMENTS));
mSettings.put(SettingsFile.SECTION_GFX_HACKS, new SettingSection(SettingsFile.SECTION_GFX_HACKS));
mView.passSettingsToActivity(mSettings); mView.passSettingsToActivity(mSettings);
} }
sl.add(new CheckBoxSetting(SettingsFile.KEY_SHOW_FPS, SettingsFile.SECTION_GFX_SETTINGS, R.string.show_fps, 0, true, showFps)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_VIDEO_BACKEND_INDEX, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.video_backend, R.string.video_backend_descrip, R.array.videoBackendEntries, R.array.videoBackendValues, 0, videoBackend));
sl.add(new CheckBoxSetting(SettingsFile.KEY_SHOW_FPS, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.show_fps, 0, true, showFps));
sl.add(new SubmenuSetting(null, null, R.string.enhancements, 0, SettingsFile.SECTION_GFX_ENHANCEMENTS)); sl.add(new SubmenuSetting(null, null, R.string.enhancements, 0, SettingsFile.SECTION_GFX_ENHANCEMENTS));
sl.add(new SubmenuSetting(null, null, R.string.hacks, 0, SettingsFile.SECTION_GFX_HACKS)); sl.add(new SubmenuSetting(null, null, R.string.hacks, 0, SettingsFile.SECTION_GFX_HACKS));
@ -228,26 +219,26 @@ public final class SettingsFragmentPresenter
private void addEnhanceSettings(ArrayList<SettingsItem> sl) private void addEnhanceSettings(ArrayList<SettingsItem> sl)
{ {
Setting resolution = mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_INTERNAL_RES); Setting resolution = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_INTERNAL_RES);
Setting fsaa = mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_FSAA); Setting fsaa = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_FSAA);
Setting anisotropic = mSettings.get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_ANISOTROPY); Setting anisotropic = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_ANISOTROPY);
Setting efbScaledCopy = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_SCALED_EFB); Setting efbScaledCopy = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_SCALED_EFB);
Setting perPixel = mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_PER_PIXEL); Setting perPixel = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_PER_PIXEL);
Setting forceFilter = mSettings.get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_FORCE_FILTERING); Setting forceFilter = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_FORCE_FILTERING);
Setting disableFog = mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_DISABLE_FOG); Setting disableFog = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_DISABLE_FOG);
sl.add(new SingleChoiceSetting(SettingsFile.KEY_INTERNAL_RES, SettingsFile.SECTION_GFX_SETTINGS, R.string.internal_resolution, R.string.internal_resolution_descrip, R.array.internalResolutionEntries, R.array.internalResolutionValues, 0, resolution)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_INTERNAL_RES, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.internal_resolution, R.string.internal_resolution_descrip, R.array.internalResolutionEntries, R.array.internalResolutionValues, 0, resolution));
sl.add(new SingleChoiceSetting(SettingsFile.KEY_FSAA, SettingsFile.SECTION_GFX_SETTINGS, R.string.FSAA, R.string.FSAA_descrip, R.array.FSAAEntries, R.array.FSAAValues, 0, fsaa)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_FSAA, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.FSAA, R.string.FSAA_descrip, R.array.FSAAEntries, R.array.FSAAValues, 0, fsaa));
sl.add(new SingleChoiceSetting(SettingsFile.KEY_ANISOTROPY, SettingsFile.SECTION_GFX_ENHANCEMENTS, R.string.anisotropic_filtering, R.string.anisotropic_filtering_descrip, R.array.anisotropicFilteringEntries, R.array.anisotropicFilteringValues, 0, anisotropic)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_ANISOTROPY, SettingsFile.SECTION_GFX_ENHANCEMENTS, SettingsFile.SETTINGS_GFX, R.string.anisotropic_filtering, R.string.anisotropic_filtering_descrip, R.array.anisotropicFilteringEntries, R.array.anisotropicFilteringValues, 0, anisotropic));
// TODO // TODO
// Setting shader = mSettings.get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_POST_SHADER) // Setting shader = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_POST_SHADER)
// sl.add(new SingleChoiceSetting(.getKey(), , R.string., R.string._descrip, R.array., R.array.)); // sl.add(new SingleChoiceSetting(.getKey(), , R.string., R.string._descrip, R.array., R.array.));
sl.add(new CheckBoxSetting(SettingsFile.KEY_SCALED_EFB, SettingsFile.SECTION_GFX_HACKS, R.string.scaled_efb_copy, R.string.scaled_efb_copy_descrip, true, efbScaledCopy)); sl.add(new CheckBoxSetting(SettingsFile.KEY_SCALED_EFB, SettingsFile.SECTION_GFX_HACKS, SettingsFile.SETTINGS_GFX, R.string.scaled_efb_copy, R.string.scaled_efb_copy_descrip, true, efbScaledCopy));
sl.add(new CheckBoxSetting(SettingsFile.KEY_PER_PIXEL, SettingsFile.SECTION_GFX_SETTINGS, R.string.per_pixel_lighting, R.string.per_pixel_lighting_descrip, false, perPixel)); sl.add(new CheckBoxSetting(SettingsFile.KEY_PER_PIXEL, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.per_pixel_lighting, R.string.per_pixel_lighting_descrip, false, perPixel));
sl.add(new CheckBoxSetting(SettingsFile.KEY_FORCE_FILTERING, SettingsFile.SECTION_GFX_ENHANCEMENTS, R.string.force_texture_filtering, R.string.force_texture_filtering_descrip, false, forceFilter)); sl.add(new CheckBoxSetting(SettingsFile.KEY_FORCE_FILTERING, SettingsFile.SECTION_GFX_ENHANCEMENTS, SettingsFile.SETTINGS_GFX, R.string.force_texture_filtering, R.string.force_texture_filtering_descrip, false, forceFilter));
sl.add(new CheckBoxSetting(SettingsFile.KEY_DISABLE_FOG, SettingsFile.SECTION_GFX_SETTINGS, R.string.disable_fog, R.string.disable_fog_descrip, false, disableFog)); sl.add(new CheckBoxSetting(SettingsFile.KEY_DISABLE_FOG, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.disable_fog, R.string.disable_fog_descrip, false, disableFog));
/* /*
Check if we support stereo Check if we support stereo
@ -265,48 +256,48 @@ public final class SettingsFragmentPresenter
private void addHackSettings(ArrayList<SettingsItem> sl) private void addHackSettings(ArrayList<SettingsItem> sl)
{ {
boolean skipEFBValue = getInvertedBooleanValue(SettingsFile.SECTION_GFX_HACKS, SettingsFile.KEY_SKIP_EFB, false); boolean skipEFBValue = getInvertedBooleanValue(SettingsFile.SETTINGS_GFX, SettingsFile.SECTION_GFX_HACKS, SettingsFile.KEY_SKIP_EFB, false);
boolean ignoreFormatValue = getInvertedBooleanValue(SettingsFile.SECTION_GFX_HACKS, SettingsFile.KEY_IGNORE_FORMAT, true); boolean ignoreFormatValue = getInvertedBooleanValue(SettingsFile.SETTINGS_GFX, SettingsFile.SECTION_GFX_HACKS, SettingsFile.KEY_IGNORE_FORMAT, true);
int xfbValue = getXfbValue(); int xfbValue = getXfbValue();
BooleanSetting skipEFB = new BooleanSetting(SettingsFile.KEY_SKIP_EFB, SettingsFile.SECTION_GFX_HACKS, skipEFBValue); BooleanSetting skipEFB = new BooleanSetting(SettingsFile.KEY_SKIP_EFB, SettingsFile.SECTION_GFX_HACKS, SettingsFile.SETTINGS_GFX, skipEFBValue);
BooleanSetting ignoreFormat = new BooleanSetting(SettingsFile.KEY_IGNORE_FORMAT, SettingsFile.SECTION_GFX_HACKS, ignoreFormatValue); BooleanSetting ignoreFormat = new BooleanSetting(SettingsFile.KEY_IGNORE_FORMAT, SettingsFile.SECTION_GFX_HACKS, SettingsFile.SETTINGS_GFX, ignoreFormatValue);
Setting efbToTexture = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_EFB_TEXTURE); Setting efbToTexture = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_EFB_TEXTURE);
Setting texCacheAccuracy = mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_TEXCACHE_ACCURACY); Setting texCacheAccuracy = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_TEXCACHE_ACCURACY);
IntSetting xfb = new IntSetting(SettingsFile.KEY_XFB, SettingsFile.SECTION_GFX_HACKS, xfbValue); IntSetting xfb = new IntSetting(SettingsFile.KEY_XFB, SettingsFile.SECTION_GFX_HACKS, SettingsFile.SETTINGS_GFX, xfbValue);
Setting fastDepth = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_FAST_DEPTH); Setting fastDepth = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_FAST_DEPTH);
Setting aspectRatio = mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_ASPECT_RATIO); Setting aspectRatio = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_ASPECT_RATIO);
sl.add(new HeaderSetting(null, null, R.string.embedded_frame_buffer, 0)); sl.add(new HeaderSetting(null, null, R.string.embedded_frame_buffer, 0));
sl.add(new CheckBoxSetting(SettingsFile.KEY_SKIP_EFB, SettingsFile.SECTION_GFX_HACKS, R.string.skip_efb_access, R.string.skip_efb_access_descrip, false, skipEFB)); sl.add(new CheckBoxSetting(SettingsFile.KEY_SKIP_EFB, SettingsFile.SECTION_GFX_HACKS, SettingsFile.SETTINGS_GFX, R.string.skip_efb_access, R.string.skip_efb_access_descrip, false, skipEFB));
sl.add(new CheckBoxSetting(SettingsFile.KEY_IGNORE_FORMAT, SettingsFile.SECTION_GFX_HACKS, R.string.ignore_format_changes, R.string.ignore_format_changes_descrip, true, ignoreFormat)); sl.add(new CheckBoxSetting(SettingsFile.KEY_IGNORE_FORMAT, SettingsFile.SECTION_GFX_HACKS, SettingsFile.SETTINGS_GFX, R.string.ignore_format_changes, R.string.ignore_format_changes_descrip, true, ignoreFormat));
sl.add(new CheckBoxSetting(SettingsFile.KEY_EFB_TEXTURE, SettingsFile.SECTION_GFX_HACKS, R.string.efb_copy_method, R.string.efb_copy_method_descrip, true, efbToTexture)); sl.add(new CheckBoxSetting(SettingsFile.KEY_EFB_TEXTURE, SettingsFile.SECTION_GFX_HACKS, SettingsFile.SETTINGS_GFX, R.string.efb_copy_method, R.string.efb_copy_method_descrip, true, efbToTexture));
sl.add(new HeaderSetting(null, null, R.string.texture_cache, 0)); sl.add(new HeaderSetting(null, null, R.string.texture_cache, 0));
sl.add(new SingleChoiceSetting(SettingsFile.KEY_TEXCACHE_ACCURACY, SettingsFile.SECTION_GFX_SETTINGS, R.string.texture_cache_accuracy, R.string.texture_cache_accuracy_descrip, R.array.textureCacheAccuracyEntries, R.array.textureCacheAccuracyValues, 128, texCacheAccuracy)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_TEXCACHE_ACCURACY, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.texture_cache_accuracy, R.string.texture_cache_accuracy_descrip, R.array.textureCacheAccuracyEntries, R.array.textureCacheAccuracyValues, 128, texCacheAccuracy));
sl.add(new HeaderSetting(null, null, R.string.external_frame_buffer, 0)); sl.add(new HeaderSetting(null, null, R.string.external_frame_buffer, 0));
sl.add(new SingleChoiceSetting(SettingsFile.KEY_XFB_METHOD, SettingsFile.SECTION_GFX_HACKS, R.string.external_frame_buffer, R.string.external_frame_buffer_descrip, R.array.externalFrameBufferEntries, R.array.externalFrameBufferValues, 0, xfb)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_XFB_METHOD, SettingsFile.SECTION_GFX_HACKS, SettingsFile.SETTINGS_GFX, R.string.external_frame_buffer, R.string.external_frame_buffer_descrip, R.array.externalFrameBufferEntries, R.array.externalFrameBufferValues, 0, xfb));
sl.add(new HeaderSetting(null, null, R.string.other, 0)); sl.add(new HeaderSetting(null, null, R.string.other, 0));
sl.add(new CheckBoxSetting(SettingsFile.KEY_FAST_DEPTH, SettingsFile.SECTION_GFX_HACKS, R.string.fast_depth_calculation, R.string.fast_depth_calculation_descrip, true, fastDepth)); sl.add(new CheckBoxSetting(SettingsFile.KEY_FAST_DEPTH, SettingsFile.SECTION_GFX_HACKS, SettingsFile.SETTINGS_GFX, R.string.fast_depth_calculation, R.string.fast_depth_calculation_descrip, true, fastDepth));
sl.add(new SingleChoiceSetting(SettingsFile.KEY_ASPECT_RATIO, SettingsFile.SECTION_GFX_SETTINGS, R.string.aspect_ratio, R.string.aspect_ratio_descrip, R.array.aspectRatioEntries, R.array.aspectRatioValues, 0, aspectRatio)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_ASPECT_RATIO, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.aspect_ratio, R.string.aspect_ratio_descrip, R.array.aspectRatioEntries, R.array.aspectRatioValues, 0, aspectRatio));
} }
private void addGcAdapterSettings(ArrayList<SettingsItem> sl, int gcPadNumber) private void addGcAdapterSettings(ArrayList<SettingsItem> sl, int gcPadNumber)
{ {
Setting rumble = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_GCADAPTER_RUMBLE + gcPadNumber); Setting rumble = mSettings.get(SettingsFile.SETTINGS_DOLPHIN).get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_GCADAPTER_RUMBLE + gcPadNumber);
Setting bongos = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_GCADAPTER_BONGOS + gcPadNumber); Setting bongos = mSettings.get(SettingsFile.SETTINGS_DOLPHIN).get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_GCADAPTER_BONGOS + gcPadNumber);
sl.add(new CheckBoxSetting(SettingsFile.KEY_GCADAPTER_RUMBLE + gcPadNumber, SettingsFile.SECTION_CORE, R.string.gc_adapter_rumble, R.string.gc_adapter_rumble_description, false, rumble)); sl.add(new CheckBoxSetting(SettingsFile.KEY_GCADAPTER_RUMBLE + gcPadNumber, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.gc_adapter_rumble, R.string.gc_adapter_rumble_description, false, rumble));
sl.add(new CheckBoxSetting(SettingsFile.KEY_GCADAPTER_BONGOS + gcPadNumber, SettingsFile.SECTION_CORE, R.string.gc_adapter_bongos, R.string.gc_adapter_bongos_description, false, bongos)); sl.add(new CheckBoxSetting(SettingsFile.KEY_GCADAPTER_BONGOS + gcPadNumber, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.gc_adapter_bongos, R.string.gc_adapter_bongos_description, false, bongos));
} }
private boolean getInvertedBooleanValue(String section, String key, boolean defaultValue) private boolean getInvertedBooleanValue(int file, String section, String key, boolean defaultValue)
{ {
try try
{ {
return !((BooleanSetting) mSettings.get(section).getSetting(key)).getValue(); return !((BooleanSetting) mSettings.get(file).get(section).getSetting(key)).getValue();
} }
catch (NullPointerException ex) catch (NullPointerException ex)
{ {
@ -320,7 +311,7 @@ public final class SettingsFragmentPresenter
try try
{ {
String videoBackend = ((StringSetting)mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_VIDEO_BACKEND)).getValue(); String videoBackend = ((StringSetting)mSettings.get(SettingsFile.SETTINGS_DOLPHIN).get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_VIDEO_BACKEND)).getValue();
if (videoBackend.equals("OGL")) if (videoBackend.equals("OGL"))
videoBackendValue = 0; videoBackendValue = 0;
else if (videoBackend.equals("Vulkan")) else if (videoBackend.equals("Vulkan"))
@ -346,8 +337,8 @@ public final class SettingsFragmentPresenter
try try
{ {
boolean usingXFB = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_XFB)).getValue(); boolean usingXFB = ((BooleanSetting) mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_XFB)).getValue();
boolean usingRealXFB = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_XFB_REAL)).getValue(); boolean usingRealXFB = ((BooleanSetting) mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_XFB_REAL)).getValue();
if (!usingXFB) if (!usingXFB)
{ {

View File

@ -19,23 +19,23 @@ public interface SettingsFragmentView
* Called by the containing Activity to notify the Fragment that an * Called by the containing Activity to notify the Fragment that an
* asynchronous load operation completed. * asynchronous load operation completed.
* *
* @param settings The potentially-null result of the load operation. * @param settings The (possibly null) result of the ini load operation.
*/ */
void onSettingsFileLoaded(HashMap<String, SettingSection> settings); void onSettingsFileLoaded(ArrayList<HashMap<String, SettingSection>> settings);
/** /**
* Pass a settings Hashmap to the containing activity, so that it can * Pass a settings HashMap to the containing activity, so that it can
* share the Hashmap with other SettingsFragments; useful so that rotations * share the HashMap with other SettingsFragments; useful so that rotations
* do not require an additional load operation. * do not require an additional load operation.
* *
* @param settings A Hashmap containing all the settings * @param settings An ArrayList containing all the settings HashMaps.
*/ */
void passSettingsToActivity(HashMap<String, SettingSection> settings); void passSettingsToActivity(ArrayList<HashMap<String, SettingSection>> settings);
/** /**
* Pass an ArrayList to the View so that it can be displayed on screen. * Pass an ArrayList to the View so that it can be displayed on screen.
* *
* @param settingsList The result of converting the Hashmap to an ArrayList * @param settingsList The result of converting the HashMap to an ArrayList
*/ */
void showSettingsList(ArrayList<SettingsItem> settingsList); void showSettingsList(ArrayList<SettingsItem> settingsList);
@ -66,7 +66,7 @@ public interface SettingsFragmentView
void showToastMessage(String message); void showToastMessage(String message);
/** /**
* Have the fragment add a setting to the Hashmap. * Have the fragment add a setting to the HashMap.
* *
* @param setting The (possibly previously missing) new setting. * @param setting The (possibly previously missing) new setting.
*/ */

View File

@ -9,6 +9,7 @@ import org.dolphinemu.dolphinemu.model.settings.IntSetting;
import org.dolphinemu.dolphinemu.model.settings.Setting; import org.dolphinemu.dolphinemu.model.settings.Setting;
import org.dolphinemu.dolphinemu.model.settings.SettingSection; import org.dolphinemu.dolphinemu.model.settings.SettingSection;
import org.dolphinemu.dolphinemu.model.settings.StringSetting; import org.dolphinemu.dolphinemu.model.settings.StringSetting;
import org.dolphinemu.dolphinemu.ui.settings.SettingsActivityView;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
@ -20,14 +21,15 @@ import java.io.UnsupportedEncodingException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Set; import java.util.Set;
import rx.Observable;
import rx.Subscriber;
/** /**
* Contains static methods for interacting with .ini files in which settings are stored. * Contains static methods for interacting with .ini files in which settings are stored.
*/ */
public final class SettingsFile public final class SettingsFile
{ {
public static final int SETTINGS_DOLPHIN = 0;
public static final int SETTINGS_GFX = 1;
public static final int SETTINGS_WIIMOTE = 2;
public static final String FILE_NAME_DOLPHIN = "Dolphin"; public static final String FILE_NAME_DOLPHIN = "Dolphin";
public static final String FILE_NAME_GFX = "GFX"; public static final String FILE_NAME_GFX = "GFX";
public static final String FILE_NAME_GCPAD = "GCPadNew"; public static final String FILE_NAME_GCPAD = "GCPadNew";
@ -92,129 +94,112 @@ public final class SettingsFile
} }
/** /**
* Reads a given .ini file from disk and returns it as an Rx Observable. If successful, * Reads a given .ini file from disk and returns it as a HashMap of SettingSections, themselves
* this Observable emits a Hashmap of SettingSections, themselves effectively a Hashmap of * effectively a HashMap of key/value settings. If unsuccessful, outputs an error telling why it
* key/value settings. If unsuccessful, the observer notifies the subscriber of why it failed. * failed.
* *
* @param fileName The name of the settings file without a path or extension. * @param fileName The name of the settings file without a path or extension.
* @return An Observable that emits a Hashmap of the file's contents, then completes. * @param view The current view.
* @return An Observable that emits a HashMap of the file's contents, then completes.
*/ */
public static Observable<HashMap<String, SettingSection>> readFile(final String fileName) public static HashMap<String, SettingSection> readFile(final String fileName, SettingsActivityView view)
{ {
return Observable.create(new Observable.OnSubscribe<HashMap<String, SettingSection>>() HashMap<String, SettingSection> sections = new HashMap<>();
File ini = getSettingsFile(fileName);
BufferedReader reader = null;
try
{ {
@Override reader = new BufferedReader(new FileReader(ini));
public void call(Subscriber<? super HashMap<String, SettingSection>> subscriber)
SettingSection current = null;
for (String line; (line = reader.readLine()) != null; )
{
if (line.startsWith("[") && line.endsWith("]"))
{
current = sectionFromLine(line);
sections.put(current.getName(), current);
}
else if ((current != null) && line.contains("="))
{
Setting setting = settingFromLine(current, line, fileName);
current.putSetting(setting);
}
}
}
catch (FileNotFoundException e)
{
Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.getMessage());
view.onSettingsFileNotFound();
}
catch (IOException e)
{
Log.error("[SettingsFile] Error reading from: " + fileName + ".ini: " + e.getMessage());
view.onSettingsFileNotFound();
}
finally
{
if (reader != null)
{ {
HashMap<String, SettingSection> sections = new HashMap<>();
File ini = getSettingsFile(fileName);
BufferedReader reader = null;
try try
{ {
reader = new BufferedReader(new FileReader(ini)); reader.close();
SettingSection current = null;
for (String line; (line = reader.readLine()) != null; )
{
if (line.startsWith("[") && line.endsWith("]"))
{
current = sectionFromLine(line);
sections.put(current.getName(), current);
}
else if ((current != null) && line.contains("="))
{
Setting setting = settingFromLine(current, line);
current.putSetting(setting.getKey(), setting);
}
}
}
catch (FileNotFoundException e)
{
Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.getMessage());
subscriber.onError(e);
} }
catch (IOException e) catch (IOException e)
{ {
Log.error("[SettingsFile] Error reading from: " + fileName + ".ini: " + e.getMessage()); Log.error("[SettingsFile] Error closing: " + fileName + ".ini: " + e.getMessage());
subscriber.onError(e);
} finally
{
if (reader != null)
{
try
{
reader.close();
}
catch (IOException e)
{
Log.error("[SettingsFile] Error closing: " + fileName + ".ini: " + e.getMessage());
subscriber.onError(e);
}
}
} }
subscriber.onNext(sections);
subscriber.onCompleted();
} }
}); }
return sections;
} }
/** /**
* Saves a Settings Hashmap to a given .ini file on disk, returning the operation * Saves a Settings HashMap to a given .ini file on disk. If unsuccessful, outputs an error
* as an Rx Observable. If successful, this Observable emits an event to notify subscribers; * telling why it failed.
* if unsuccessful, the observer notifies the subscriber of why it failed.
* *
* @param fileName The target filename without a path or extension. * @param fileName The target filename without a path or extension.
* @param sections The hashmap containing the Settings we want to serialize. * @param sections The HashMap containing the Settings we want to serialize.
* @param view The current view.
* @return An Observable representing the operation. * @return An Observable representing the operation.
*/ */
public static Observable<Boolean> saveFile(final String fileName, final HashMap<String, SettingSection> sections) public static void saveFile(final String fileName, final HashMap<String, SettingSection> sections, SettingsActivityView view)
{ {
return Observable.create(new Observable.OnSubscribe<Boolean>() File ini = getSettingsFile(fileName);
PrintWriter writer = null;
try
{ {
@Override writer = new PrintWriter(ini, "UTF-8");
public void call(Subscriber<? super Boolean> subscriber)
Set<String> keySet = sections.keySet();
for (String key : keySet)
{ {
File ini = getSettingsFile(fileName); SettingSection section = sections.get(key);
writeSection(writer, section);
PrintWriter writer = null;
try
{
writer = new PrintWriter(ini, "UTF-8");
Set<String> keySet = sections.keySet();
for (String key : keySet)
{
SettingSection section = sections.get(key);
writeSection(writer, section);
}
}
catch (FileNotFoundException e)
{
Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.getMessage());
subscriber.onError(e);
}
catch (UnsupportedEncodingException e)
{
Log.error("[SettingsFile] Bad encoding; please file a bug report: " + fileName + ".ini: " + e.getMessage());
subscriber.onError(e);
} finally
{
if (writer != null)
{
writer.close();
}
}
subscriber.onNext(true);
subscriber.onCompleted();
} }
}); }
catch (FileNotFoundException e)
{
Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.getMessage());
view.showToastMessage("Error saving " + fileName + ".ini: " + e.getMessage());
}
catch (UnsupportedEncodingException e)
{
Log.error("[SettingsFile] Bad encoding; please file a bug report: " + fileName + ".ini: " + e.getMessage());
view.showToastMessage("Error saving " + fileName + ".ini: " + e.getMessage());
}
finally
{
if (writer != null)
{
writer.close();
}
}
} }
@NonNull @NonNull
@ -234,22 +219,37 @@ public final class SettingsFile
* For a line of text, determines what type of data is being represented, and returns * For a line of text, determines what type of data is being represented, and returns
* a Setting object containing this data. * a Setting object containing this data.
* *
* @param current The section currently being parsed by the consuming method. * @param current The section currently being parsed by the consuming method.
* @param line The line of text being parsed. * @param line The line of text being parsed.
* @param fileName The name of the ini file the setting is in.
* @return A typed Setting containing the key/value contained in the line. * @return A typed Setting containing the key/value contained in the line.
*/ */
private static Setting settingFromLine(SettingSection current, String line) private static Setting settingFromLine(SettingSection current, String line, String fileName)
{ {
String[] splitLine = line.split("="); String[] splitLine = line.split("=");
String key = splitLine[0].trim(); String key = splitLine[0].trim();
String value = splitLine[1].trim(); String value = splitLine[1].trim();
int file;
switch (fileName)
{
case FILE_NAME_GFX:
file = SETTINGS_GFX;
break;
case FILE_NAME_WIIMOTE:
file = SETTINGS_WIIMOTE;
break;
default:
file = SETTINGS_DOLPHIN;
break;
}
try try
{ {
int valueAsInt = Integer.valueOf(value); int valueAsInt = Integer.valueOf(value);
return new IntSetting(key, current.getName(), valueAsInt); return new IntSetting(key, current.getName(), file, valueAsInt);
} }
catch (NumberFormatException ex) catch (NumberFormatException ex)
{ {
@ -259,7 +259,7 @@ public final class SettingsFile
{ {
float valueAsFloat = Float.valueOf(value); float valueAsFloat = Float.valueOf(value);
return new FloatSetting(key, current.getName(), valueAsFloat); return new FloatSetting(key, current.getName(), file, valueAsFloat);
} }
catch (NumberFormatException ex) catch (NumberFormatException ex)
{ {
@ -268,16 +268,16 @@ public final class SettingsFile
switch (value) switch (value)
{ {
case "True": case "True":
return new BooleanSetting(key, current.getName(), true); return new BooleanSetting(key, current.getName(), file, true);
case "False": case "False":
return new BooleanSetting(key, current.getName(), false); return new BooleanSetting(key, current.getName(), file, false);
default: default:
return new StringSetting(key, current.getName(), value); return new StringSetting(key, current.getName(), file, value);
} }
} }
/** /**
* Writes the contents of a Section hashmap to disk. * Writes the contents of a Section HashMap to disk.
* *
* @param writer A PrintWriter pointed at a file on disk. * @param writer A PrintWriter pointed at a file on disk.
* @param section A section containing settings to be written to the file. * @param section A section containing settings to be written to the file.