Merge pull request #11662 from t895/kotlin-settings
Android: Convert Settings to Kotlin
This commit is contained in:
commit
002a96adb0
|
@ -160,7 +160,7 @@ class CheatsActivity : AppCompatActivity(), PanelSlideListener {
|
||||||
|
|
||||||
fun loadGameSpecificSettings(): Settings {
|
fun loadGameSpecificSettings(): Settings {
|
||||||
val settings = Settings()
|
val settings = Settings()
|
||||||
settings.loadSettings(gameId, revision, isWii)
|
settings.loadSettings(gameId!!, revision, isWii)
|
||||||
return settings
|
return settings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ abstract class SettingDisabledWarningFragment(
|
||||||
super.onResume()
|
super.onResume()
|
||||||
val activity = requireActivity() as CheatsActivity
|
val activity = requireActivity() as CheatsActivity
|
||||||
activity.loadGameSpecificSettings().use {
|
activity.loadGameSpecificSettings().use {
|
||||||
val cheatsEnabled = setting.getBoolean()
|
val cheatsEnabled = setting.boolean
|
||||||
requireView().visibility = if (cheatsEnabled) View.GONE else View.VISIBLE
|
requireView().visibility = if (cheatsEnabled) View.GONE else View.VISIBLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,8 +46,8 @@ public class InputDeviceSetting extends StringSingleChoiceSetting
|
||||||
{
|
{
|
||||||
String[] devices = ControllerInterface.getAllDeviceStrings();
|
String[] devices = ControllerInterface.getAllDeviceStrings();
|
||||||
|
|
||||||
mChoices = devices;
|
setChoices(devices);
|
||||||
mValues = devices;
|
setValues(devices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.input.ui
|
package org.dolphinemu.dolphinemu.features.input.ui
|
||||||
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -14,6 +13,7 @@ import com.google.android.material.divider.MaterialDividerItemDecoration
|
||||||
import org.dolphinemu.dolphinemu.R
|
import org.dolphinemu.dolphinemu.R
|
||||||
import org.dolphinemu.dolphinemu.databinding.DialogInputProfilesBinding
|
import org.dolphinemu.dolphinemu.databinding.DialogInputProfilesBinding
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag
|
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag
|
||||||
|
import org.dolphinemu.dolphinemu.utils.SerializableHelper.serializable
|
||||||
|
|
||||||
class ProfileDialog : BottomSheetDialogFragment() {
|
class ProfileDialog : BottomSheetDialogFragment() {
|
||||||
private var presenter: ProfileDialogPresenter? = null
|
private var presenter: ProfileDialogPresenter? = null
|
||||||
|
@ -22,11 +22,7 @@ class ProfileDialog : BottomSheetDialogFragment() {
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
val menuTag: MenuTag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
val menuTag = requireArguments().serializable<MenuTag>(KEY_MENU_TAG)
|
||||||
requireArguments().getSerializable(KEY_MENU_TAG, MenuTag::class.java) as MenuTag
|
|
||||||
} else {
|
|
||||||
requireArguments().getSerializable(KEY_MENU_TAG) as MenuTag
|
|
||||||
}
|
|
||||||
|
|
||||||
presenter = ProfileDialogPresenter(this, menuTag)
|
presenter = ProfileDialogPresenter(this, menuTag)
|
||||||
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public interface AbstractBooleanSetting extends AbstractSetting
|
|
||||||
{
|
|
||||||
boolean getBoolean();
|
|
||||||
|
|
||||||
void setBoolean(@NonNull Settings settings, boolean newValue);
|
|
||||||
}
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
interface AbstractBooleanSetting : AbstractSetting {
|
||||||
|
val boolean: Boolean
|
||||||
|
|
||||||
|
fun setBoolean(settings: Settings, newValue: Boolean)
|
||||||
|
}
|
|
@ -1,12 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public interface AbstractFloatSetting extends AbstractSetting
|
|
||||||
{
|
|
||||||
float getFloat();
|
|
||||||
|
|
||||||
void setFloat(@NonNull Settings settings, float newValue);
|
|
||||||
}
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
interface AbstractFloatSetting : AbstractSetting {
|
||||||
|
val float: Float
|
||||||
|
|
||||||
|
fun setFloat(settings: Settings, newValue: Float)
|
||||||
|
}
|
|
@ -1,12 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public interface AbstractIntSetting extends AbstractSetting
|
|
||||||
{
|
|
||||||
int getInt();
|
|
||||||
|
|
||||||
void setInt(@NonNull Settings settings, int newValue);
|
|
||||||
}
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
interface AbstractIntSetting : AbstractSetting {
|
||||||
|
val int: Int
|
||||||
|
|
||||||
|
fun setInt(settings: Settings, newValue: Int)
|
||||||
|
}
|
|
@ -1,14 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public interface AbstractSetting
|
|
||||||
{
|
|
||||||
boolean isOverridden();
|
|
||||||
|
|
||||||
boolean isRuntimeEditable();
|
|
||||||
|
|
||||||
boolean delete(@NonNull Settings settings);
|
|
||||||
}
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
interface AbstractSetting {
|
||||||
|
val isOverridden: Boolean
|
||||||
|
val isRuntimeEditable: Boolean
|
||||||
|
|
||||||
|
fun delete(settings: Settings): Boolean
|
||||||
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public interface AbstractStringSetting extends AbstractSetting
|
|
||||||
{
|
|
||||||
@NonNull
|
|
||||||
String getString();
|
|
||||||
|
|
||||||
void setString(@NonNull Settings settings, @NonNull String newValue);
|
|
||||||
}
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
interface AbstractStringSetting : AbstractSetting {
|
||||||
|
val string: String
|
||||||
|
|
||||||
|
fun setString(settings: Settings, newValue: String)
|
||||||
|
}
|
|
@ -1,62 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public class AdHocBooleanSetting implements AbstractBooleanSetting
|
|
||||||
{
|
|
||||||
private final String mFile;
|
|
||||||
private final String mSection;
|
|
||||||
private final String mKey;
|
|
||||||
private final boolean mDefaultValue;
|
|
||||||
|
|
||||||
public AdHocBooleanSetting(String file, String section, String key, boolean defaultValue)
|
|
||||||
{
|
|
||||||
mFile = file;
|
|
||||||
mSection = section;
|
|
||||||
mKey = key;
|
|
||||||
mDefaultValue = defaultValue;
|
|
||||||
|
|
||||||
if (!NativeConfig.isSettingSaveable(file, section, key))
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("File/section/key is unknown or legacy");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOverridden()
|
|
||||||
{
|
|
||||||
return NativeConfig.isOverridden(mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRuntimeEditable()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean delete(@NonNull Settings settings)
|
|
||||||
{
|
|
||||||
return NativeConfig.deleteKey(settings.getWriteLayer(), mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean getBoolean()
|
|
||||||
{
|
|
||||||
return NativeConfig.getBoolean(NativeConfig.LAYER_ACTIVE, mFile, mSection, mKey, mDefaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBoolean(@NonNull Settings settings, boolean newValue)
|
|
||||||
{
|
|
||||||
NativeConfig.setBoolean(settings.getWriteLayer(), mFile, mSection, mKey, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean getBooleanGlobal(String file, String section, String key,
|
|
||||||
boolean defaultValue)
|
|
||||||
{
|
|
||||||
return NativeConfig.getBoolean(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
class AdHocBooleanSetting(
|
||||||
|
private val file: String,
|
||||||
|
private val section: String,
|
||||||
|
private val key: String,
|
||||||
|
private val defaultValue: Boolean
|
||||||
|
) : AbstractBooleanSetting {
|
||||||
|
init {
|
||||||
|
require(
|
||||||
|
NativeConfig.isSettingSaveable(
|
||||||
|
file,
|
||||||
|
section,
|
||||||
|
key
|
||||||
|
)
|
||||||
|
) { "File/section/key is unknown or legacy" }
|
||||||
|
}
|
||||||
|
|
||||||
|
override val isOverridden: Boolean
|
||||||
|
get() = NativeConfig.isOverridden(file, section, key)
|
||||||
|
|
||||||
|
override val isRuntimeEditable: Boolean = true
|
||||||
|
|
||||||
|
override fun delete(settings: Settings): Boolean {
|
||||||
|
return NativeConfig.deleteKey(settings.writeLayer, file, section, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val boolean: Boolean
|
||||||
|
get() = NativeConfig.getBoolean(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue)
|
||||||
|
|
||||||
|
override fun setBoolean(settings: Settings, newValue: Boolean) {
|
||||||
|
NativeConfig.setBoolean(settings.writeLayer, file, section, key, newValue)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,61 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public class AdHocStringSetting implements AbstractStringSetting
|
|
||||||
{
|
|
||||||
private final String mFile;
|
|
||||||
private final String mSection;
|
|
||||||
private final String mKey;
|
|
||||||
private final String mDefaultValue;
|
|
||||||
|
|
||||||
public AdHocStringSetting(String file, String section, String key, String defaultValue)
|
|
||||||
{
|
|
||||||
mFile = file;
|
|
||||||
mSection = section;
|
|
||||||
mKey = key;
|
|
||||||
mDefaultValue = defaultValue;
|
|
||||||
|
|
||||||
if (!NativeConfig.isSettingSaveable(file, section, key))
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("File/section/key is unknown or legacy");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOverridden()
|
|
||||||
{
|
|
||||||
return NativeConfig.isOverridden(mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRuntimeEditable()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean delete(@NonNull Settings settings)
|
|
||||||
{
|
|
||||||
return NativeConfig.deleteKey(settings.getWriteLayer(), mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public String getString()
|
|
||||||
{
|
|
||||||
return NativeConfig.getString(NativeConfig.LAYER_ACTIVE, mFile, mSection, mKey, mDefaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setString(@NonNull Settings settings, @NonNull String newValue)
|
|
||||||
{
|
|
||||||
NativeConfig.setString(settings.getWriteLayer(), mFile, mSection, mKey, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getStringGlobal(String file, String section, String key, String defaultValue)
|
|
||||||
{
|
|
||||||
return NativeConfig.getString(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
class AdHocStringSetting(
|
||||||
|
private val file: String,
|
||||||
|
private val section: String,
|
||||||
|
private val key: String,
|
||||||
|
private val defaultValue: String
|
||||||
|
) : AbstractStringSetting {
|
||||||
|
init {
|
||||||
|
require(
|
||||||
|
NativeConfig.isSettingSaveable(
|
||||||
|
file,
|
||||||
|
section,
|
||||||
|
key
|
||||||
|
)
|
||||||
|
) { "File/section/key is unknown or legacy" }
|
||||||
|
}
|
||||||
|
|
||||||
|
override val isOverridden: Boolean
|
||||||
|
get() = NativeConfig.isOverridden(file, section, key)
|
||||||
|
|
||||||
|
override val isRuntimeEditable: Boolean = true
|
||||||
|
|
||||||
|
override fun delete(settings: Settings): Boolean {
|
||||||
|
return NativeConfig.deleteKey(settings.writeLayer, file, section, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val string: String
|
||||||
|
get() = NativeConfig.getString(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue)
|
||||||
|
|
||||||
|
override fun setString(settings: Settings, newValue: String) {
|
||||||
|
NativeConfig.setString(settings.writeLayer, file, section, key, newValue)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,371 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public enum BooleanSetting implements AbstractBooleanSetting
|
|
||||||
{
|
|
||||||
// These entries have the same names and order as in C++, just for consistency.
|
|
||||||
|
|
||||||
MAIN_SKIP_IPL(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SkipIPL", true),
|
|
||||||
MAIN_DSP_HLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "DSPHLE", true),
|
|
||||||
MAIN_FASTMEM(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Fastmem", true),
|
|
||||||
MAIN_CPU_THREAD(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "CPUThread", true),
|
|
||||||
MAIN_SYNC_ON_SKIP_IDLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SyncOnSkipIdle", true),
|
|
||||||
MAIN_ENABLE_CHEATS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EnableCheats", false),
|
|
||||||
MAIN_OVERRIDE_REGION_SETTINGS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE,
|
|
||||||
"OverrideRegionSettings", false),
|
|
||||||
MAIN_AUDIO_STRETCH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AudioStretch", false),
|
|
||||||
MAIN_BBA_XLINK_CHAT_OSD(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_XLINK_CHAT_OSD",
|
|
||||||
false),
|
|
||||||
MAIN_ADAPTER_RUMBLE_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble0", true),
|
|
||||||
MAIN_ADAPTER_RUMBLE_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble1", true),
|
|
||||||
MAIN_ADAPTER_RUMBLE_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble2", true),
|
|
||||||
MAIN_ADAPTER_RUMBLE_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble3", true),
|
|
||||||
MAIN_SIMULATE_KONGA_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SimulateKonga0", false),
|
|
||||||
MAIN_SIMULATE_KONGA_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SimulateKonga1", false),
|
|
||||||
MAIN_SIMULATE_KONGA_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SimulateKonga2", false),
|
|
||||||
MAIN_SIMULATE_KONGA_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SimulateKonga3", false),
|
|
||||||
MAIN_WII_SD_CARD(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "WiiSDCard", true),
|
|
||||||
MAIN_WII_SD_CARD_ENABLE_FOLDER_SYNC(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE,
|
|
||||||
"WiiSDCardEnableFolderSync", false),
|
|
||||||
MAIN_WIIMOTE_CONTINUOUS_SCANNING(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE,
|
|
||||||
"WiimoteContinuousScanning", false),
|
|
||||||
MAIN_WIIMOTE_ENABLE_SPEAKER(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE,
|
|
||||||
"WiimoteEnableSpeaker", false),
|
|
||||||
MAIN_MMU(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "MMU", false),
|
|
||||||
MAIN_PAUSE_ON_PANIC(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "PauseOnPanic", false),
|
|
||||||
MAIN_ACCURATE_CPU_CACHE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AccurateCPUCache",
|
|
||||||
false),
|
|
||||||
MAIN_SYNC_GPU(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SyncGPU", false),
|
|
||||||
MAIN_FAST_DISC_SPEED(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "FastDiscSpeed",
|
|
||||||
false),
|
|
||||||
MAIN_OVERCLOCK_ENABLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "OverclockEnable", false),
|
|
||||||
MAIN_RAM_OVERRIDE_ENABLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "RAMOverrideEnable",
|
|
||||||
false),
|
|
||||||
MAIN_CUSTOM_RTC_ENABLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EnableCustomRTC",
|
|
||||||
false),
|
|
||||||
MAIN_AUTO_DISC_CHANGE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AutoDiscChange", false),
|
|
||||||
MAIN_ALLOW_SD_WRITES(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "WiiSDCardAllowWrites",
|
|
||||||
true),
|
|
||||||
MAIN_ENABLE_SAVESTATES(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EnableSaveStates",
|
|
||||||
false),
|
|
||||||
|
|
||||||
MAIN_DSP_JIT(Settings.FILE_DOLPHIN, Settings.SECTION_INI_DSP, "EnableJIT", true),
|
|
||||||
|
|
||||||
MAIN_EXPAND_TO_CUTOUT_AREA(Settings.FILE_DOLPHIN, Settings.SECTION_INI_INTERFACE,
|
|
||||||
"ExpandToCutoutArea", false),
|
|
||||||
MAIN_USE_PANIC_HANDLERS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_INTERFACE,
|
|
||||||
"UsePanicHandlers", true),
|
|
||||||
MAIN_OSD_MESSAGES(Settings.FILE_DOLPHIN, Settings.SECTION_INI_INTERFACE,
|
|
||||||
"OnScreenDisplayMessages", true),
|
|
||||||
|
|
||||||
MAIN_ANALYTICS_ENABLED(Settings.FILE_DOLPHIN, Settings.SECTION_ANALYTICS, "Enabled", false),
|
|
||||||
MAIN_ANALYTICS_PERMISSION_ASKED(Settings.FILE_DOLPHIN, Settings.SECTION_ANALYTICS,
|
|
||||||
"PermissionAsked", false),
|
|
||||||
|
|
||||||
MAIN_RECURSIVE_ISO_PATHS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL,
|
|
||||||
"RecursiveISOPaths", false),
|
|
||||||
MAIN_USE_GAME_COVERS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL,
|
|
||||||
"UseGameCovers", true),
|
|
||||||
|
|
||||||
MAIN_DEBUG_JIT_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitOff", false),
|
|
||||||
MAIN_DEBUG_JIT_LOAD_STORE_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitLoadStoreOff",
|
|
||||||
false),
|
|
||||||
MAIN_DEBUG_JIT_LOAD_STORE_FLOATING_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG,
|
|
||||||
"JitLoadStoreFloatingOff", false),
|
|
||||||
MAIN_DEBUG_JIT_LOAD_STORE_PAIRED_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG,
|
|
||||||
"JitLoadStorePairedOff", false),
|
|
||||||
MAIN_DEBUG_JIT_FLOATING_POINT_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG,
|
|
||||||
"JitFloatingPointOff", false),
|
|
||||||
MAIN_DEBUG_JIT_INTEGER_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitIntegerOff", false),
|
|
||||||
MAIN_DEBUG_JIT_PAIRED_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitPairedOff", false),
|
|
||||||
MAIN_DEBUG_JIT_SYSTEM_REGISTERS_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG,
|
|
||||||
"JitSystemRegistersOff", false),
|
|
||||||
MAIN_DEBUG_JIT_BRANCH_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitBranchOff", false),
|
|
||||||
MAIN_DEBUG_JIT_REGISTER_CACHE_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG,
|
|
||||||
"JitRegisterCacheOff", false),
|
|
||||||
|
|
||||||
MAIN_EMULATE_SKYLANDER_PORTAL(Settings.FILE_DOLPHIN, Settings.SECTION_EMULATED_USB_DEVICES,
|
|
||||||
"EmulateSkylanderPortal", false),
|
|
||||||
|
|
||||||
MAIN_SHOW_GAME_TITLES(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
|
|
||||||
"ShowGameTitles", true),
|
|
||||||
MAIN_USE_BLACK_BACKGROUNDS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
|
|
||||||
"UseBlackBackgrounds", false),
|
|
||||||
MAIN_JOYSTICK_REL_CENTER(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
|
|
||||||
"JoystickRelCenter", true),
|
|
||||||
MAIN_SHOW_INPUT_OVERLAY(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
|
|
||||||
"ShowInputOverlay", true),
|
|
||||||
MAIN_IR_ALWAYS_RECENTER(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
|
|
||||||
"IRAlwaysRecenter", false),
|
|
||||||
|
|
||||||
MAIN_BUTTON_TOGGLE_GC_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleGCButtonA", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_GC_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleGCButtonB", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_GC_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleGCButtonX", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_GC_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleGCButtonY", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_GC_4(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleGCButtonZ", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_GC_5(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleGCButtonStart", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_GC_6(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleGCTriggerL", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_GC_7(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleGCTriggerR", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_GC_8(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleGCDPad", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_GC_9(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleGCStickMain", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_GC_10(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleGCStickC", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicButtonA", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicButtonB", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicButtonX", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicButtonY", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_4(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicButtonPlus", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_5(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicButtonMinus", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_6(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicButtonHome", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_7(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicTriggerL", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_8(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicTriggerR", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_9(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicButtonZL", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_10(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicButtonZR", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_11(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicDPad", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_12(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicStickLeft", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_CLASSIC_13(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleClassicStickRight", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_WII_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleWiimoteButtonA", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_WII_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleWiimoteButtonB", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_WII_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleWiimoteButton1", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_WII_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleWiimoteButton2", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_WII_4(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleWiimoteButtonPlus", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_WII_5(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleWiimoteButtonMinus", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_WII_6(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleWiimoteButtonHome", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_WII_7(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleWiimoteDPad", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_WII_8(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleNunchukC", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_WII_9(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleNunchukZ", true),
|
|
||||||
MAIN_BUTTON_TOGGLE_WII_10(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"ButtonToggleNunchukStick", true),
|
|
||||||
|
|
||||||
SYSCONF_SCREENSAVER(Settings.FILE_SYSCONF, "IPL", "SSV", false),
|
|
||||||
SYSCONF_WIDESCREEN(Settings.FILE_SYSCONF, "IPL", "AR", true),
|
|
||||||
SYSCONF_PROGRESSIVE_SCAN(Settings.FILE_SYSCONF, "IPL", "PGS", true),
|
|
||||||
SYSCONF_PAL60(Settings.FILE_SYSCONF, "IPL", "E60", true),
|
|
||||||
|
|
||||||
SYSCONF_WIIMOTE_MOTOR(Settings.FILE_SYSCONF, "BT", "MOT", true),
|
|
||||||
|
|
||||||
GFX_WIDESCREEN_HACK(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "wideScreenHack", false),
|
|
||||||
GFX_CROP(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "Crop", false),
|
|
||||||
GFX_SHOW_FPS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowFPS", false),
|
|
||||||
GFX_SHOW_FTIMES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowFTimes", false),
|
|
||||||
GFX_SHOW_VPS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowVPS", false),
|
|
||||||
GFX_SHOW_VTIMES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowVTimes", false),
|
|
||||||
GFX_SHOW_GRAPHS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowGraphs", false),
|
|
||||||
GFX_SHOW_SPEED(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowSpeed", false),
|
|
||||||
GFX_SHOW_SPEED_COLORS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowSpeedColors", true),
|
|
||||||
GFX_LOG_RENDER_TIME_TO_FILE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
|
|
||||||
"LogRenderTimeToFile", false),
|
|
||||||
GFX_OVERLAY_STATS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "OverlayStats", false),
|
|
||||||
GFX_DUMP_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpTextures", false),
|
|
||||||
GFX_DUMP_MIP_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpMipTextures", false),
|
|
||||||
GFX_DUMP_BASE_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpBaseTextures",
|
|
||||||
false),
|
|
||||||
GFX_HIRES_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "HiresTextures", false),
|
|
||||||
GFX_CACHE_HIRES_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "CacheHiresTextures",
|
|
||||||
false),
|
|
||||||
GFX_DUMP_EFB_TARGET(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpEFBTarget", false),
|
|
||||||
GFX_DUMP_XFB_TARGET(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpXFBTarget", false),
|
|
||||||
GFX_INTERNAL_RESOLUTION_FRAME_DUMPS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
|
|
||||||
"InternalResolutionFrameDumps", false),
|
|
||||||
GFX_ENABLE_GPU_TEXTURE_DECODING(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
|
|
||||||
"EnableGPUTextureDecoding", false),
|
|
||||||
GFX_ENABLE_PIXEL_LIGHTING(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
|
|
||||||
"EnablePixelLighting", false),
|
|
||||||
GFX_FAST_DEPTH_CALC(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "FastDepthCalc", true),
|
|
||||||
GFX_TEXFMT_OVERLAY_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "TexFmtOverlayEnable",
|
|
||||||
false),
|
|
||||||
GFX_ENABLE_WIREFRAME(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "WireFrame", false),
|
|
||||||
GFX_DISABLE_FOG(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DisableFog", false),
|
|
||||||
GFX_ENABLE_VALIDATION_LAYER(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
|
|
||||||
"EnableValidationLayer", false),
|
|
||||||
GFX_BACKEND_MULTITHREADING(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
|
|
||||||
"BackendMultithreading", true),
|
|
||||||
GFX_WAIT_FOR_SHADERS_BEFORE_STARTING(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
|
|
||||||
"WaitForShadersBeforeStarting", false),
|
|
||||||
GFX_SAVE_TEXTURE_CACHE_TO_STATE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
|
|
||||||
"SaveTextureCacheToState", true),
|
|
||||||
GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
|
|
||||||
"PreferVSForLinePointExpansion", false),
|
|
||||||
GFX_CPU_CULL(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "CPUCull", false),
|
|
||||||
GFX_MODS_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "EnableMods", false),
|
|
||||||
|
|
||||||
GFX_ENHANCE_FORCE_TRUE_COLOR(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS,
|
|
||||||
"ForceTrueColor", true),
|
|
||||||
GFX_ENHANCE_DISABLE_COPY_FILTER(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS,
|
|
||||||
"DisableCopyFilter", true),
|
|
||||||
GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS,
|
|
||||||
"ArbitraryMipmapDetection", true),
|
|
||||||
|
|
||||||
GFX_STEREO_SWAP_EYES(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoSwapEyes", false),
|
|
||||||
|
|
||||||
GFX_HACK_EFB_ACCESS_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "EFBAccessEnable",
|
|
||||||
true),
|
|
||||||
GFX_HACK_EFB_DEFER_INVALIDATION(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS,
|
|
||||||
"EFBAccessDeferInvalidation", false),
|
|
||||||
GFX_HACK_BBOX_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "BBoxEnable", false),
|
|
||||||
GFX_HACK_SKIP_EFB_COPY_TO_RAM(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS,
|
|
||||||
"EFBToTextureEnable", true),
|
|
||||||
GFX_HACK_SKIP_XFB_COPY_TO_RAM(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS,
|
|
||||||
"XFBToTextureEnable", true),
|
|
||||||
GFX_HACK_DISABLE_COPY_TO_VRAM(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "DisableCopyToVRAM",
|
|
||||||
false),
|
|
||||||
GFX_HACK_DEFER_EFB_COPIES(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "DeferEFBCopies", true),
|
|
||||||
GFX_HACK_IMMEDIATE_XFB(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "ImmediateXFBEnable",
|
|
||||||
false),
|
|
||||||
GFX_HACK_SKIP_DUPLICATE_XFBS(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "SkipDuplicateXFBs",
|
|
||||||
true),
|
|
||||||
GFX_HACK_COPY_EFB_SCALED(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "EFBScaledCopy", true),
|
|
||||||
GFX_HACK_EFB_EMULATE_FORMAT_CHANGES(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS,
|
|
||||||
"EFBEmulateFormatChanges", false),
|
|
||||||
GFX_HACK_VERTEX_ROUNDING(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "VertexRounding", false),
|
|
||||||
GFX_HACK_VI_SKIP(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "VISkip", false),
|
|
||||||
GFX_HACK_FAST_TEXTURE_SAMPLING(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS,
|
|
||||||
"FastTextureSampling", true),
|
|
||||||
|
|
||||||
LOGGER_WRITE_TO_FILE(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_OPTIONS, "WriteToFile", false);
|
|
||||||
|
|
||||||
private static final BooleanSetting[] NOT_RUNTIME_EDITABLE_ARRAY = new BooleanSetting[]{
|
|
||||||
MAIN_DSP_HLE,
|
|
||||||
MAIN_CPU_THREAD,
|
|
||||||
MAIN_ENABLE_CHEATS,
|
|
||||||
MAIN_OVERRIDE_REGION_SETTINGS,
|
|
||||||
MAIN_MMU,
|
|
||||||
MAIN_PAUSE_ON_PANIC,
|
|
||||||
MAIN_ACCURATE_CPU_CACHE,
|
|
||||||
MAIN_RAM_OVERRIDE_ENABLE,
|
|
||||||
MAIN_CUSTOM_RTC_ENABLE,
|
|
||||||
MAIN_DSP_JIT,
|
|
||||||
MAIN_EMULATE_SKYLANDER_PORTAL,
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final Set<BooleanSetting> NOT_RUNTIME_EDITABLE =
|
|
||||||
new HashSet<>(Arrays.asList(NOT_RUNTIME_EDITABLE_ARRAY));
|
|
||||||
|
|
||||||
private final String mFile;
|
|
||||||
private final String mSection;
|
|
||||||
private final String mKey;
|
|
||||||
private final boolean mDefaultValue;
|
|
||||||
|
|
||||||
BooleanSetting(String file, String section, String key, boolean defaultValue)
|
|
||||||
{
|
|
||||||
mFile = file;
|
|
||||||
mSection = section;
|
|
||||||
mKey = key;
|
|
||||||
mDefaultValue = defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOverridden()
|
|
||||||
{
|
|
||||||
return NativeConfig.isOverridden(mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRuntimeEditable()
|
|
||||||
{
|
|
||||||
if (mFile.equals(Settings.FILE_SYSCONF))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (BooleanSetting setting : NOT_RUNTIME_EDITABLE)
|
|
||||||
{
|
|
||||||
if (setting == this)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NativeConfig.isSettingSaveable(mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean delete(@NonNull Settings settings)
|
|
||||||
{
|
|
||||||
if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NativeConfig.deleteKey(settings.getWriteLayer(), mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean getBoolean()
|
|
||||||
{
|
|
||||||
return NativeConfig.getBoolean(NativeConfig.LAYER_ACTIVE, mFile, mSection, mKey, mDefaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBoolean(@NonNull Settings settings, boolean newValue)
|
|
||||||
{
|
|
||||||
if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeConfig.setBoolean(settings.getWriteLayer(), mFile, mSection, mKey, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBoolean(int layer, boolean newValue)
|
|
||||||
{
|
|
||||||
if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeConfig.setBoolean(layer, mFile, mSection, mKey, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BooleanSetting getSettingForAdapterRumble(int channel)
|
|
||||||
{
|
|
||||||
return new BooleanSetting[]{MAIN_ADAPTER_RUMBLE_0, MAIN_ADAPTER_RUMBLE_1, MAIN_ADAPTER_RUMBLE_2,
|
|
||||||
MAIN_ADAPTER_RUMBLE_3}[channel];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BooleanSetting getSettingForSimulateKonga(int channel)
|
|
||||||
{
|
|
||||||
return new BooleanSetting[]{MAIN_SIMULATE_KONGA_0, MAIN_SIMULATE_KONGA_1, MAIN_SIMULATE_KONGA_2,
|
|
||||||
MAIN_SIMULATE_KONGA_3}[channel];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,747 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
enum class BooleanSetting(
|
||||||
|
private val file: String,
|
||||||
|
private val section: String,
|
||||||
|
private val key: String,
|
||||||
|
private val defaultValue: Boolean
|
||||||
|
) : AbstractBooleanSetting {
|
||||||
|
// These entries have the same names and order as in C++, just for consistency.
|
||||||
|
MAIN_SKIP_IPL(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SkipIPL", true),
|
||||||
|
MAIN_DSP_HLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "DSPHLE", true),
|
||||||
|
MAIN_FASTMEM(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Fastmem", true),
|
||||||
|
MAIN_CPU_THREAD(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "CPUThread", true),
|
||||||
|
MAIN_SYNC_ON_SKIP_IDLE(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"SyncOnSkipIdle",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_ENABLE_CHEATS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EnableCheats", false),
|
||||||
|
MAIN_OVERRIDE_REGION_SETTINGS(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"OverrideRegionSettings",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_AUDIO_STRETCH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AudioStretch", false),
|
||||||
|
MAIN_BBA_XLINK_CHAT_OSD(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"BBA_XLINK_CHAT_OSD",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_ADAPTER_RUMBLE_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble0", true),
|
||||||
|
MAIN_ADAPTER_RUMBLE_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble1", true),
|
||||||
|
MAIN_ADAPTER_RUMBLE_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble2", true),
|
||||||
|
MAIN_ADAPTER_RUMBLE_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble3", true),
|
||||||
|
MAIN_SIMULATE_KONGA_0(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"SimulateKonga0",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_SIMULATE_KONGA_1(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"SimulateKonga1",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_SIMULATE_KONGA_2(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"SimulateKonga2",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_SIMULATE_KONGA_3(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"SimulateKonga3",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_WII_SD_CARD(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "WiiSDCard", true),
|
||||||
|
MAIN_WII_SD_CARD_ENABLE_FOLDER_SYNC(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"WiiSDCardEnableFolderSync",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_WIIMOTE_CONTINUOUS_SCANNING(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"WiimoteContinuousScanning",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_WIIMOTE_ENABLE_SPEAKER(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"WiimoteEnableSpeaker",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_MMU(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "MMU", false),
|
||||||
|
MAIN_PAUSE_ON_PANIC(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "PauseOnPanic", false),
|
||||||
|
MAIN_ACCURATE_CPU_CACHE(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"AccurateCPUCache",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_SYNC_GPU(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SyncGPU", false),
|
||||||
|
MAIN_FAST_DISC_SPEED(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "FastDiscSpeed", false),
|
||||||
|
MAIN_OVERCLOCK_ENABLE(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"OverclockEnable",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_RAM_OVERRIDE_ENABLE(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"RAMOverrideEnable",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_CUSTOM_RTC_ENABLE(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"EnableCustomRTC",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_AUTO_DISC_CHANGE(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"AutoDiscChange",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_ALLOW_SD_WRITES(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"WiiSDCardAllowWrites",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_ENABLE_SAVESTATES(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"EnableSaveStates",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_DSP_JIT(Settings.FILE_DOLPHIN, Settings.SECTION_INI_DSP, "EnableJIT", true),
|
||||||
|
MAIN_EXPAND_TO_CUTOUT_AREA(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_INTERFACE,
|
||||||
|
"ExpandToCutoutArea",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_USE_PANIC_HANDLERS(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_INTERFACE,
|
||||||
|
"UsePanicHandlers",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_OSD_MESSAGES(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_INTERFACE,
|
||||||
|
"OnScreenDisplayMessages",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_ANALYTICS_ENABLED(Settings.FILE_DOLPHIN, Settings.SECTION_ANALYTICS, "Enabled", false),
|
||||||
|
MAIN_ANALYTICS_PERMISSION_ASKED(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_ANALYTICS,
|
||||||
|
"PermissionAsked",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_RECURSIVE_ISO_PATHS(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_GENERAL,
|
||||||
|
"RecursiveISOPaths",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_USE_GAME_COVERS(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_GENERAL,
|
||||||
|
"UseGameCovers",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_DEBUG_JIT_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitOff", false),
|
||||||
|
MAIN_DEBUG_JIT_LOAD_STORE_OFF(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_DEBUG,
|
||||||
|
"JitLoadStoreOff",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_DEBUG_JIT_LOAD_STORE_FLOATING_OFF(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_DEBUG,
|
||||||
|
"JitLoadStoreFloatingOff",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_DEBUG_JIT_LOAD_STORE_PAIRED_OFF(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_DEBUG,
|
||||||
|
"JitLoadStorePairedOff",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_DEBUG_JIT_FLOATING_POINT_OFF(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_DEBUG,
|
||||||
|
"JitFloatingPointOff",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_DEBUG_JIT_INTEGER_OFF(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_DEBUG,
|
||||||
|
"JitIntegerOff",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_DEBUG_JIT_PAIRED_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitPairedOff", false),
|
||||||
|
MAIN_DEBUG_JIT_SYSTEM_REGISTERS_OFF(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_DEBUG,
|
||||||
|
"JitSystemRegistersOff",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_DEBUG_JIT_BRANCH_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitBranchOff", false),
|
||||||
|
MAIN_DEBUG_JIT_REGISTER_CACHE_OFF(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_DEBUG,
|
||||||
|
"JitRegisterCacheOff",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_EMULATE_SKYLANDER_PORTAL(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_EMULATED_USB_DEVICES,
|
||||||
|
"EmulateSkylanderPortal",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_SHOW_GAME_TITLES(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID,
|
||||||
|
"ShowGameTitles",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_USE_BLACK_BACKGROUNDS(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID,
|
||||||
|
"UseBlackBackgrounds",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_JOYSTICK_REL_CENTER(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID,
|
||||||
|
"JoystickRelCenter",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_SHOW_INPUT_OVERLAY(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID,
|
||||||
|
"ShowInputOverlay",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_IR_ALWAYS_RECENTER(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID,
|
||||||
|
"IRAlwaysRecenter",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_GC_0(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleGCButtonA",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_GC_1(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleGCButtonB",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_GC_2(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleGCButtonX",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_GC_3(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleGCButtonY",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_GC_4(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleGCButtonZ",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_GC_5(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleGCButtonStart",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_GC_6(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleGCTriggerL",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_GC_7(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleGCTriggerR",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_GC_8(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleGCDPad",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_GC_9(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleGCStickMain",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_GC_10(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleGCStickC",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_0(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicButtonA",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_1(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicButtonB",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_2(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicButtonX",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_3(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicButtonY",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_4(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicButtonPlus",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_5(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicButtonMinus",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_6(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicButtonHome",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_7(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicTriggerL",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_8(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicTriggerR",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_9(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicButtonZL",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_10(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicButtonZR",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_11(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicDPad",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_12(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicStickLeft",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_CLASSIC_13(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleClassicStickRight",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_WII_0(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleWiimoteButtonA",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_WII_1(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleWiimoteButtonB",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_WII_2(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleWiimoteButton1",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_WII_3(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleWiimoteButton2",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_WII_4(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleWiimoteButtonPlus",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_WII_5(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleWiimoteButtonMinus",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_WII_6(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleWiimoteButtonHome",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_WII_7(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleWiimoteDPad",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_WII_8(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleNunchukC",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_WII_9(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleNunchukZ",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
MAIN_BUTTON_TOGGLE_WII_10(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"ButtonToggleNunchukStick",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
SYSCONF_SCREENSAVER(Settings.FILE_SYSCONF, "IPL", "SSV", false),
|
||||||
|
SYSCONF_WIDESCREEN(Settings.FILE_SYSCONF, "IPL", "AR", true),
|
||||||
|
SYSCONF_PROGRESSIVE_SCAN(Settings.FILE_SYSCONF, "IPL", "PGS", true),
|
||||||
|
SYSCONF_PAL60(Settings.FILE_SYSCONF, "IPL", "E60", true),
|
||||||
|
SYSCONF_WIIMOTE_MOTOR(Settings.FILE_SYSCONF, "BT", "MOT", true),
|
||||||
|
GFX_WIDESCREEN_HACK(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "wideScreenHack", false),
|
||||||
|
GFX_CROP(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "Crop", false),
|
||||||
|
GFX_SHOW_FPS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowFPS", false),
|
||||||
|
GFX_SHOW_FTIMES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowFTimes", false),
|
||||||
|
GFX_SHOW_VPS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowVPS", false),
|
||||||
|
GFX_SHOW_VTIMES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowVTimes", false),
|
||||||
|
GFX_SHOW_GRAPHS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowGraphs", false),
|
||||||
|
GFX_SHOW_SPEED(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowSpeed", false),
|
||||||
|
GFX_SHOW_SPEED_COLORS(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"ShowSpeedColors",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
GFX_LOG_RENDER_TIME_TO_FILE(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"LogRenderTimeToFile",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_OVERLAY_STATS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "OverlayStats", false),
|
||||||
|
GFX_DUMP_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpTextures", false),
|
||||||
|
GFX_DUMP_MIP_TEXTURES(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"DumpMipTextures",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_DUMP_BASE_TEXTURES(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"DumpBaseTextures",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_HIRES_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "HiresTextures", false),
|
||||||
|
GFX_CACHE_HIRES_TEXTURES(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"CacheHiresTextures",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_DUMP_EFB_TARGET(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpEFBTarget", false),
|
||||||
|
GFX_DUMP_XFB_TARGET(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpXFBTarget", false),
|
||||||
|
GFX_INTERNAL_RESOLUTION_FRAME_DUMPS(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"InternalResolutionFrameDumps",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_ENABLE_GPU_TEXTURE_DECODING(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"EnableGPUTextureDecoding",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_ENABLE_PIXEL_LIGHTING(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"EnablePixelLighting",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_FAST_DEPTH_CALC(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "FastDepthCalc", true),
|
||||||
|
GFX_TEXFMT_OVERLAY_ENABLE(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"TexFmtOverlayEnable",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_ENABLE_WIREFRAME(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "WireFrame", false),
|
||||||
|
GFX_DISABLE_FOG(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DisableFog", false),
|
||||||
|
GFX_ENABLE_VALIDATION_LAYER(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"EnableValidationLayer",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_BACKEND_MULTITHREADING(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"BackendMultithreading",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
GFX_WAIT_FOR_SHADERS_BEFORE_STARTING(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"WaitForShadersBeforeStarting",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_SAVE_TEXTURE_CACHE_TO_STATE(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"SaveTextureCacheToState",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"PreferVSForLinePointExpansion",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_CPU_CULL(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "CPUCull", false),
|
||||||
|
GFX_MODS_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "EnableMods", false),
|
||||||
|
GFX_ENHANCE_FORCE_TRUE_COLOR(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_ENHANCEMENTS,
|
||||||
|
"ForceTrueColor",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
GFX_ENHANCE_DISABLE_COPY_FILTER(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_ENHANCEMENTS,
|
||||||
|
"DisableCopyFilter",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_ENHANCEMENTS,
|
||||||
|
"ArbitraryMipmapDetection",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
GFX_STEREO_SWAP_EYES(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoSwapEyes", false),
|
||||||
|
GFX_HACK_EFB_ACCESS_ENABLE(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_HACKS,
|
||||||
|
"EFBAccessEnable",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
GFX_HACK_EFB_DEFER_INVALIDATION(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_HACKS,
|
||||||
|
"EFBAccessDeferInvalidation",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_HACK_BBOX_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "BBoxEnable", false),
|
||||||
|
GFX_HACK_SKIP_EFB_COPY_TO_RAM(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_HACKS,
|
||||||
|
"EFBToTextureEnable",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
GFX_HACK_SKIP_XFB_COPY_TO_RAM(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_HACKS,
|
||||||
|
"XFBToTextureEnable",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
GFX_HACK_DISABLE_COPY_TO_VRAM(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_HACKS,
|
||||||
|
"DisableCopyToVRAM",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_HACK_DEFER_EFB_COPIES(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_HACKS,
|
||||||
|
"DeferEFBCopies",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
GFX_HACK_IMMEDIATE_XFB(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_HACKS,
|
||||||
|
"ImmediateXFBEnable",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_HACK_SKIP_DUPLICATE_XFBS(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_HACKS,
|
||||||
|
"SkipDuplicateXFBs",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
GFX_HACK_COPY_EFB_SCALED(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "EFBScaledCopy", true),
|
||||||
|
GFX_HACK_EFB_EMULATE_FORMAT_CHANGES(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_HACKS,
|
||||||
|
"EFBEmulateFormatChanges",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_HACK_VERTEX_ROUNDING(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_HACKS,
|
||||||
|
"VertexRounding",
|
||||||
|
false
|
||||||
|
),
|
||||||
|
GFX_HACK_VI_SKIP(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "VISkip", false),
|
||||||
|
GFX_HACK_FAST_TEXTURE_SAMPLING(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_HACKS,
|
||||||
|
"FastTextureSampling",
|
||||||
|
true
|
||||||
|
),
|
||||||
|
LOGGER_WRITE_TO_FILE(
|
||||||
|
Settings.FILE_LOGGER,
|
||||||
|
Settings.SECTION_LOGGER_OPTIONS,
|
||||||
|
"WriteToFile",
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
override val isOverridden: Boolean
|
||||||
|
get() = NativeConfig.isOverridden(file, section, key)
|
||||||
|
|
||||||
|
override val isRuntimeEditable: Boolean
|
||||||
|
get() {
|
||||||
|
if (file == Settings.FILE_SYSCONF) return false
|
||||||
|
for (setting in NOT_RUNTIME_EDITABLE) {
|
||||||
|
if (setting == this) return false
|
||||||
|
}
|
||||||
|
return NativeConfig.isSettingSaveable(file, section, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun delete(settings: Settings): Boolean {
|
||||||
|
if (!NativeConfig.isSettingSaveable(file, section, key)) {
|
||||||
|
throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
|
||||||
|
}
|
||||||
|
return NativeConfig.deleteKey(settings.writeLayer, file, section, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val boolean: Boolean
|
||||||
|
get() = NativeConfig.getBoolean(
|
||||||
|
NativeConfig.LAYER_ACTIVE,
|
||||||
|
file,
|
||||||
|
section,
|
||||||
|
key,
|
||||||
|
defaultValue
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun setBoolean(settings: Settings, newValue: Boolean) {
|
||||||
|
if (!NativeConfig.isSettingSaveable(file, section, key)) {
|
||||||
|
throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
|
||||||
|
}
|
||||||
|
NativeConfig.setBoolean(settings.writeLayer, file, section, key, newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setBoolean(layer: Int, newValue: Boolean) {
|
||||||
|
if (!NativeConfig.isSettingSaveable(file, section, key)) {
|
||||||
|
throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
|
||||||
|
}
|
||||||
|
NativeConfig.setBoolean(layer, file, section, key, newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val NOT_RUNTIME_EDITABLE_ARRAY = arrayOf(
|
||||||
|
MAIN_DSP_HLE,
|
||||||
|
MAIN_CPU_THREAD,
|
||||||
|
MAIN_ENABLE_CHEATS,
|
||||||
|
MAIN_OVERRIDE_REGION_SETTINGS,
|
||||||
|
MAIN_MMU,
|
||||||
|
MAIN_PAUSE_ON_PANIC,
|
||||||
|
MAIN_ACCURATE_CPU_CACHE,
|
||||||
|
MAIN_RAM_OVERRIDE_ENABLE,
|
||||||
|
MAIN_CUSTOM_RTC_ENABLE,
|
||||||
|
MAIN_DSP_JIT,
|
||||||
|
MAIN_EMULATE_SKYLANDER_PORTAL
|
||||||
|
)
|
||||||
|
private val NOT_RUNTIME_EDITABLE: Set<BooleanSetting> =
|
||||||
|
HashSet(listOf(*NOT_RUNTIME_EDITABLE_ARRAY))
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getSettingForAdapterRumble(channel: Int): BooleanSetting {
|
||||||
|
return arrayOf(
|
||||||
|
MAIN_ADAPTER_RUMBLE_0,
|
||||||
|
MAIN_ADAPTER_RUMBLE_1,
|
||||||
|
MAIN_ADAPTER_RUMBLE_2,
|
||||||
|
MAIN_ADAPTER_RUMBLE_3
|
||||||
|
)[channel]
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getSettingForSimulateKonga(channel: Int): BooleanSetting {
|
||||||
|
return arrayOf(
|
||||||
|
MAIN_SIMULATE_KONGA_0,
|
||||||
|
MAIN_SIMULATE_KONGA_1,
|
||||||
|
MAIN_SIMULATE_KONGA_2,
|
||||||
|
MAIN_SIMULATE_KONGA_3
|
||||||
|
)[channel]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,73 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public enum FloatSetting implements AbstractFloatSetting
|
|
||||||
{
|
|
||||||
// These entries have the same names and order as in C++, just for consistency.
|
|
||||||
|
|
||||||
MAIN_EMULATION_SPEED(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EmulationSpeed", 1.0f),
|
|
||||||
MAIN_OVERCLOCK(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Overclock", 1.0f);
|
|
||||||
|
|
||||||
private final String mFile;
|
|
||||||
private final String mSection;
|
|
||||||
private final String mKey;
|
|
||||||
private final float mDefaultValue;
|
|
||||||
|
|
||||||
FloatSetting(String file, String section, String key, float defaultValue)
|
|
||||||
{
|
|
||||||
mFile = file;
|
|
||||||
mSection = section;
|
|
||||||
mKey = key;
|
|
||||||
mDefaultValue = defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOverridden()
|
|
||||||
{
|
|
||||||
return NativeConfig.isOverridden(mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRuntimeEditable()
|
|
||||||
{
|
|
||||||
return NativeConfig.isSettingSaveable(mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean delete(@NonNull Settings settings)
|
|
||||||
{
|
|
||||||
if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NativeConfig.deleteKey(settings.getWriteLayer(), mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getFloat()
|
|
||||||
{
|
|
||||||
return NativeConfig.getFloat(NativeConfig.LAYER_ACTIVE, mFile, mSection, mKey, mDefaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFloat(@NonNull Settings settings, float newValue)
|
|
||||||
{
|
|
||||||
if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeConfig.setFloat(settings.getWriteLayer(), mFile, mSection, mKey, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFloat(int layer, float newValue)
|
|
||||||
{
|
|
||||||
NativeConfig.setFloat(layer, mFile, mSection, mKey, newValue);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
enum class FloatSetting(
|
||||||
|
private val file: String,
|
||||||
|
private val section: String,
|
||||||
|
private val key: String,
|
||||||
|
private val defaultValue: Float
|
||||||
|
) : AbstractFloatSetting {
|
||||||
|
// These entries have the same names and order as in C++, just for consistency.
|
||||||
|
MAIN_EMULATION_SPEED(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EmulationSpeed", 1.0f),
|
||||||
|
MAIN_OVERCLOCK(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Overclock", 1.0f);
|
||||||
|
|
||||||
|
override val isOverridden: Boolean
|
||||||
|
get() = NativeConfig.isOverridden(file, section, key)
|
||||||
|
|
||||||
|
override val isRuntimeEditable: Boolean
|
||||||
|
get() = NativeConfig.isSettingSaveable(file, section, key)
|
||||||
|
|
||||||
|
override fun delete(settings: Settings): Boolean {
|
||||||
|
if (!NativeConfig.isSettingSaveable(file, section, key)) {
|
||||||
|
throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
|
||||||
|
}
|
||||||
|
return NativeConfig.deleteKey(settings.writeLayer, file, section, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val float: Float
|
||||||
|
get() = NativeConfig.getFloat(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue)
|
||||||
|
|
||||||
|
override fun setFloat(settings: Settings, newValue: Float) {
|
||||||
|
if (!NativeConfig.isSettingSaveable(file, section, key)) {
|
||||||
|
throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
|
||||||
|
}
|
||||||
|
NativeConfig.setFloat(settings.writeLayer, file, section, key, newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setFloat(layer: Int, newValue: Float) {
|
||||||
|
NativeConfig.setFloat(layer, file, section, key, newValue)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,196 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
|
||||||
import org.dolphinemu.dolphinemu.overlay.InputOverlayPointer;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public enum IntSetting implements AbstractIntSetting
|
|
||||||
{
|
|
||||||
// These entries have the same names and order as in C++, just for consistency.
|
|
||||||
|
|
||||||
MAIN_CPU_CORE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "CPUCore",
|
|
||||||
NativeLibrary.DefaultCPUCore()),
|
|
||||||
MAIN_GC_LANGUAGE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SelectedLanguage", 0),
|
|
||||||
MAIN_MEM1_SIZE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "MEM1Size", 0x01800000),
|
|
||||||
MAIN_MEM2_SIZE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "MEM2Size", 0x04000000),
|
|
||||||
MAIN_SLOT_A(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SlotA", 8),
|
|
||||||
MAIN_SLOT_B(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SlotB", 255),
|
|
||||||
MAIN_SERIAL_PORT_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SerialPort1", 255),
|
|
||||||
MAIN_FALLBACK_REGION(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "FallbackRegion", 2),
|
|
||||||
MAIN_SI_DEVICE_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice0", 6),
|
|
||||||
MAIN_SI_DEVICE_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice1", 0),
|
|
||||||
MAIN_SI_DEVICE_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice2", 0),
|
|
||||||
MAIN_SI_DEVICE_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice3", 0),
|
|
||||||
|
|
||||||
MAIN_AUDIO_VOLUME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_DSP, "Volume", 100),
|
|
||||||
|
|
||||||
MAIN_OVERLAY_GC_CONTROLLER(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
|
|
||||||
"OverlayGCController", 0), // Defaults to GameCube controller 1
|
|
||||||
MAIN_OVERLAY_WII_CONTROLLER(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
|
|
||||||
"OverlayWiiController", 4), // Defaults to Wii Remote 1
|
|
||||||
MAIN_CONTROL_SCALE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "ControlScale", 50),
|
|
||||||
MAIN_CONTROL_OPACITY(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "ControlOpacity", 65),
|
|
||||||
MAIN_EMULATION_ORIENTATION(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
|
|
||||||
"EmulationOrientation", ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE),
|
|
||||||
MAIN_INTERFACE_THEME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "InterfaceTheme", 0),
|
|
||||||
MAIN_INTERFACE_THEME_MODE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
|
|
||||||
"InterfaceThemeMode", -1),
|
|
||||||
MAIN_LAST_PLATFORM_TAB(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "LastPlatformTab", 0),
|
|
||||||
MAIN_IR_MODE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "IRMode",
|
|
||||||
InputOverlayPointer.MODE_FOLLOW),
|
|
||||||
|
|
||||||
MAIN_DOUBLE_TAP_BUTTON(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
|
||||||
"DoubleTapButton", NativeLibrary.ButtonType.WIIMOTE_BUTTON_A),
|
|
||||||
|
|
||||||
SYSCONF_LANGUAGE(Settings.FILE_SYSCONF, "IPL", "LNG", 0x01),
|
|
||||||
SYSCONF_SOUND_MODE(Settings.FILE_SYSCONF, "IPL", "SND", 0x01),
|
|
||||||
|
|
||||||
SYSCONF_SENSOR_BAR_POSITION(Settings.FILE_SYSCONF, "BT", "BAR", 0x01),
|
|
||||||
SYSCONF_SENSOR_BAR_SENSITIVITY(Settings.FILE_SYSCONF, "BT", "SENS", 0x03),
|
|
||||||
SYSCONF_SPEAKER_VOLUME(Settings.FILE_SYSCONF, "BT", "SPKV", 0x58),
|
|
||||||
|
|
||||||
GFX_ASPECT_RATIO(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "AspectRatio", 0),
|
|
||||||
GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
|
|
||||||
"SafeTextureCacheColorSamples", 128),
|
|
||||||
GFX_PNG_COMPRESSION_LEVEL(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "PNGCompressionLevel",
|
|
||||||
6),
|
|
||||||
GFX_MSAA(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "MSAA", 1),
|
|
||||||
GFX_EFB_SCALE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "InternalResolution", 1),
|
|
||||||
GFX_SHADER_COMPILATION_MODE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
|
|
||||||
"ShaderCompilationMode", 0),
|
|
||||||
|
|
||||||
GFX_ENHANCE_FORCE_TEXTURE_FILTERING(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS,
|
|
||||||
"ForceTextureFiltering", 0),
|
|
||||||
|
|
||||||
GFX_ENHANCE_MAX_ANISOTROPY(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS, "MaxAnisotropy",
|
|
||||||
0),
|
|
||||||
|
|
||||||
GFX_STEREO_MODE(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoMode", 0),
|
|
||||||
GFX_STEREO_DEPTH(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoDepth", 20),
|
|
||||||
GFX_STEREO_CONVERGENCE_PERCENTAGE(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY,
|
|
||||||
"StereoConvergencePercentage", 100),
|
|
||||||
|
|
||||||
GFX_PERF_SAMP_WINDOW(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "PerfSampWindowMS", 1000),
|
|
||||||
|
|
||||||
LOGGER_VERBOSITY(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_OPTIONS, "Verbosity", 1),
|
|
||||||
|
|
||||||
WIIMOTE_1_SOURCE(Settings.FILE_WIIMOTE, "Wiimote1", "Source", 1),
|
|
||||||
WIIMOTE_2_SOURCE(Settings.FILE_WIIMOTE, "Wiimote2", "Source", 0),
|
|
||||||
WIIMOTE_3_SOURCE(Settings.FILE_WIIMOTE, "Wiimote3", "Source", 0),
|
|
||||||
WIIMOTE_4_SOURCE(Settings.FILE_WIIMOTE, "Wiimote4", "Source", 0),
|
|
||||||
WIIMOTE_BB_SOURCE(Settings.FILE_WIIMOTE, "BalanceBoard", "Source", 0);
|
|
||||||
|
|
||||||
private static final IntSetting[] NOT_RUNTIME_EDITABLE_ARRAY = new IntSetting[]{
|
|
||||||
MAIN_CPU_CORE,
|
|
||||||
MAIN_GC_LANGUAGE,
|
|
||||||
MAIN_MEM1_SIZE,
|
|
||||||
MAIN_MEM2_SIZE,
|
|
||||||
MAIN_SLOT_A, // Can actually be changed, but specific code is required
|
|
||||||
MAIN_SLOT_B, // Can actually be changed, but specific code is required
|
|
||||||
MAIN_SERIAL_PORT_1,
|
|
||||||
MAIN_FALLBACK_REGION,
|
|
||||||
MAIN_SI_DEVICE_0, // Can actually be changed, but specific code is required
|
|
||||||
MAIN_SI_DEVICE_1, // Can actually be changed, but specific code is required
|
|
||||||
MAIN_SI_DEVICE_2, // Can actually be changed, but specific code is required
|
|
||||||
MAIN_SI_DEVICE_3, // Can actually be changed, but specific code is required
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final Set<IntSetting> NOT_RUNTIME_EDITABLE =
|
|
||||||
new HashSet<>(Arrays.asList(NOT_RUNTIME_EDITABLE_ARRAY));
|
|
||||||
|
|
||||||
private final String mFile;
|
|
||||||
private final String mSection;
|
|
||||||
private final String mKey;
|
|
||||||
private final int mDefaultValue;
|
|
||||||
|
|
||||||
IntSetting(String file, String section, String key, int defaultValue)
|
|
||||||
{
|
|
||||||
mFile = file;
|
|
||||||
mSection = section;
|
|
||||||
mKey = key;
|
|
||||||
mDefaultValue = defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOverridden()
|
|
||||||
{
|
|
||||||
return NativeConfig.isOverridden(mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRuntimeEditable()
|
|
||||||
{
|
|
||||||
if (mFile.equals(Settings.FILE_SYSCONF))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (IntSetting setting : NOT_RUNTIME_EDITABLE)
|
|
||||||
{
|
|
||||||
if (setting == this)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NativeConfig.isSettingSaveable(mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean delete(@NonNull Settings settings)
|
|
||||||
{
|
|
||||||
if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NativeConfig.deleteKey(settings.getWriteLayer(), mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getInt()
|
|
||||||
{
|
|
||||||
return NativeConfig.getInt(NativeConfig.LAYER_ACTIVE, mFile, mSection, mKey, mDefaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setInt(@NonNull Settings settings, int newValue)
|
|
||||||
{
|
|
||||||
if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeConfig.setInt(settings.getWriteLayer(), mFile, mSection, mKey, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInt(int layer, int newValue)
|
|
||||||
{
|
|
||||||
if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeConfig.setInt(layer, mFile, mSection, mKey, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IntSetting getSettingForSIDevice(int channel)
|
|
||||||
{
|
|
||||||
return new IntSetting[]{MAIN_SI_DEVICE_0, MAIN_SI_DEVICE_1, MAIN_SI_DEVICE_2, MAIN_SI_DEVICE_3}
|
|
||||||
[channel];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IntSetting getSettingForWiimoteSource(int index)
|
|
||||||
{
|
|
||||||
return new IntSetting[]{WIIMOTE_1_SOURCE, WIIMOTE_2_SOURCE, WIIMOTE_3_SOURCE, WIIMOTE_4_SOURCE,
|
|
||||||
WIIMOTE_BB_SOURCE}[index];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,219 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
|
import org.dolphinemu.dolphinemu.NativeLibrary
|
||||||
|
import org.dolphinemu.dolphinemu.overlay.InputOverlayPointer
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
enum class IntSetting(
|
||||||
|
private val file: String,
|
||||||
|
private val section: String,
|
||||||
|
private val key: String,
|
||||||
|
private val defaultValue: Int
|
||||||
|
) : AbstractIntSetting {
|
||||||
|
// These entries have the same names and order as in C++, just for consistency.
|
||||||
|
MAIN_CPU_CORE(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"CPUCore",
|
||||||
|
NativeLibrary.DefaultCPUCore()
|
||||||
|
),
|
||||||
|
MAIN_GC_LANGUAGE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SelectedLanguage", 0),
|
||||||
|
MAIN_MEM1_SIZE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "MEM1Size", 0x01800000),
|
||||||
|
MAIN_MEM2_SIZE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "MEM2Size", 0x04000000),
|
||||||
|
MAIN_SLOT_A(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SlotA", 8),
|
||||||
|
MAIN_SLOT_B(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SlotB", 255),
|
||||||
|
MAIN_SERIAL_PORT_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SerialPort1", 255),
|
||||||
|
MAIN_FALLBACK_REGION(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "FallbackRegion", 2),
|
||||||
|
MAIN_SI_DEVICE_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice0", 6),
|
||||||
|
MAIN_SI_DEVICE_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice1", 0),
|
||||||
|
MAIN_SI_DEVICE_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice2", 0),
|
||||||
|
MAIN_SI_DEVICE_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice3", 0),
|
||||||
|
MAIN_AUDIO_VOLUME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_DSP, "Volume", 100),
|
||||||
|
MAIN_OVERLAY_GC_CONTROLLER(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID,
|
||||||
|
"OverlayGCController",
|
||||||
|
0
|
||||||
|
),
|
||||||
|
|
||||||
|
// Defaults to GameCube controller 1
|
||||||
|
MAIN_OVERLAY_WII_CONTROLLER(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID,
|
||||||
|
"OverlayWiiController",
|
||||||
|
4
|
||||||
|
),
|
||||||
|
|
||||||
|
// Defaults to Wii Remote 1
|
||||||
|
MAIN_CONTROL_SCALE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "ControlScale", 50),
|
||||||
|
MAIN_CONTROL_OPACITY(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "ControlOpacity", 65),
|
||||||
|
MAIN_EMULATION_ORIENTATION(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID,
|
||||||
|
"EmulationOrientation",
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||||
|
),
|
||||||
|
MAIN_INTERFACE_THEME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "InterfaceTheme", 0),
|
||||||
|
MAIN_INTERFACE_THEME_MODE(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID,
|
||||||
|
"InterfaceThemeMode",
|
||||||
|
-1
|
||||||
|
),
|
||||||
|
MAIN_LAST_PLATFORM_TAB(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID,
|
||||||
|
"LastPlatformTab",
|
||||||
|
0
|
||||||
|
),
|
||||||
|
MAIN_IR_MODE(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID,
|
||||||
|
"IRMode",
|
||||||
|
InputOverlayPointer.MODE_FOLLOW
|
||||||
|
),
|
||||||
|
MAIN_DOUBLE_TAP_BUTTON(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
|
||||||
|
"DoubleTapButton",
|
||||||
|
NativeLibrary.ButtonType.WIIMOTE_BUTTON_A
|
||||||
|
),
|
||||||
|
SYSCONF_LANGUAGE(Settings.FILE_SYSCONF, "IPL", "LNG", 0x01),
|
||||||
|
SYSCONF_SOUND_MODE(Settings.FILE_SYSCONF, "IPL", "SND", 0x01),
|
||||||
|
SYSCONF_SENSOR_BAR_POSITION(Settings.FILE_SYSCONF, "BT", "BAR", 0x01),
|
||||||
|
SYSCONF_SENSOR_BAR_SENSITIVITY(Settings.FILE_SYSCONF, "BT", "SENS", 0x03),
|
||||||
|
SYSCONF_SPEAKER_VOLUME(Settings.FILE_SYSCONF, "BT", "SPKV", 0x58),
|
||||||
|
GFX_ASPECT_RATIO(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "AspectRatio", 0),
|
||||||
|
GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"SafeTextureCacheColorSamples",
|
||||||
|
128
|
||||||
|
),
|
||||||
|
GFX_PNG_COMPRESSION_LEVEL(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"PNGCompressionLevel",
|
||||||
|
6
|
||||||
|
),
|
||||||
|
GFX_MSAA(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "MSAA", 1),
|
||||||
|
GFX_EFB_SCALE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "InternalResolution", 1),
|
||||||
|
GFX_SHADER_COMPILATION_MODE(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"ShaderCompilationMode",
|
||||||
|
0
|
||||||
|
),
|
||||||
|
GFX_ENHANCE_FORCE_TEXTURE_FILTERING(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_ENHANCEMENTS,
|
||||||
|
"ForceTextureFiltering",
|
||||||
|
0
|
||||||
|
),
|
||||||
|
GFX_ENHANCE_MAX_ANISOTROPY(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_ENHANCEMENTS,
|
||||||
|
"MaxAnisotropy",
|
||||||
|
0
|
||||||
|
),
|
||||||
|
GFX_STEREO_MODE(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoMode", 0),
|
||||||
|
GFX_STEREO_DEPTH(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoDepth", 20),
|
||||||
|
GFX_STEREO_CONVERGENCE_PERCENTAGE(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_STEREOSCOPY,
|
||||||
|
"StereoConvergencePercentage",
|
||||||
|
100
|
||||||
|
),
|
||||||
|
GFX_PERF_SAMP_WINDOW(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_SETTINGS,
|
||||||
|
"PerfSampWindowMS",
|
||||||
|
1000
|
||||||
|
),
|
||||||
|
LOGGER_VERBOSITY(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_OPTIONS, "Verbosity", 1),
|
||||||
|
WIIMOTE_1_SOURCE(Settings.FILE_WIIMOTE, "Wiimote1", "Source", 1),
|
||||||
|
WIIMOTE_2_SOURCE(Settings.FILE_WIIMOTE, "Wiimote2", "Source", 0),
|
||||||
|
WIIMOTE_3_SOURCE(Settings.FILE_WIIMOTE, "Wiimote3", "Source", 0),
|
||||||
|
WIIMOTE_4_SOURCE(Settings.FILE_WIIMOTE, "Wiimote4", "Source", 0),
|
||||||
|
WIIMOTE_BB_SOURCE(Settings.FILE_WIIMOTE, "BalanceBoard", "Source", 0);
|
||||||
|
|
||||||
|
override val isOverridden: Boolean
|
||||||
|
get() = NativeConfig.isOverridden(file, section, key)
|
||||||
|
|
||||||
|
override val isRuntimeEditable: Boolean
|
||||||
|
get() {
|
||||||
|
if (file == Settings.FILE_SYSCONF) return false
|
||||||
|
for (setting in NOT_RUNTIME_EDITABLE) {
|
||||||
|
if (setting == this) return false
|
||||||
|
}
|
||||||
|
return NativeConfig.isSettingSaveable(file, section, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun delete(settings: Settings): Boolean {
|
||||||
|
if (!NativeConfig.isSettingSaveable(file, section, key)) {
|
||||||
|
throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
|
||||||
|
}
|
||||||
|
return NativeConfig.deleteKey(settings.writeLayer, file, section, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val int: Int
|
||||||
|
get() = NativeConfig.getInt(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue)
|
||||||
|
|
||||||
|
override fun setInt(settings: Settings, newValue: Int) {
|
||||||
|
if (!NativeConfig.isSettingSaveable(file, section, key)) {
|
||||||
|
throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
|
||||||
|
}
|
||||||
|
NativeConfig.setInt(settings.writeLayer, file, section, key, newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setInt(layer: Int, newValue: Int) {
|
||||||
|
if (!NativeConfig.isSettingSaveable(file, section, key)) {
|
||||||
|
throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
|
||||||
|
}
|
||||||
|
NativeConfig.setInt(layer, file, section, key, newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val NOT_RUNTIME_EDITABLE_ARRAY = arrayOf(
|
||||||
|
MAIN_CPU_CORE,
|
||||||
|
MAIN_GC_LANGUAGE,
|
||||||
|
MAIN_MEM1_SIZE,
|
||||||
|
MAIN_MEM2_SIZE,
|
||||||
|
MAIN_SLOT_A,
|
||||||
|
MAIN_SLOT_B,
|
||||||
|
MAIN_SERIAL_PORT_1,
|
||||||
|
MAIN_FALLBACK_REGION,
|
||||||
|
MAIN_SI_DEVICE_0,
|
||||||
|
MAIN_SI_DEVICE_1,
|
||||||
|
MAIN_SI_DEVICE_2,
|
||||||
|
MAIN_SI_DEVICE_3
|
||||||
|
)
|
||||||
|
|
||||||
|
private val NOT_RUNTIME_EDITABLE: Set<IntSetting> =
|
||||||
|
HashSet(listOf(*NOT_RUNTIME_EDITABLE_ARRAY))
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getSettingForSIDevice(channel: Int): IntSetting {
|
||||||
|
return arrayOf(
|
||||||
|
MAIN_SI_DEVICE_0,
|
||||||
|
MAIN_SI_DEVICE_1,
|
||||||
|
MAIN_SI_DEVICE_2,
|
||||||
|
MAIN_SI_DEVICE_3
|
||||||
|
)[channel]
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getSettingForWiimoteSource(index: Int): IntSetting {
|
||||||
|
return arrayOf(
|
||||||
|
WIIMOTE_1_SOURCE,
|
||||||
|
WIIMOTE_2_SOURCE,
|
||||||
|
WIIMOTE_3_SOURCE,
|
||||||
|
WIIMOTE_4_SOURCE,
|
||||||
|
WIIMOTE_BB_SOURCE
|
||||||
|
)[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,51 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
public class NativeConfig
|
|
||||||
{
|
|
||||||
public static final int LAYER_BASE_OR_CURRENT = 0;
|
|
||||||
public static final int LAYER_BASE = 1;
|
|
||||||
public static final int LAYER_LOCAL_GAME = 2;
|
|
||||||
public static final int LAYER_ACTIVE = 3;
|
|
||||||
public static final int LAYER_CURRENT = 4;
|
|
||||||
|
|
||||||
public static native boolean isSettingSaveable(String file, String section, String key);
|
|
||||||
|
|
||||||
public static native void loadGameInis(String gameId, int revision);
|
|
||||||
|
|
||||||
public static native void unloadGameInis();
|
|
||||||
|
|
||||||
public static native void save(int layer);
|
|
||||||
|
|
||||||
public static native void deleteAllKeys(int layer);
|
|
||||||
|
|
||||||
public static native boolean isOverridden(String file, String section, String key);
|
|
||||||
|
|
||||||
public static native boolean deleteKey(int layer, String file, String section, String key);
|
|
||||||
|
|
||||||
public static native boolean exists(int layer, String file, String section, String key);
|
|
||||||
|
|
||||||
public static native String getString(int layer, String file, String section, String key,
|
|
||||||
String defaultValue);
|
|
||||||
|
|
||||||
public static native boolean getBoolean(int layer, String file, String section, String key,
|
|
||||||
boolean defaultValue);
|
|
||||||
|
|
||||||
public static native int getInt(int layer, String file, String section, String key,
|
|
||||||
int defaultValue);
|
|
||||||
|
|
||||||
public static native float getFloat(int layer, String file, String section, String key,
|
|
||||||
float defaultValue);
|
|
||||||
|
|
||||||
public static native void setString(int layer, String file, String section, String key,
|
|
||||||
String value);
|
|
||||||
|
|
||||||
public static native void setBoolean(int layer, String file, String section, String key,
|
|
||||||
boolean value);
|
|
||||||
|
|
||||||
public static native void setInt(int layer, String file, String section, String key, int value);
|
|
||||||
|
|
||||||
public static native void setFloat(int layer, String file, String section, String key,
|
|
||||||
float value);
|
|
||||||
}
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
object NativeConfig {
|
||||||
|
const val LAYER_BASE_OR_CURRENT = 0
|
||||||
|
const val LAYER_BASE = 1
|
||||||
|
const val LAYER_LOCAL_GAME = 2
|
||||||
|
const val LAYER_ACTIVE = 3
|
||||||
|
const val LAYER_CURRENT = 4
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun isSettingSaveable(file: String, section: String, key: String): Boolean
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun loadGameInis(gameId: String, revision: Int)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun unloadGameInis()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun save(layer: Int)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun deleteAllKeys(layer: Int)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun isOverridden(file: String, section: String, key: String): Boolean
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun deleteKey(layer: Int, file: String, section: String, key: String): Boolean
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun exists(layer: Int, file: String, section: String, key: String): Boolean
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun getString(
|
||||||
|
layer: Int,
|
||||||
|
file: String,
|
||||||
|
section: String,
|
||||||
|
key: String,
|
||||||
|
defaultValue: String
|
||||||
|
): String
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun getBoolean(
|
||||||
|
layer: Int,
|
||||||
|
file: String,
|
||||||
|
section: String,
|
||||||
|
key: String,
|
||||||
|
defaultValue: Boolean
|
||||||
|
): Boolean
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun getInt(
|
||||||
|
layer: Int,
|
||||||
|
file: String,
|
||||||
|
section: String,
|
||||||
|
key: String,
|
||||||
|
defaultValue: Int
|
||||||
|
): Int
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun getFloat(
|
||||||
|
layer: Int,
|
||||||
|
file: String,
|
||||||
|
section: String,
|
||||||
|
key: String,
|
||||||
|
defaultValue: Float
|
||||||
|
): Float
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun setString(
|
||||||
|
layer: Int,
|
||||||
|
file: String,
|
||||||
|
section: String,
|
||||||
|
key: String,
|
||||||
|
value: String?
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun setBoolean(
|
||||||
|
layer: Int,
|
||||||
|
file: String,
|
||||||
|
section: String,
|
||||||
|
key: String,
|
||||||
|
value: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun setInt(
|
||||||
|
layer: Int,
|
||||||
|
file: String,
|
||||||
|
section: String,
|
||||||
|
key: String,
|
||||||
|
value: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun setFloat(
|
||||||
|
layer: Int,
|
||||||
|
file: String,
|
||||||
|
section: String,
|
||||||
|
key: String,
|
||||||
|
value: Float
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,17 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public class PostProcessing
|
|
||||||
{
|
|
||||||
@NonNull
|
|
||||||
public static native String[] getShaderList();
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static native String[] getAnaglyphShaderList();
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static native String[] getPassiveShaderList();
|
|
||||||
}
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
object PostProcessing {
|
||||||
|
@JvmStatic
|
||||||
|
val shaderList: Array<String?>
|
||||||
|
external get
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
val anaglyphShaderList: Array<String?>
|
||||||
|
external get
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
val passiveShaderList: Array<String?>
|
||||||
|
external get
|
||||||
|
}
|
|
@ -6,21 +6,18 @@ class ScaledIntSetting(
|
||||||
private val scale: Int,
|
private val scale: Int,
|
||||||
private val setting: AbstractIntSetting
|
private val setting: AbstractIntSetting
|
||||||
) : AbstractIntSetting {
|
) : AbstractIntSetting {
|
||||||
override fun isOverridden(): Boolean {
|
override val isOverridden: Boolean
|
||||||
return setting.isOverridden()
|
get() = setting.isOverridden
|
||||||
}
|
|
||||||
|
|
||||||
override fun isRuntimeEditable(): Boolean {
|
override val isRuntimeEditable: Boolean
|
||||||
return setting.isRuntimeEditable
|
get() = setting.isRuntimeEditable
|
||||||
}
|
|
||||||
|
|
||||||
override fun delete(settings: Settings): Boolean {
|
override fun delete(settings: Settings): Boolean {
|
||||||
return setting.delete(settings)
|
return setting.delete(settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getInt(): Int {
|
override val int: Int
|
||||||
return setting.getInt() / scale
|
get() = setting.int / scale
|
||||||
}
|
|
||||||
|
|
||||||
override fun setInt(settings: Settings, newValue: Int) {
|
override fun setInt(settings: Settings, newValue: Int) {
|
||||||
return setting.setInt(settings, newValue * scale)
|
return setting.setInt(settings, newValue * scale)
|
||||||
|
|
|
@ -1,181 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
|
||||||
import org.dolphinemu.dolphinemu.features.input.model.MappingCommon;
|
|
||||||
import org.dolphinemu.dolphinemu.services.GameFileCacheManager;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
|
||||||
|
|
||||||
public class Settings implements Closeable
|
|
||||||
{
|
|
||||||
public static final String FILE_DOLPHIN = "Dolphin";
|
|
||||||
public static final String FILE_SYSCONF = "SYSCONF";
|
|
||||||
public static final String FILE_GFX = "GFX";
|
|
||||||
public static final String FILE_LOGGER = "Logger";
|
|
||||||
public static final String FILE_WIIMOTE = "WiimoteNew";
|
|
||||||
public static final String FILE_GAME_SETTINGS_ONLY = "GameSettingsOnly";
|
|
||||||
|
|
||||||
public static final String SECTION_INI_ANDROID = "Android";
|
|
||||||
public static final String SECTION_INI_ANDROID_OVERLAY_BUTTONS = "AndroidOverlayButtons";
|
|
||||||
public static final String SECTION_INI_GENERAL = "General";
|
|
||||||
public static final String SECTION_INI_CORE = "Core";
|
|
||||||
public static final String SECTION_INI_INTERFACE = "Interface";
|
|
||||||
public static final String SECTION_INI_DSP = "DSP";
|
|
||||||
|
|
||||||
public static final String SECTION_LOGGER_LOGS = "Logs";
|
|
||||||
public static final String SECTION_LOGGER_OPTIONS = "Options";
|
|
||||||
|
|
||||||
public static final String SECTION_GFX_SETTINGS = "Settings";
|
|
||||||
public static final String SECTION_GFX_ENHANCEMENTS = "Enhancements";
|
|
||||||
public static final String SECTION_GFX_HACKS = "Hacks";
|
|
||||||
|
|
||||||
public static final String SECTION_DEBUG = "Debug";
|
|
||||||
public static final String SECTION_EMULATED_USB_DEVICES = "EmulatedUSBDevices";
|
|
||||||
|
|
||||||
public static final String SECTION_STEREOSCOPY = "Stereoscopy";
|
|
||||||
|
|
||||||
public static final String SECTION_BINDINGS = "Android";
|
|
||||||
public static final String SECTION_PROFILE = "Profile";
|
|
||||||
|
|
||||||
public static final String SECTION_ANALYTICS = "Analytics";
|
|
||||||
|
|
||||||
private String mGameId;
|
|
||||||
private int mRevision;
|
|
||||||
private boolean mIsWii;
|
|
||||||
|
|
||||||
private boolean mSettingsLoaded = false;
|
|
||||||
|
|
||||||
private boolean mLoadedRecursiveIsoPathsValue = false;
|
|
||||||
|
|
||||||
public boolean isGameSpecific()
|
|
||||||
{
|
|
||||||
return !TextUtils.isEmpty(mGameId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isWii()
|
|
||||||
{
|
|
||||||
return mIsWii;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWriteLayer()
|
|
||||||
{
|
|
||||||
return isGameSpecific() ? NativeConfig.LAYER_LOCAL_GAME : NativeConfig.LAYER_BASE_OR_CURRENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean areSettingsLoaded()
|
|
||||||
{
|
|
||||||
return mSettingsLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadSettings()
|
|
||||||
{
|
|
||||||
// The value of isWii doesn't matter if we don't have any SettingsActivity
|
|
||||||
loadSettings(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadSettings(boolean isWii)
|
|
||||||
{
|
|
||||||
mIsWii = isWii;
|
|
||||||
mSettingsLoaded = true;
|
|
||||||
|
|
||||||
if (isGameSpecific())
|
|
||||||
{
|
|
||||||
// Loading game INIs while the core is running will mess with the game INIs loaded by the core
|
|
||||||
if (NativeLibrary.IsRunning())
|
|
||||||
throw new IllegalStateException("Attempted to load game INI while emulating");
|
|
||||||
|
|
||||||
NativeConfig.loadGameInis(mGameId, mRevision);
|
|
||||||
}
|
|
||||||
|
|
||||||
mLoadedRecursiveIsoPathsValue = BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.getBoolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadSettings(String gameId, int revision, boolean isWii)
|
|
||||||
{
|
|
||||||
mGameId = gameId;
|
|
||||||
mRevision = revision;
|
|
||||||
loadSettings(isWii);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveSettings(Context context)
|
|
||||||
{
|
|
||||||
if (!isGameSpecific())
|
|
||||||
{
|
|
||||||
if (context != null)
|
|
||||||
Toast.makeText(context, R.string.settings_saved, Toast.LENGTH_SHORT).show();
|
|
||||||
|
|
||||||
MappingCommon.save();
|
|
||||||
|
|
||||||
NativeConfig.save(NativeConfig.LAYER_BASE);
|
|
||||||
|
|
||||||
NativeLibrary.ReloadLoggerConfig();
|
|
||||||
NativeLibrary.UpdateGCAdapterScanThread();
|
|
||||||
|
|
||||||
if (mLoadedRecursiveIsoPathsValue != BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.getBoolean())
|
|
||||||
{
|
|
||||||
// Refresh game library
|
|
||||||
GameFileCacheManager.startRescan();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// custom game settings
|
|
||||||
|
|
||||||
if (context != null)
|
|
||||||
{
|
|
||||||
Toast.makeText(context, context.getString(R.string.settings_saved_game_specific, mGameId),
|
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeConfig.save(NativeConfig.LAYER_LOCAL_GAME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearGameSettings()
|
|
||||||
{
|
|
||||||
NativeConfig.deleteAllKeys(NativeConfig.LAYER_LOCAL_GAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean gameIniContainsJunk()
|
|
||||||
{
|
|
||||||
// Older versions of Android Dolphin would copy the entire contents of most of the global INIs
|
|
||||||
// into any game INI that got saved (with some of the sections renamed to match the game INI
|
|
||||||
// section names). The problems with this are twofold:
|
|
||||||
//
|
|
||||||
// 1. The user game INIs will contain entries that Dolphin doesn't support reading from
|
|
||||||
// game INIs. This is annoying when editing game INIs manually but shouldn't really be
|
|
||||||
// a problem for those who only use the GUI.
|
|
||||||
//
|
|
||||||
// 2. Global settings will stick around in user game INIs. For instance, if someone wants to
|
|
||||||
// change the texture cache accuracy to safe for all games, they have to edit not only the
|
|
||||||
// global settings but also every single game INI they have created, since the old value of
|
|
||||||
// the texture cache accuracy setting has been copied into every user game INI.
|
|
||||||
//
|
|
||||||
// These problems are serious enough that we should detect and delete such INI files.
|
|
||||||
// Problem 1 is easy to detect, but due to the nature of problem 2, it's unfortunately not
|
|
||||||
// possible to know which lines were added intentionally by the user and which lines were added
|
|
||||||
// unintentionally, which is why we have to delete the whole file in order to fix everything.
|
|
||||||
|
|
||||||
if (!isGameSpecific())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return NativeConfig.exists(NativeConfig.LAYER_LOCAL_GAME, FILE_DOLPHIN, SECTION_INI_INTERFACE,
|
|
||||||
"ThemeName");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close()
|
|
||||||
{
|
|
||||||
if (isGameSpecific())
|
|
||||||
{
|
|
||||||
NativeConfig.unloadGameInis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.widget.Toast
|
||||||
|
import org.dolphinemu.dolphinemu.NativeLibrary
|
||||||
|
import org.dolphinemu.dolphinemu.R
|
||||||
|
import org.dolphinemu.dolphinemu.features.input.model.MappingCommon
|
||||||
|
import org.dolphinemu.dolphinemu.services.GameFileCacheManager
|
||||||
|
import java.io.Closeable
|
||||||
|
|
||||||
|
class Settings : Closeable {
|
||||||
|
private var gameId: String = ""
|
||||||
|
private var revision = 0
|
||||||
|
|
||||||
|
var isWii = false
|
||||||
|
private set
|
||||||
|
|
||||||
|
private var settingsLoaded = false
|
||||||
|
private var loadedRecursiveIsoPathsValue = false
|
||||||
|
|
||||||
|
private val isGameSpecific: Boolean
|
||||||
|
get() = !TextUtils.isEmpty(gameId)
|
||||||
|
|
||||||
|
val writeLayer: Int
|
||||||
|
get() = if (isGameSpecific) NativeConfig.LAYER_LOCAL_GAME else NativeConfig.LAYER_BASE_OR_CURRENT
|
||||||
|
|
||||||
|
fun areSettingsLoaded(): Boolean {
|
||||||
|
return settingsLoaded
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
fun loadSettings(isWii: Boolean = true) {
|
||||||
|
this.isWii = isWii
|
||||||
|
settingsLoaded = true
|
||||||
|
|
||||||
|
if (isGameSpecific) {
|
||||||
|
// Loading game INIs while the core is running will mess with the game INIs loaded by the core
|
||||||
|
check(!NativeLibrary.IsRunning()) { "Attempted to load game INI while emulating" }
|
||||||
|
NativeConfig.loadGameInis(gameId, revision)
|
||||||
|
}
|
||||||
|
|
||||||
|
loadedRecursiveIsoPathsValue = BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadSettings(gameId: String, revision: Int, isWii: Boolean) {
|
||||||
|
this.gameId = gameId
|
||||||
|
this.revision = revision
|
||||||
|
loadSettings(isWii)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveSettings(context: Context?) {
|
||||||
|
if (!isGameSpecific) {
|
||||||
|
if (context != null) Toast.makeText(
|
||||||
|
context,
|
||||||
|
R.string.settings_saved,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
|
||||||
|
MappingCommon.save()
|
||||||
|
|
||||||
|
NativeConfig.save(NativeConfig.LAYER_BASE)
|
||||||
|
|
||||||
|
NativeLibrary.ReloadLoggerConfig()
|
||||||
|
NativeLibrary.UpdateGCAdapterScanThread()
|
||||||
|
|
||||||
|
if (loadedRecursiveIsoPathsValue != BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.boolean) {
|
||||||
|
// Refresh game library
|
||||||
|
GameFileCacheManager.startRescan()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// custom game settings
|
||||||
|
if (context != null) {
|
||||||
|
Toast.makeText(
|
||||||
|
context, context.getString(R.string.settings_saved_game_specific, gameId),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
NativeConfig.save(NativeConfig.LAYER_LOCAL_GAME)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearGameSettings() {
|
||||||
|
NativeConfig.deleteAllKeys(NativeConfig.LAYER_LOCAL_GAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun gameIniContainsJunk(): Boolean {
|
||||||
|
// Older versions of Android Dolphin would copy the entire contents of most of the global INIs
|
||||||
|
// into any game INI that got saved (with some of the sections renamed to match the game INI
|
||||||
|
// section names). The problems with this are twofold:
|
||||||
|
//
|
||||||
|
// 1. The user game INIs will contain entries that Dolphin doesn't support reading from
|
||||||
|
// game INIs. This is annoying when editing game INIs manually but shouldn't really be
|
||||||
|
// a problem for those who only use the GUI.
|
||||||
|
//
|
||||||
|
// 2. Global settings will stick around in user game INIs. For instance, if someone wants to
|
||||||
|
// change the texture cache accuracy to safe for all games, they have to edit not only the
|
||||||
|
// global settings but also every single game INI they have created, since the old value of
|
||||||
|
// the texture cache accuracy Setting has been copied into every user game INI.
|
||||||
|
//
|
||||||
|
// These problems are serious enough that we should detect and delete such INI files.
|
||||||
|
// Problem 1 is easy to detect, but due to the nature of problem 2, it's unfortunately not
|
||||||
|
// possible to know which lines were added intentionally by the user and which lines were added
|
||||||
|
// unintentionally, which is why we have to delete the whole file in order to fix everything.
|
||||||
|
return if (!isGameSpecific) false else NativeConfig.exists(
|
||||||
|
NativeConfig.LAYER_LOCAL_GAME,
|
||||||
|
FILE_DOLPHIN,
|
||||||
|
SECTION_INI_INTERFACE,
|
||||||
|
"ThemeName"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
if (isGameSpecific) {
|
||||||
|
NativeConfig.unloadGameInis()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val FILE_DOLPHIN = "Dolphin"
|
||||||
|
const val FILE_SYSCONF = "SYSCONF"
|
||||||
|
const val FILE_GFX = "GFX"
|
||||||
|
const val FILE_LOGGER = "Logger"
|
||||||
|
const val FILE_WIIMOTE = "WiimoteNew"
|
||||||
|
const val FILE_GAME_SETTINGS_ONLY = "GameSettingsOnly"
|
||||||
|
const val SECTION_INI_ANDROID = "Android"
|
||||||
|
const val SECTION_INI_ANDROID_OVERLAY_BUTTONS = "AndroidOverlayButtons"
|
||||||
|
const val SECTION_INI_GENERAL = "General"
|
||||||
|
const val SECTION_INI_CORE = "Core"
|
||||||
|
const val SECTION_INI_INTERFACE = "Interface"
|
||||||
|
const val SECTION_INI_DSP = "DSP"
|
||||||
|
const val SECTION_LOGGER_LOGS = "Logs"
|
||||||
|
const val SECTION_LOGGER_OPTIONS = "Options"
|
||||||
|
const val SECTION_GFX_SETTINGS = "Settings"
|
||||||
|
const val SECTION_GFX_ENHANCEMENTS = "Enhancements"
|
||||||
|
const val SECTION_GFX_HACKS = "Hacks"
|
||||||
|
const val SECTION_DEBUG = "Debug"
|
||||||
|
const val SECTION_EMULATED_USB_DEVICES = "EmulatedUSBDevices"
|
||||||
|
const val SECTION_STEREOSCOPY = "Stereoscopy"
|
||||||
|
const val SECTION_ANALYTICS = "Analytics"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,113 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public enum StringSetting implements AbstractStringSetting
|
|
||||||
{
|
|
||||||
// These entries have the same names and order as in C++, just for consistency.
|
|
||||||
|
|
||||||
MAIN_DEFAULT_ISO(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "DefaultISO", ""),
|
|
||||||
|
|
||||||
MAIN_BBA_MAC(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_MAC", ""),
|
|
||||||
MAIN_BBA_XLINK_IP(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_XLINK_IP", ""),
|
|
||||||
|
|
||||||
// Schthack PSO Server - https://schtserv.com/
|
|
||||||
MAIN_BBA_BUILTIN_DNS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_BUILTIN_DNS",
|
|
||||||
"149.56.167.128"),
|
|
||||||
|
|
||||||
MAIN_CUSTOM_RTC_VALUE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "CustomRTCValue",
|
|
||||||
"0x386d4380"),
|
|
||||||
|
|
||||||
MAIN_GFX_BACKEND(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "GFXBackend",
|
|
||||||
NativeLibrary.GetDefaultGraphicsBackendName()),
|
|
||||||
|
|
||||||
MAIN_DUMP_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "DumpPath", ""),
|
|
||||||
MAIN_LOAD_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "LoadPath", ""),
|
|
||||||
MAIN_RESOURCEPACK_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "ResourcePackPath",
|
|
||||||
""),
|
|
||||||
MAIN_FS_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "NANDRootPath", ""),
|
|
||||||
MAIN_WII_SD_CARD_IMAGE_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "WiiSDCardPath",
|
|
||||||
""),
|
|
||||||
MAIN_WII_SD_CARD_SYNC_FOLDER_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL,
|
|
||||||
"WiiSDCardSyncFolder", ""),
|
|
||||||
MAIN_WFS_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "WFSPath", ""),
|
|
||||||
|
|
||||||
GFX_ENHANCE_POST_SHADER(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS,
|
|
||||||
"PostProcessingShader", "");
|
|
||||||
|
|
||||||
private static final StringSetting[] NOT_RUNTIME_EDITABLE_ARRAY = new StringSetting[]{
|
|
||||||
MAIN_CUSTOM_RTC_VALUE,
|
|
||||||
MAIN_GFX_BACKEND,
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final Set<StringSetting> NOT_RUNTIME_EDITABLE =
|
|
||||||
new HashSet<>(Arrays.asList(NOT_RUNTIME_EDITABLE_ARRAY));
|
|
||||||
|
|
||||||
private final String mFile;
|
|
||||||
private final String mSection;
|
|
||||||
private final String mKey;
|
|
||||||
private final String mDefaultValue;
|
|
||||||
|
|
||||||
StringSetting(String file, String section, String key, String defaultValue)
|
|
||||||
{
|
|
||||||
mFile = file;
|
|
||||||
mSection = section;
|
|
||||||
mKey = key;
|
|
||||||
mDefaultValue = defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOverridden()
|
|
||||||
{
|
|
||||||
return NativeConfig.isOverridden(mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRuntimeEditable()
|
|
||||||
{
|
|
||||||
for (StringSetting setting : NOT_RUNTIME_EDITABLE)
|
|
||||||
{
|
|
||||||
if (setting == this)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NativeConfig.isSettingSaveable(mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean delete(@NonNull Settings settings)
|
|
||||||
{
|
|
||||||
return NativeConfig.deleteKey(settings.getWriteLayer(), mFile, mSection, mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public String getString()
|
|
||||||
{
|
|
||||||
if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NativeConfig.getString(NativeConfig.LAYER_ACTIVE, mFile, mSection, mKey, mDefaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setString(@NonNull Settings settings, @NonNull String newValue)
|
|
||||||
{
|
|
||||||
NativeConfig.setString(settings.getWriteLayer(), mFile, mSection, mKey, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setString(int layer, String newValue)
|
|
||||||
{
|
|
||||||
NativeConfig.setString(layer, mFile, mSection, mKey, newValue);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.NativeLibrary
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
enum class StringSetting(
|
||||||
|
private val file: String,
|
||||||
|
private val section: String,
|
||||||
|
private val key: String,
|
||||||
|
private val defaultValue: String
|
||||||
|
) : AbstractStringSetting {
|
||||||
|
// These entries have the same names and order as in C++, just for consistency.
|
||||||
|
MAIN_DEFAULT_ISO(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "DefaultISO", ""),
|
||||||
|
MAIN_BBA_MAC(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_MAC", ""),
|
||||||
|
MAIN_BBA_XLINK_IP(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_XLINK_IP", ""),
|
||||||
|
|
||||||
|
// Schthack PSO Server - https://schtserv.com/
|
||||||
|
MAIN_BBA_BUILTIN_DNS(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"BBA_BUILTIN_DNS",
|
||||||
|
"149.56.167.128"
|
||||||
|
),
|
||||||
|
MAIN_CUSTOM_RTC_VALUE(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"CustomRTCValue",
|
||||||
|
"0x386d4380"
|
||||||
|
),
|
||||||
|
MAIN_GFX_BACKEND(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"GFXBackend",
|
||||||
|
NativeLibrary.GetDefaultGraphicsBackendName()
|
||||||
|
),
|
||||||
|
MAIN_DUMP_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "DumpPath", ""),
|
||||||
|
MAIN_LOAD_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "LoadPath", ""),
|
||||||
|
MAIN_RESOURCEPACK_PATH(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_GENERAL,
|
||||||
|
"ResourcePackPath",
|
||||||
|
""
|
||||||
|
),
|
||||||
|
MAIN_FS_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "NANDRootPath", ""),
|
||||||
|
MAIN_WII_SD_CARD_IMAGE_PATH(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_GENERAL,
|
||||||
|
"WiiSDCardPath",
|
||||||
|
""
|
||||||
|
),
|
||||||
|
MAIN_WII_SD_CARD_SYNC_FOLDER_PATH(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_GENERAL,
|
||||||
|
"WiiSDCardSyncFolder",
|
||||||
|
""
|
||||||
|
),
|
||||||
|
MAIN_WFS_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "WFSPath", ""),
|
||||||
|
GFX_ENHANCE_POST_SHADER(
|
||||||
|
Settings.FILE_GFX,
|
||||||
|
Settings.SECTION_GFX_ENHANCEMENTS,
|
||||||
|
"PostProcessingShader",
|
||||||
|
""
|
||||||
|
);
|
||||||
|
|
||||||
|
override val isOverridden: Boolean
|
||||||
|
get() = NativeConfig.isOverridden(file, section, key)
|
||||||
|
|
||||||
|
override val isRuntimeEditable: Boolean
|
||||||
|
get() {
|
||||||
|
for (setting in NOT_RUNTIME_EDITABLE) {
|
||||||
|
if (setting == this) return false
|
||||||
|
}
|
||||||
|
return NativeConfig.isSettingSaveable(file, section, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun delete(settings: Settings): Boolean {
|
||||||
|
return NativeConfig.deleteKey(settings.writeLayer, file, section, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val string: String
|
||||||
|
get() = if (!NativeConfig.isSettingSaveable(file, section, key)) {
|
||||||
|
throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
|
||||||
|
} else NativeConfig.getString(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue)
|
||||||
|
|
||||||
|
override fun setString(settings: Settings, newValue: String) {
|
||||||
|
NativeConfig.setString(settings.writeLayer, file, section, key, newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setString(layer: Int, newValue: String?) {
|
||||||
|
NativeConfig.setString(layer, file, section, key, newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val NOT_RUNTIME_EDITABLE_ARRAY = arrayOf(
|
||||||
|
MAIN_CUSTOM_RTC_VALUE,
|
||||||
|
MAIN_GFX_BACKEND
|
||||||
|
)
|
||||||
|
|
||||||
|
private val NOT_RUNTIME_EDITABLE: Set<StringSetting> =
|
||||||
|
HashSet(listOf(*NOT_RUNTIME_EDITABLE_ARRAY))
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,29 +3,22 @@
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
|
||||||
class DateTimeChoiceSetting(
|
class DateTimeChoiceSetting(
|
||||||
context: Context,
|
context: Context,
|
||||||
private val setting: AbstractStringSetting,
|
override val setting: AbstractStringSetting,
|
||||||
nameId: Int,
|
nameId: Int,
|
||||||
descriptionId: Int
|
descriptionId: Int
|
||||||
) : SettingsItem(context, nameId, descriptionId) {
|
) : SettingsItem(context, nameId, descriptionId) {
|
||||||
override fun getType(): Int {
|
override val type: Int = TYPE_DATETIME_CHOICE
|
||||||
return TYPE_DATETIME_CHOICE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getSetting(): AbstractSetting {
|
|
||||||
return setting
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setSelectedValue(settings: Settings, selection: String) {
|
fun setSelectedValue(settings: Settings, selection: String) {
|
||||||
setting.setString(settings, selection)
|
setting.setString(settings, selection)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSelectedValue(): String {
|
fun getSelectedValue(): String {
|
||||||
return setting.getString()
|
return setting.string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
|
|
||||||
public final class FilePicker extends SettingsItem
|
|
||||||
{
|
|
||||||
private AbstractStringSetting mSetting;
|
|
||||||
private int mRequestType;
|
|
||||||
private String mDefaultPathRelativeToUserDirectory;
|
|
||||||
|
|
||||||
public FilePicker(Context context, AbstractStringSetting setting, int titleId, int descriptionId,
|
|
||||||
int requestType, @Nullable String defaultPathRelativeToUserDirectory)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId);
|
|
||||||
mSetting = setting;
|
|
||||||
mRequestType = requestType;
|
|
||||||
mDefaultPathRelativeToUserDirectory = defaultPathRelativeToUserDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSelectedValue()
|
|
||||||
{
|
|
||||||
return mSetting.getString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelectedValue(Settings settings, String selection)
|
|
||||||
{
|
|
||||||
mSetting.setString(settings, selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRequestType()
|
|
||||||
{
|
|
||||||
return mRequestType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getDefaultPathRelativeToUserDirectory()
|
|
||||||
{
|
|
||||||
return mDefaultPathRelativeToUserDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return TYPE_FILE_PICKER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return mSetting;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
|
||||||
|
class FilePicker(
|
||||||
|
context: Context,
|
||||||
|
override var setting: AbstractStringSetting,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int,
|
||||||
|
val requestType: Int,
|
||||||
|
val defaultPathRelativeToUserDirectory: String?
|
||||||
|
) : SettingsItem(context, titleId, descriptionId) {
|
||||||
|
override val type: Int = TYPE_FILE_PICKER
|
||||||
|
|
||||||
|
fun getSelectedValue() : String {
|
||||||
|
return setting.string
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSelectedValue(settings: Settings, selection: String) {
|
||||||
|
setting.setString(settings, selection)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
|
|
||||||
public class FloatSliderSetting extends SliderSetting
|
|
||||||
{
|
|
||||||
protected AbstractFloatSetting mSetting;
|
|
||||||
|
|
||||||
public FloatSliderSetting(Context context, AbstractFloatSetting setting, int titleId,
|
|
||||||
int descriptionId, int min, int max, String units, int stepSize)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId, min, max, units, stepSize);
|
|
||||||
mSetting = setting;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FloatSliderSetting(AbstractFloatSetting setting, CharSequence name,
|
|
||||||
CharSequence description, int min, int max, String units)
|
|
||||||
{
|
|
||||||
super(name, description, min, max, units);
|
|
||||||
mSetting = setting;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSelectedValue()
|
|
||||||
{
|
|
||||||
return Math.round(mSetting.getFloat());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelectedValue(Settings settings, float selection)
|
|
||||||
{
|
|
||||||
mSetting.setFloat(settings, selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return mSetting;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
open class FloatSliderSetting : SliderSetting {
|
||||||
|
var floatSetting: AbstractFloatSetting
|
||||||
|
|
||||||
|
override val setting: AbstractSetting
|
||||||
|
get() = floatSetting
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
context: Context,
|
||||||
|
setting: AbstractFloatSetting,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int,
|
||||||
|
min: Int,
|
||||||
|
max: Int,
|
||||||
|
units: String?,
|
||||||
|
stepSize: Int
|
||||||
|
) : super(context, titleId, descriptionId, min, max, units, stepSize) {
|
||||||
|
floatSetting = setting
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
setting: AbstractFloatSetting,
|
||||||
|
name: CharSequence,
|
||||||
|
description: CharSequence?,
|
||||||
|
min: Int,
|
||||||
|
max: Int,
|
||||||
|
units: String?
|
||||||
|
) : super(name, description, min, max, units) {
|
||||||
|
floatSetting = setting
|
||||||
|
}
|
||||||
|
|
||||||
|
override val selectedValue: Int
|
||||||
|
get() = floatSetting.float.roundToInt()
|
||||||
|
|
||||||
|
open fun setSelectedValue(settings: Settings?, selection: Float) {
|
||||||
|
floatSetting.setFloat(settings!!, selection)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
|
|
||||||
public class HeaderSetting extends SettingsItem
|
|
||||||
{
|
|
||||||
public HeaderSetting(Context context, int titleId, int descriptionId)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HeaderSetting(CharSequence title, CharSequence description)
|
|
||||||
{
|
|
||||||
super(title, description);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return SettingsItem.TYPE_HEADER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
||||||
|
|
||||||
|
open class HeaderSetting : SettingsItem {
|
||||||
|
override val setting: AbstractSetting? = null
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
context: Context,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int
|
||||||
|
) : super(context, titleId, descriptionId)
|
||||||
|
|
||||||
|
constructor(title: CharSequence, description: CharSequence?) : super(title, description)
|
||||||
|
|
||||||
|
override val type: Int = TYPE_HEADER
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
public final class HyperLinkHeaderSetting extends HeaderSetting
|
|
||||||
{
|
|
||||||
public HyperLinkHeaderSetting(Context context, int titleId, int descriptionId)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return SettingsItem.TYPE_HYPERLINK_HEADER;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
|
||||||
|
class HyperLinkHeaderSetting(
|
||||||
|
context: Context,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int
|
||||||
|
) : HeaderSetting(context, titleId, descriptionId)
|
|
@ -1,72 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
|
||||||
|
|
||||||
public class InputStringSetting extends SettingsItem
|
|
||||||
{
|
|
||||||
private AbstractStringSetting mSetting;
|
|
||||||
|
|
||||||
private MenuTag mMenuTag;
|
|
||||||
|
|
||||||
public InputStringSetting(Context context, AbstractStringSetting setting, int titleId,
|
|
||||||
int descriptionId, MenuTag menuTag)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId);
|
|
||||||
mSetting = setting;
|
|
||||||
mMenuTag = menuTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStringSetting(Context context, AbstractStringSetting setting, int titleId,
|
|
||||||
int descriptionId)
|
|
||||||
{
|
|
||||||
this(context, setting, titleId, descriptionId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStringSetting(Context context, AbstractStringSetting setting, int titleId,
|
|
||||||
int descriptionId, int choicesId, int valuesId, MenuTag menuTag)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId);
|
|
||||||
mSetting = setting;
|
|
||||||
mMenuTag = menuTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStringSetting(Context context, AbstractStringSetting setting, int titleId,
|
|
||||||
int descriptionId, int choicesId, int valuesId)
|
|
||||||
{
|
|
||||||
this(context, setting, titleId, descriptionId, choicesId, valuesId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSelectedValue()
|
|
||||||
{
|
|
||||||
return mSetting.getString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MenuTag getMenuTag()
|
|
||||||
{
|
|
||||||
return mMenuTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelectedValue(Settings settings, String selection)
|
|
||||||
{
|
|
||||||
mSetting.setString(settings, selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return TYPE_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return mSetting;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
|
||||||
|
class InputStringSetting(
|
||||||
|
context: Context,
|
||||||
|
setting: AbstractStringSetting,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int,
|
||||||
|
) : SettingsItem(context, titleId, descriptionId) {
|
||||||
|
override val type: Int = TYPE_STRING
|
||||||
|
|
||||||
|
private var stringSetting: AbstractStringSetting = setting
|
||||||
|
|
||||||
|
override val setting: AbstractSetting
|
||||||
|
get() = stringSetting
|
||||||
|
|
||||||
|
val selectedValue: String
|
||||||
|
get() = stringSetting.string
|
||||||
|
|
||||||
|
fun setSelectedValue(settings: Settings, selection: String) {
|
||||||
|
stringSetting.setString(settings, selection)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,37 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
|
|
||||||
public final class IntSliderSetting extends SliderSetting
|
|
||||||
{
|
|
||||||
private AbstractIntSetting mSetting;
|
|
||||||
|
|
||||||
public IntSliderSetting(Context context, AbstractIntSetting setting, int titleId,
|
|
||||||
int descriptionId, int min, int max, String units, int stepSize)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId, min, max, units, stepSize);
|
|
||||||
mSetting = setting;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSelectedValue()
|
|
||||||
{
|
|
||||||
return mSetting.getInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelectedValue(Settings settings, int selection)
|
|
||||||
{
|
|
||||||
mSetting.setInt(settings, selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return mSetting;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
|
||||||
|
class IntSliderSetting(
|
||||||
|
context: Context,
|
||||||
|
private val intSetting: AbstractIntSetting,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int,
|
||||||
|
min: Int,
|
||||||
|
max: Int,
|
||||||
|
units: String?,
|
||||||
|
stepSize: Int
|
||||||
|
) : SliderSetting(context, titleId, descriptionId, min, max, units, stepSize) {
|
||||||
|
override val setting: AbstractSetting
|
||||||
|
get() = intSetting
|
||||||
|
|
||||||
|
override val selectedValue: Int
|
||||||
|
get() = intSetting.int
|
||||||
|
|
||||||
|
fun setSelectedValue(settings: Settings?, selection: Int) {
|
||||||
|
intSetting.setInt(settings!!, selection)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,36 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractBooleanSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
|
|
||||||
public final class InvertedSwitchSetting extends SwitchSetting
|
|
||||||
{
|
|
||||||
public InvertedSwitchSetting(Context context, AbstractBooleanSetting setting, int titleId,
|
|
||||||
int descriptionId)
|
|
||||||
{
|
|
||||||
super(context, setting, titleId, descriptionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChecked()
|
|
||||||
{
|
|
||||||
return !mSetting.getBoolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setChecked(Settings settings, boolean checked)
|
|
||||||
{
|
|
||||||
mSetting.setBoolean(settings, !checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return mSetting;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractBooleanSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
|
||||||
|
class InvertedSwitchSetting(
|
||||||
|
context: Context,
|
||||||
|
setting: AbstractBooleanSetting,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int
|
||||||
|
) : SwitchSetting(context, setting, titleId, descriptionId) {
|
||||||
|
override val setting: AbstractSetting
|
||||||
|
get() = booleanSetting
|
||||||
|
|
||||||
|
override val isChecked: Boolean
|
||||||
|
get() = !booleanSetting.boolean
|
||||||
|
|
||||||
|
override fun setChecked(settings: Settings?, checked: Boolean) {
|
||||||
|
booleanSetting.setBoolean(settings!!, !checked)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,23 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AdHocBooleanSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
|
|
||||||
public class LogSwitchSetting extends SwitchSetting
|
|
||||||
{
|
|
||||||
String mKey;
|
|
||||||
|
|
||||||
public LogSwitchSetting(String key, CharSequence title, CharSequence description)
|
|
||||||
{
|
|
||||||
super(new AdHocBooleanSetting(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_LOGS, key, false),
|
|
||||||
title, description);
|
|
||||||
mKey = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKey()
|
|
||||||
{
|
|
||||||
return mKey;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AdHocBooleanSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
|
||||||
|
class LogSwitchSetting(
|
||||||
|
var key: String,
|
||||||
|
title: CharSequence?,
|
||||||
|
description: CharSequence?
|
||||||
|
) : SwitchSetting(
|
||||||
|
AdHocBooleanSetting(
|
||||||
|
Settings.FILE_LOGGER,
|
||||||
|
Settings.SECTION_LOGGER_LOGS,
|
||||||
|
key,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
title,
|
||||||
|
description
|
||||||
|
)
|
|
@ -1,36 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
|
|
||||||
public final class PercentSliderSetting extends FloatSliderSetting
|
|
||||||
{
|
|
||||||
public PercentSliderSetting(Context context, AbstractFloatSetting setting, int titleId,
|
|
||||||
int descriptionId, int min, int max, String units, int stepSize)
|
|
||||||
{
|
|
||||||
super(context, setting, titleId, descriptionId, min, max, units, stepSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSelectedValue()
|
|
||||||
{
|
|
||||||
return Math.round(mSetting.getFloat() * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSelectedValue(Settings settings, float selection)
|
|
||||||
{
|
|
||||||
mSetting.setFloat(settings, selection / 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return mSetting;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
class PercentSliderSetting(
|
||||||
|
context: Context,
|
||||||
|
override val setting: AbstractFloatSetting,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int,
|
||||||
|
min: Int,
|
||||||
|
max: Int,
|
||||||
|
units: String?,
|
||||||
|
stepSize: Int
|
||||||
|
) : FloatSliderSetting(context, setting, titleId, descriptionId, min, max, units, stepSize) {
|
||||||
|
override val selectedValue: Int
|
||||||
|
get() = (floatSetting.float * 100).roundToInt()
|
||||||
|
|
||||||
|
override fun setSelectedValue(settings: Settings?, selection: Float) {
|
||||||
|
floatSetting.setFloat(settings!!, selection / 100)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,59 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
|
|
||||||
public final class RunRunnable extends SettingsItem
|
|
||||||
{
|
|
||||||
private final int mAlertText;
|
|
||||||
private final int mToastTextAfterRun;
|
|
||||||
private final boolean mWorksDuringEmulation;
|
|
||||||
private final Runnable mRunnable;
|
|
||||||
|
|
||||||
public RunRunnable(Context context, int titleId, int descriptionId, int alertText,
|
|
||||||
int toastTextAfterRun, boolean worksDuringEmulation, Runnable runnable)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId);
|
|
||||||
mAlertText = alertText;
|
|
||||||
mToastTextAfterRun = toastTextAfterRun;
|
|
||||||
mWorksDuringEmulation = worksDuringEmulation;
|
|
||||||
mRunnable = runnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAlertText()
|
|
||||||
{
|
|
||||||
return mAlertText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getToastTextAfterRun()
|
|
||||||
{
|
|
||||||
return mToastTextAfterRun;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Runnable getRunnable()
|
|
||||||
{
|
|
||||||
return mRunnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return TYPE_RUN_RUNNABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEditable()
|
|
||||||
{
|
|
||||||
return mWorksDuringEmulation || !NativeLibrary.IsRunning();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.NativeLibrary
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
||||||
|
|
||||||
|
class RunRunnable(
|
||||||
|
context: Context,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int,
|
||||||
|
val alertText: Int,
|
||||||
|
val toastTextAfterRun: Int,
|
||||||
|
private val worksDuringEmulation: Boolean,
|
||||||
|
val runnable: Runnable
|
||||||
|
) : SettingsItem(context, titleId, descriptionId) {
|
||||||
|
override val type: Int = TYPE_RUN_RUNNABLE
|
||||||
|
|
||||||
|
override val setting: AbstractSetting? = null
|
||||||
|
|
||||||
|
override val isEditable: Boolean
|
||||||
|
get() = worksDuringEmulation || !NativeLibrary.IsRunning()
|
||||||
|
}
|
|
@ -1,107 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ViewModel abstraction for an Item in the RecyclerView powering SettingsFragments.
|
|
||||||
* Most of them correspond to a single line in an INI file, but there are a few with multiple
|
|
||||||
* analogues and a few with none (Headers, for example, do not correspond to anything on disk.)
|
|
||||||
*/
|
|
||||||
public abstract class SettingsItem
|
|
||||||
{
|
|
||||||
public static final int TYPE_HEADER = 0;
|
|
||||||
public static final int TYPE_SWITCH = 1;
|
|
||||||
public static final int TYPE_SINGLE_CHOICE = 2;
|
|
||||||
public static final int TYPE_SLIDER = 3;
|
|
||||||
public static final int TYPE_SUBMENU = 4;
|
|
||||||
public static final int TYPE_INPUT_MAPPING_CONTROL = 5;
|
|
||||||
public static final int TYPE_STRING_SINGLE_CHOICE = 6;
|
|
||||||
public static final int TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS = 8;
|
|
||||||
public static final int TYPE_FILE_PICKER = 9;
|
|
||||||
public static final int TYPE_RUN_RUNNABLE = 10;
|
|
||||||
public static final int TYPE_STRING = 11;
|
|
||||||
public static final int TYPE_HYPERLINK_HEADER = 12;
|
|
||||||
public static final int TYPE_DATETIME_CHOICE = 13;
|
|
||||||
|
|
||||||
private final CharSequence mName;
|
|
||||||
private final CharSequence mDescription;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base constructor.
|
|
||||||
*
|
|
||||||
* @param name A text string to be displayed as this setting's name.
|
|
||||||
* @param description A text string to be displayed as this setting's description.
|
|
||||||
*/
|
|
||||||
public SettingsItem(CharSequence name, CharSequence description)
|
|
||||||
{
|
|
||||||
mName = name;
|
|
||||||
mDescription = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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.
|
|
||||||
*/
|
|
||||||
public SettingsItem(Context context, int nameId, int descriptionId)
|
|
||||||
{
|
|
||||||
mName = nameId == 0 ? "" : context.getText(nameId);
|
|
||||||
mDescription = descriptionId == 0 ? "" : context.getText(descriptionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CharSequence getName()
|
|
||||||
{
|
|
||||||
return mName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CharSequence getDescription()
|
|
||||||
{
|
|
||||||
return mDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by {@link SettingsAdapter}'s onCreateViewHolder()
|
|
||||||
* method to determine which type of ViewHolder should be created.
|
|
||||||
*
|
|
||||||
* @return An integer (ideally, one of the constants defined in this file)
|
|
||||||
*/
|
|
||||||
public abstract int getType();
|
|
||||||
|
|
||||||
protected abstract AbstractSetting getSetting();
|
|
||||||
|
|
||||||
public boolean isOverridden()
|
|
||||||
{
|
|
||||||
AbstractSetting setting = getSetting();
|
|
||||||
return setting != null && setting.isOverridden();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEditable()
|
|
||||||
{
|
|
||||||
if (!NativeLibrary.IsRunning())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
AbstractSetting setting = getSetting();
|
|
||||||
return setting != null && setting.isRuntimeEditable();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasSetting()
|
|
||||||
{
|
|
||||||
return getSetting() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canClear()
|
|
||||||
{
|
|
||||||
return hasSetting();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear(Settings settings)
|
|
||||||
{
|
|
||||||
getSetting().delete(settings);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.NativeLibrary
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ViewModel abstraction for an Item in the RecyclerView powering SettingsFragments.
|
||||||
|
* Most of them correspond to a single line in an INI file, but there are a few with multiple
|
||||||
|
* analogues and a few with none (Headers, for example, do not correspond to anything on disk.)
|
||||||
|
*/
|
||||||
|
abstract class SettingsItem {
|
||||||
|
val name: CharSequence
|
||||||
|
val description: CharSequence?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base constructor.
|
||||||
|
*
|
||||||
|
* @param name A text string to be displayed as this Setting's name.
|
||||||
|
* @param description A text string to be displayed as this Setting's description.
|
||||||
|
*/
|
||||||
|
constructor(name: CharSequence, description: CharSequence?) {
|
||||||
|
this.name = name
|
||||||
|
this.description = description
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
constructor(context: Context, nameId: Int, descriptionId: Int) {
|
||||||
|
name = if (nameId == 0) "" else context.getText(nameId)
|
||||||
|
description = if (descriptionId == 0) "" else context.getText(descriptionId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by [SettingsAdapter]'s onCreateViewHolder()
|
||||||
|
* method to determine which type of ViewHolder should be created.
|
||||||
|
*
|
||||||
|
* @return An integer (ideally, one of the constants defined in this file)
|
||||||
|
*/
|
||||||
|
abstract val type: Int
|
||||||
|
|
||||||
|
abstract val setting: AbstractSetting?
|
||||||
|
|
||||||
|
val isOverridden: Boolean
|
||||||
|
get() {
|
||||||
|
val setting = setting
|
||||||
|
return setting != null && setting.isOverridden
|
||||||
|
}
|
||||||
|
|
||||||
|
open val isEditable: Boolean
|
||||||
|
get() {
|
||||||
|
if (!NativeLibrary.IsRunning()) return true
|
||||||
|
val setting = setting
|
||||||
|
return setting != null && setting.isRuntimeEditable
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasSetting(): Boolean {
|
||||||
|
return setting != null
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun canClear(): Boolean {
|
||||||
|
return hasSetting()
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun clear(settings: Settings) {
|
||||||
|
setting!!.delete(settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TYPE_HEADER = 0
|
||||||
|
const val TYPE_SWITCH = 1
|
||||||
|
const val TYPE_SINGLE_CHOICE = 2
|
||||||
|
const val TYPE_SLIDER = 3
|
||||||
|
const val TYPE_SUBMENU = 4
|
||||||
|
const val TYPE_INPUT_MAPPING_CONTROL = 5
|
||||||
|
const val TYPE_STRING_SINGLE_CHOICE = 6
|
||||||
|
const val TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS = 8
|
||||||
|
const val TYPE_FILE_PICKER = 9
|
||||||
|
const val TYPE_RUN_RUNNABLE = 10
|
||||||
|
const val TYPE_STRING = 11
|
||||||
|
const val TYPE_HYPERLINK_HEADER = 12
|
||||||
|
const val TYPE_DATETIME_CHOICE = 13
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,72 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
|
||||||
|
|
||||||
public final class SingleChoiceSetting extends SettingsItem
|
|
||||||
{
|
|
||||||
private AbstractIntSetting mSetting;
|
|
||||||
|
|
||||||
private int mChoicesId;
|
|
||||||
private int mValuesId;
|
|
||||||
private MenuTag menuTag;
|
|
||||||
|
|
||||||
public SingleChoiceSetting(Context context, AbstractIntSetting setting, int titleId,
|
|
||||||
int descriptionId, int choicesId, int valuesId, MenuTag menuTag)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId);
|
|
||||||
mSetting = setting;
|
|
||||||
mValuesId = valuesId;
|
|
||||||
mChoicesId = choicesId;
|
|
||||||
this.menuTag = menuTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SingleChoiceSetting(Context context, AbstractIntSetting setting, int titleId,
|
|
||||||
int descriptionId, int choicesId, int valuesId)
|
|
||||||
{
|
|
||||||
this(context, setting, titleId, descriptionId, choicesId, valuesId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getChoicesId()
|
|
||||||
{
|
|
||||||
return mChoicesId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getValuesId()
|
|
||||||
{
|
|
||||||
return mValuesId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSelectedValue()
|
|
||||||
{
|
|
||||||
return mSetting.getInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MenuTag getMenuTag()
|
|
||||||
{
|
|
||||||
return menuTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelectedValue(Settings settings, int selection)
|
|
||||||
{
|
|
||||||
mSetting.setInt(settings, selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return TYPE_SINGLE_CHOICE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return mSetting;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag
|
||||||
|
|
||||||
|
class SingleChoiceSetting(
|
||||||
|
context: Context,
|
||||||
|
private val intSetting: AbstractIntSetting,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int,
|
||||||
|
val choicesId: Int,
|
||||||
|
val valuesId: Int,
|
||||||
|
val menuTag: MenuTag? = null
|
||||||
|
) : SettingsItem(context, titleId, descriptionId) {
|
||||||
|
override val type: Int = TYPE_SINGLE_CHOICE
|
||||||
|
|
||||||
|
override val setting: AbstractSetting
|
||||||
|
get() = intSetting
|
||||||
|
|
||||||
|
val selectedValue: Int
|
||||||
|
get() = intSetting.int
|
||||||
|
|
||||||
|
fun setSelectedValue(settings: Settings?, selection: Int) {
|
||||||
|
intSetting.setInt(settings!!, selection)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,89 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
|
||||||
|
|
||||||
public final class SingleChoiceSettingDynamicDescriptions extends SettingsItem
|
|
||||||
{
|
|
||||||
private AbstractIntSetting mSetting;
|
|
||||||
|
|
||||||
private int mChoicesId;
|
|
||||||
private int mValuesId;
|
|
||||||
private int mDescriptionChoicesId;
|
|
||||||
private int mDescriptionValuesId;
|
|
||||||
private MenuTag menuTag;
|
|
||||||
|
|
||||||
public SingleChoiceSettingDynamicDescriptions(Context context, AbstractIntSetting setting,
|
|
||||||
int titleId, int descriptionId, int choicesId, int valuesId, int descriptionChoicesId,
|
|
||||||
int descriptionValuesId, MenuTag menuTag)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId);
|
|
||||||
mSetting = setting;
|
|
||||||
mValuesId = valuesId;
|
|
||||||
mChoicesId = choicesId;
|
|
||||||
mDescriptionChoicesId = descriptionChoicesId;
|
|
||||||
mDescriptionValuesId = descriptionValuesId;
|
|
||||||
this.menuTag = menuTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SingleChoiceSettingDynamicDescriptions(Context context, AbstractIntSetting setting,
|
|
||||||
int titleId, int descriptionId, int choicesId, int valuesId, int descriptionChoicesId,
|
|
||||||
int descriptionValuesId)
|
|
||||||
{
|
|
||||||
this(context, setting, titleId, descriptionId, choicesId, valuesId, descriptionChoicesId,
|
|
||||||
descriptionValuesId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getChoicesId()
|
|
||||||
{
|
|
||||||
return mChoicesId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getValuesId()
|
|
||||||
{
|
|
||||||
return mValuesId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDescriptionChoicesId()
|
|
||||||
{
|
|
||||||
return mDescriptionChoicesId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDescriptionValuesId()
|
|
||||||
{
|
|
||||||
return mDescriptionValuesId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSelectedValue()
|
|
||||||
{
|
|
||||||
return mSetting.getInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MenuTag getMenuTag()
|
|
||||||
{
|
|
||||||
return menuTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelectedValue(Settings settings, int selection)
|
|
||||||
{
|
|
||||||
mSetting.setInt(settings, selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return mSetting;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
|
||||||
|
class SingleChoiceSettingDynamicDescriptions(
|
||||||
|
context: Context,
|
||||||
|
override val setting: AbstractIntSetting,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int,
|
||||||
|
val choicesId: Int,
|
||||||
|
val valuesId: Int,
|
||||||
|
val descriptionChoicesId: Int,
|
||||||
|
val descriptionValuesId: Int,
|
||||||
|
) : SettingsItem(context, titleId, descriptionId) {
|
||||||
|
override val type: Int = TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS
|
||||||
|
|
||||||
|
val selectedValue: Int
|
||||||
|
get() = setting.int
|
||||||
|
|
||||||
|
fun setSelectedValue(settings: Settings, selection: Int) {
|
||||||
|
setting.setInt(settings, selection)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,61 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
|
|
||||||
public abstract class SliderSetting extends SettingsItem
|
|
||||||
{
|
|
||||||
private int mMin;
|
|
||||||
private int mMax;
|
|
||||||
private String mUnits;
|
|
||||||
private int mStepSize;
|
|
||||||
|
|
||||||
public SliderSetting(Context context, int nameId, int descriptionId, int min, int max,
|
|
||||||
String units, int stepSize)
|
|
||||||
{
|
|
||||||
super(context, nameId, descriptionId);
|
|
||||||
mMin = min;
|
|
||||||
mMax = max;
|
|
||||||
mUnits = units;
|
|
||||||
mStepSize = stepSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SliderSetting(CharSequence name, CharSequence description, int min, int max, String units)
|
|
||||||
{
|
|
||||||
super(name, description);
|
|
||||||
mMin = min;
|
|
||||||
mMax = max;
|
|
||||||
mUnits = units;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract int getSelectedValue();
|
|
||||||
|
|
||||||
public int getMin()
|
|
||||||
{
|
|
||||||
return mMin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMax()
|
|
||||||
{
|
|
||||||
return mMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUnits()
|
|
||||||
{
|
|
||||||
return mUnits;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getStepSize()
|
|
||||||
{
|
|
||||||
return mStepSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return TYPE_SLIDER;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
|
||||||
|
abstract class SliderSetting : SettingsItem {
|
||||||
|
override val type: Int = TYPE_SLIDER
|
||||||
|
|
||||||
|
var min: Int
|
||||||
|
private set
|
||||||
|
var max: Int
|
||||||
|
private set
|
||||||
|
var units: String?
|
||||||
|
private set
|
||||||
|
var stepSize = 0
|
||||||
|
private set
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
context: Context,
|
||||||
|
nameId: Int,
|
||||||
|
descriptionId: Int,
|
||||||
|
min: Int,
|
||||||
|
max: Int,
|
||||||
|
units: String?,
|
||||||
|
stepSize: Int
|
||||||
|
) : super(context, nameId, descriptionId) {
|
||||||
|
this.min = min
|
||||||
|
this.max = max
|
||||||
|
this.units = units
|
||||||
|
this.stepSize = stepSize
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
name: CharSequence,
|
||||||
|
description: CharSequence?,
|
||||||
|
min: Int,
|
||||||
|
max: Int,
|
||||||
|
units: String?
|
||||||
|
) : super(name, description) {
|
||||||
|
this.min = min
|
||||||
|
this.max = max
|
||||||
|
this.units = units
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract val selectedValue: Int
|
||||||
|
}
|
|
@ -1,153 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.DolphinApplication;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
|
||||||
|
|
||||||
public class StringSingleChoiceSetting extends SettingsItem
|
|
||||||
{
|
|
||||||
private final AbstractStringSetting mSetting;
|
|
||||||
|
|
||||||
protected String[] mChoices;
|
|
||||||
protected String[] mValues;
|
|
||||||
private final MenuTag mMenuTag;
|
|
||||||
private int mNoChoicesAvailableString = 0;
|
|
||||||
|
|
||||||
public StringSingleChoiceSetting(Context context, AbstractStringSetting setting, int titleId,
|
|
||||||
int descriptionId, String[] choices, String[] values, MenuTag menuTag)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId);
|
|
||||||
mSetting = setting;
|
|
||||||
mChoices = choices;
|
|
||||||
mValues = values;
|
|
||||||
mMenuTag = menuTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringSingleChoiceSetting(Context context, AbstractStringSetting setting, int titleId,
|
|
||||||
int descriptionId, String[] choices, String[] values)
|
|
||||||
{
|
|
||||||
this(context, setting, titleId, descriptionId, choices, values, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringSingleChoiceSetting(Context context, AbstractStringSetting setting, int titleId,
|
|
||||||
int descriptionId, String[] choices, String[] values, int noChoicesAvailableString)
|
|
||||||
{
|
|
||||||
this(context, setting, titleId, descriptionId, choices, values, null);
|
|
||||||
mNoChoicesAvailableString = noChoicesAvailableString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringSingleChoiceSetting(Context context, AbstractStringSetting setting, int titleId,
|
|
||||||
int descriptionId, int choicesId, int valuesId, MenuTag menuTag)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId);
|
|
||||||
mSetting = setting;
|
|
||||||
mChoices = DolphinApplication.getAppContext().getResources().getStringArray(choicesId);
|
|
||||||
mValues = DolphinApplication.getAppContext().getResources().getStringArray(valuesId);
|
|
||||||
mMenuTag = menuTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringSingleChoiceSetting(Context context, AbstractStringSetting setting, int titleId,
|
|
||||||
int descriptionId, int choicesId, int valuesId)
|
|
||||||
{
|
|
||||||
this(context, setting, titleId, descriptionId, choicesId, valuesId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] getChoices()
|
|
||||||
{
|
|
||||||
return mChoices;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] getValues()
|
|
||||||
{
|
|
||||||
return mValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getChoiceAt(int index)
|
|
||||||
{
|
|
||||||
if (mChoices == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (index >= 0 && index < mChoices.length)
|
|
||||||
{
|
|
||||||
return mChoices[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValueAt(int index)
|
|
||||||
{
|
|
||||||
if (mValues == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (index >= 0 && index < mValues.length)
|
|
||||||
{
|
|
||||||
return mValues[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSelectedChoice()
|
|
||||||
{
|
|
||||||
return getChoiceAt(getSelectedValueIndex());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSelectedValue()
|
|
||||||
{
|
|
||||||
return mSetting.getString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSelectedValueIndex()
|
|
||||||
{
|
|
||||||
String selectedValue = getSelectedValue();
|
|
||||||
for (int i = 0; i < mValues.length; i++)
|
|
||||||
{
|
|
||||||
if (mValues[i].equals(selectedValue))
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MenuTag getMenuTag()
|
|
||||||
{
|
|
||||||
return mMenuTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNoChoicesAvailableString()
|
|
||||||
{
|
|
||||||
return mNoChoicesAvailableString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelectedValue(Settings settings, String selection)
|
|
||||||
{
|
|
||||||
mSetting.setString(settings, selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void refreshChoicesAndValues()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return TYPE_STRING_SINGLE_CHOICE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return mSetting;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.DolphinApplication
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag
|
||||||
|
|
||||||
|
open class StringSingleChoiceSetting : SettingsItem {
|
||||||
|
override val type: Int = TYPE_SINGLE_CHOICE
|
||||||
|
|
||||||
|
private val stringSetting: AbstractStringSetting?
|
||||||
|
|
||||||
|
override val setting: AbstractSetting?
|
||||||
|
get() = stringSetting
|
||||||
|
|
||||||
|
var choices: Array<String?>?
|
||||||
|
protected set
|
||||||
|
var values: Array<String?>?
|
||||||
|
protected set
|
||||||
|
val menuTag: MenuTag?
|
||||||
|
var noChoicesAvailableString = 0
|
||||||
|
private set
|
||||||
|
|
||||||
|
open val selectedChoice: String?
|
||||||
|
get() = getChoiceAt(selectedValueIndex)
|
||||||
|
|
||||||
|
open val selectedValue: String
|
||||||
|
get() = stringSetting!!.string
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
constructor(
|
||||||
|
context: Context,
|
||||||
|
setting: AbstractStringSetting?,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int,
|
||||||
|
choices: Array<String?>?,
|
||||||
|
values: Array<String?>?,
|
||||||
|
menuTag: MenuTag? = null
|
||||||
|
) : super(context, titleId, descriptionId) {
|
||||||
|
stringSetting = setting
|
||||||
|
this.choices = choices
|
||||||
|
this.values = values
|
||||||
|
this.menuTag = menuTag
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
context: Context,
|
||||||
|
setting: AbstractStringSetting,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int,
|
||||||
|
choices: Array<String?>,
|
||||||
|
values: Array<String?>,
|
||||||
|
noChoicesAvailableString: Int
|
||||||
|
) : this(context, setting, titleId, descriptionId, choices, values) {
|
||||||
|
this.noChoicesAvailableString = noChoicesAvailableString
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
constructor(
|
||||||
|
context: Context,
|
||||||
|
setting: AbstractStringSetting,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int,
|
||||||
|
choicesId: Int,
|
||||||
|
valuesId: Int,
|
||||||
|
menuTag: MenuTag? = null
|
||||||
|
) : super(context, titleId, descriptionId) {
|
||||||
|
stringSetting = setting
|
||||||
|
choices = DolphinApplication.getAppContext().resources.getStringArray(choicesId)
|
||||||
|
values = DolphinApplication.getAppContext().resources.getStringArray(valuesId)
|
||||||
|
this.menuTag = menuTag
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getChoiceAt(index: Int): String? {
|
||||||
|
if (choices == null) return null
|
||||||
|
|
||||||
|
return if (index >= 0 && index < choices!!.size) {
|
||||||
|
choices!![index]
|
||||||
|
} else ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getValueAt(index: Int): String? {
|
||||||
|
if (values == null) return null
|
||||||
|
|
||||||
|
return if (index >= 0 && index < values!!.size) {
|
||||||
|
values!![index]
|
||||||
|
} else ""
|
||||||
|
}
|
||||||
|
|
||||||
|
val selectedValueIndex: Int
|
||||||
|
get() {
|
||||||
|
val selectedValue = selectedValue
|
||||||
|
for (i in values!!.indices) {
|
||||||
|
if (values!![i] == selectedValue) {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun setSelectedValue(settings: Settings?, selection: String?) {
|
||||||
|
stringSetting!!.setString(settings!!, selection!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun refreshChoicesAndValues() {}
|
||||||
|
}
|
|
@ -1,36 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
|
||||||
|
|
||||||
public final class SubmenuSetting extends SettingsItem
|
|
||||||
{
|
|
||||||
private MenuTag mMenuKey;
|
|
||||||
|
|
||||||
public SubmenuSetting(Context context, int titleId, MenuTag menuKey)
|
|
||||||
{
|
|
||||||
super(context, titleId, 0);
|
|
||||||
mMenuKey = menuKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MenuTag getMenuKey()
|
|
||||||
{
|
|
||||||
return mMenuKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return TYPE_SUBMENU;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag
|
||||||
|
|
||||||
|
class SubmenuSetting(
|
||||||
|
context: Context,
|
||||||
|
titleId: Int,
|
||||||
|
val menuKey: MenuTag
|
||||||
|
) : SettingsItem(context, titleId, 0) {
|
||||||
|
override val type: Int = TYPE_SUBMENU
|
||||||
|
|
||||||
|
override val setting: AbstractSetting? = null
|
||||||
|
}
|
|
@ -1,50 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractBooleanSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
|
|
||||||
public class SwitchSetting extends SettingsItem
|
|
||||||
{
|
|
||||||
protected AbstractBooleanSetting mSetting;
|
|
||||||
|
|
||||||
public SwitchSetting(Context context, AbstractBooleanSetting setting, int titleId,
|
|
||||||
int descriptionId)
|
|
||||||
{
|
|
||||||
super(context, titleId, descriptionId);
|
|
||||||
mSetting = setting;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SwitchSetting(AbstractBooleanSetting setting, CharSequence title,
|
|
||||||
CharSequence description)
|
|
||||||
{
|
|
||||||
super(title, description);
|
|
||||||
mSetting = setting;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isChecked()
|
|
||||||
{
|
|
||||||
return mSetting.getBoolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setChecked(Settings settings, boolean checked)
|
|
||||||
{
|
|
||||||
mSetting.setBoolean(settings, checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return TYPE_SWITCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractSetting getSetting()
|
|
||||||
{
|
|
||||||
return mSetting;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.model.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractBooleanSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
|
||||||
|
open class SwitchSetting : SettingsItem {
|
||||||
|
override val type: Int = TYPE_SWITCH
|
||||||
|
|
||||||
|
protected var booleanSetting: AbstractBooleanSetting
|
||||||
|
|
||||||
|
override val setting: AbstractSetting
|
||||||
|
get() = booleanSetting
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
context: Context,
|
||||||
|
setting: AbstractBooleanSetting,
|
||||||
|
titleId: Int,
|
||||||
|
descriptionId: Int
|
||||||
|
) : super(context, titleId, descriptionId) {
|
||||||
|
booleanSetting = setting
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
setting: AbstractBooleanSetting,
|
||||||
|
title: CharSequence?,
|
||||||
|
description: CharSequence?
|
||||||
|
) : super(title!!, description) {
|
||||||
|
booleanSetting = setting
|
||||||
|
}
|
||||||
|
|
||||||
|
open val isChecked: Boolean
|
||||||
|
get() = booleanSetting.boolean
|
||||||
|
|
||||||
|
open fun setChecked(settings: Settings?, checked: Boolean) {
|
||||||
|
booleanSetting.setBoolean(settings!!, checked)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,165 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.input.model.controlleremu.EmulatedController;
|
|
||||||
|
|
||||||
public enum MenuTag
|
|
||||||
{
|
|
||||||
SETTINGS("settings"),
|
|
||||||
CONFIG("config"),
|
|
||||||
CONFIG_GENERAL("config_general"),
|
|
||||||
CONFIG_INTERFACE("config_interface"),
|
|
||||||
CONFIG_AUDIO("config_audio"),
|
|
||||||
CONFIG_PATHS("config_paths"),
|
|
||||||
CONFIG_GAME_CUBE("config_gamecube"),
|
|
||||||
CONFIG_SERIALPORT1("config_serialport1"),
|
|
||||||
CONFIG_WII("config_wii"),
|
|
||||||
CONFIG_ADVANCED("config_advanced"),
|
|
||||||
CONFIG_LOG("config_log"),
|
|
||||||
DEBUG("debug"),
|
|
||||||
GRAPHICS("graphics"),
|
|
||||||
ENHANCEMENTS("enhancements"),
|
|
||||||
STEREOSCOPY("stereoscopy"),
|
|
||||||
HACKS("hacks"),
|
|
||||||
STATISTICS("statistics"),
|
|
||||||
ADVANCED_GRAPHICS("advanced_graphics"),
|
|
||||||
GCPAD_TYPE("gc_pad_type"),
|
|
||||||
WIIMOTE("wiimote"),
|
|
||||||
WIIMOTE_EXTENSION("wiimote_extension"),
|
|
||||||
GCPAD_1("gcpad", 0),
|
|
||||||
GCPAD_2("gcpad", 1),
|
|
||||||
GCPAD_3("gcpad", 2),
|
|
||||||
GCPAD_4("gcpad", 3),
|
|
||||||
WIIMOTE_1("wiimote", 0),
|
|
||||||
WIIMOTE_2("wiimote", 1),
|
|
||||||
WIIMOTE_3("wiimote", 2),
|
|
||||||
WIIMOTE_4("wiimote", 3),
|
|
||||||
WIIMOTE_EXTENSION_1("wiimote_extension", 0),
|
|
||||||
WIIMOTE_EXTENSION_2("wiimote_extension", 1),
|
|
||||||
WIIMOTE_EXTENSION_3("wiimote_extension", 2),
|
|
||||||
WIIMOTE_EXTENSION_4("wiimote_extension", 3),
|
|
||||||
WIIMOTE_GENERAL_1("wiimote_general", 0),
|
|
||||||
WIIMOTE_GENERAL_2("wiimote_general", 1),
|
|
||||||
WIIMOTE_GENERAL_3("wiimote_general", 2),
|
|
||||||
WIIMOTE_GENERAL_4("wiimote_general", 3),
|
|
||||||
WIIMOTE_MOTION_SIMULATION_1("wiimote_motion_simulation", 0),
|
|
||||||
WIIMOTE_MOTION_SIMULATION_2("wiimote_motion_simulation", 1),
|
|
||||||
WIIMOTE_MOTION_SIMULATION_3("wiimote_motion_simulation", 2),
|
|
||||||
WIIMOTE_MOTION_SIMULATION_4("wiimote_motion_simulation", 3),
|
|
||||||
WIIMOTE_MOTION_INPUT_1("wiimote_motion_input", 0),
|
|
||||||
WIIMOTE_MOTION_INPUT_2("wiimote_motion_input", 1),
|
|
||||||
WIIMOTE_MOTION_INPUT_3("wiimote_motion_input", 2),
|
|
||||||
WIIMOTE_MOTION_INPUT_4("wiimote_motion_input", 3);
|
|
||||||
|
|
||||||
private String tag;
|
|
||||||
private int subType = -1;
|
|
||||||
|
|
||||||
MenuTag(String tag)
|
|
||||||
{
|
|
||||||
this.tag = tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuTag(String tag, int subtype)
|
|
||||||
{
|
|
||||||
this.tag = tag;
|
|
||||||
this.subType = subtype;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
if (subType != -1)
|
|
||||||
{
|
|
||||||
return tag + subType;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTag()
|
|
||||||
{
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSubType()
|
|
||||||
{
|
|
||||||
return subType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EmulatedController getCorrespondingEmulatedController()
|
|
||||||
{
|
|
||||||
if (isGCPadMenu())
|
|
||||||
return EmulatedController.getGcPad(getSubType());
|
|
||||||
else if (isWiimoteMenu())
|
|
||||||
return EmulatedController.getWiimote(getSubType());
|
|
||||||
else
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSerialPort1Menu()
|
|
||||||
{
|
|
||||||
return this == CONFIG_SERIALPORT1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isGCPadMenu()
|
|
||||||
{
|
|
||||||
return this == GCPAD_1 || this == GCPAD_2 || this == GCPAD_3 || this == GCPAD_4;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isWiimoteMenu()
|
|
||||||
{
|
|
||||||
return this == WIIMOTE_1 || this == WIIMOTE_2 || this == WIIMOTE_3 || this == WIIMOTE_4;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isWiimoteExtensionMenu()
|
|
||||||
{
|
|
||||||
return this == WIIMOTE_EXTENSION_1 || this == WIIMOTE_EXTENSION_2
|
|
||||||
|| this == WIIMOTE_EXTENSION_3 || this == WIIMOTE_EXTENSION_4;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MenuTag getGCPadMenuTag(int subtype)
|
|
||||||
{
|
|
||||||
return getMenuTag("gcpad", subtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MenuTag getWiimoteMenuTag(int subtype)
|
|
||||||
{
|
|
||||||
return getMenuTag("wiimote", subtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MenuTag getWiimoteExtensionMenuTag(int subtype)
|
|
||||||
{
|
|
||||||
return getMenuTag("wiimote_extension", subtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MenuTag getWiimoteGeneralMenuTag(int subtype)
|
|
||||||
{
|
|
||||||
return getMenuTag("wiimote_general", subtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MenuTag getWiimoteMotionSimulationMenuTag(int subtype)
|
|
||||||
{
|
|
||||||
return getMenuTag("wiimote_motion_simulation", subtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MenuTag getWiimoteMotionInputMenuTag(int subtype)
|
|
||||||
{
|
|
||||||
return getMenuTag("wiimote_motion_input", subtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MenuTag getMenuTag(String tag, int subtype)
|
|
||||||
{
|
|
||||||
for (MenuTag menuTag : MenuTag.values())
|
|
||||||
{
|
|
||||||
if (menuTag.tag.equals(tag) && menuTag.subType == subtype)
|
|
||||||
return menuTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("You are asking for a menu that is not available or " +
|
|
||||||
"passing a wrong subtype");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.features.input.model.controlleremu.EmulatedController
|
||||||
|
|
||||||
|
enum class MenuTag {
|
||||||
|
SETTINGS("settings"),
|
||||||
|
CONFIG("config"),
|
||||||
|
CONFIG_GENERAL("config_general"),
|
||||||
|
CONFIG_INTERFACE("config_interface"),
|
||||||
|
CONFIG_AUDIO("config_audio"),
|
||||||
|
CONFIG_PATHS("config_paths"),
|
||||||
|
CONFIG_GAME_CUBE("config_gamecube"),
|
||||||
|
CONFIG_SERIALPORT1("config_serialport1"),
|
||||||
|
CONFIG_WII("config_wii"),
|
||||||
|
CONFIG_ADVANCED("config_advanced"),
|
||||||
|
CONFIG_LOG("config_log"),
|
||||||
|
DEBUG("debug"),
|
||||||
|
GRAPHICS("graphics"),
|
||||||
|
ENHANCEMENTS("enhancements"),
|
||||||
|
STEREOSCOPY("stereoscopy"),
|
||||||
|
HACKS("hacks"),
|
||||||
|
STATISTICS("statistics"),
|
||||||
|
ADVANCED_GRAPHICS("advanced_graphics"),
|
||||||
|
GCPAD_TYPE("gc_pad_type"),
|
||||||
|
WIIMOTE("wiimote"),
|
||||||
|
WIIMOTE_EXTENSION("wiimote_extension"),
|
||||||
|
GCPAD_1("gcpad", 0),
|
||||||
|
GCPAD_2("gcpad", 1),
|
||||||
|
GCPAD_3("gcpad", 2),
|
||||||
|
GCPAD_4("gcpad", 3),
|
||||||
|
WIIMOTE_1("wiimote", 0),
|
||||||
|
WIIMOTE_2("wiimote", 1),
|
||||||
|
WIIMOTE_3("wiimote", 2),
|
||||||
|
WIIMOTE_4("wiimote", 3),
|
||||||
|
WIIMOTE_EXTENSION_1("wiimote_extension", 0),
|
||||||
|
WIIMOTE_EXTENSION_2("wiimote_extension", 1),
|
||||||
|
WIIMOTE_EXTENSION_3("wiimote_extension", 2),
|
||||||
|
WIIMOTE_EXTENSION_4("wiimote_extension", 3),
|
||||||
|
WIIMOTE_GENERAL_1("wiimote_general", 0),
|
||||||
|
WIIMOTE_GENERAL_2("wiimote_general", 1),
|
||||||
|
WIIMOTE_GENERAL_3("wiimote_general", 2),
|
||||||
|
WIIMOTE_GENERAL_4("wiimote_general", 3),
|
||||||
|
WIIMOTE_MOTION_SIMULATION_1("wiimote_motion_simulation", 0),
|
||||||
|
WIIMOTE_MOTION_SIMULATION_2("wiimote_motion_simulation", 1),
|
||||||
|
WIIMOTE_MOTION_SIMULATION_3("wiimote_motion_simulation", 2),
|
||||||
|
WIIMOTE_MOTION_SIMULATION_4("wiimote_motion_simulation", 3),
|
||||||
|
WIIMOTE_MOTION_INPUT_1("wiimote_motion_input", 0),
|
||||||
|
WIIMOTE_MOTION_INPUT_2("wiimote_motion_input", 1),
|
||||||
|
WIIMOTE_MOTION_INPUT_3("wiimote_motion_input", 2),
|
||||||
|
WIIMOTE_MOTION_INPUT_4("wiimote_motion_input", 3);
|
||||||
|
|
||||||
|
var tag: String
|
||||||
|
private set
|
||||||
|
var subType = -1
|
||||||
|
private set
|
||||||
|
|
||||||
|
constructor(tag: String) {
|
||||||
|
this.tag = tag
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(tag: String, subtype: Int) {
|
||||||
|
this.tag = tag
|
||||||
|
subType = subtype
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return if (subType != -1) {
|
||||||
|
tag + subType
|
||||||
|
} else tag
|
||||||
|
}
|
||||||
|
|
||||||
|
val correspondingEmulatedController: EmulatedController
|
||||||
|
get() = if (isGCPadMenu) EmulatedController.getGcPad(subType) else if (isWiimoteMenu) EmulatedController.getWiimote(
|
||||||
|
subType
|
||||||
|
) else throw UnsupportedOperationException()
|
||||||
|
|
||||||
|
val isSerialPort1Menu: Boolean
|
||||||
|
get() = this == CONFIG_SERIALPORT1
|
||||||
|
|
||||||
|
val isGCPadMenu: Boolean
|
||||||
|
get() = this == GCPAD_1 || this == GCPAD_2 || this == GCPAD_3 || this == GCPAD_4
|
||||||
|
|
||||||
|
val isWiimoteMenu: Boolean
|
||||||
|
get() = this == WIIMOTE_1 || this == WIIMOTE_2 || this == WIIMOTE_3 || this == WIIMOTE_4
|
||||||
|
|
||||||
|
val isWiimoteExtensionMenu: Boolean
|
||||||
|
get() = this == WIIMOTE_EXTENSION_1 || this == WIIMOTE_EXTENSION_2 || this == WIIMOTE_EXTENSION_3 || this == WIIMOTE_EXTENSION_4
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun getGCPadMenuTag(subtype: Int): MenuTag {
|
||||||
|
return getMenuTag("gcpad", subtype)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getWiimoteMenuTag(subtype: Int): MenuTag {
|
||||||
|
return getMenuTag("wiimote", subtype)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getWiimoteExtensionMenuTag(subtype: Int): MenuTag {
|
||||||
|
return getMenuTag("wiimote_extension", subtype)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getWiimoteGeneralMenuTag(subtype: Int): MenuTag {
|
||||||
|
return getMenuTag("wiimote_general", subtype)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getWiimoteMotionSimulationMenuTag(subtype: Int): MenuTag {
|
||||||
|
return getMenuTag("wiimote_motion_simulation", subtype)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getWiimoteMotionInputMenuTag(subtype: Int): MenuTag {
|
||||||
|
return getMenuTag("wiimote_motion_input", subtype)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMenuTag(tag: String, subtype: Int): MenuTag {
|
||||||
|
for (menuTag in values()) {
|
||||||
|
if (menuTag.tag == tag && menuTag.subType == subtype) return menuTag
|
||||||
|
}
|
||||||
|
throw IllegalArgumentException(
|
||||||
|
"You are asking for a menu that is not available or " +
|
||||||
|
"passing a wrong subtype"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,401 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.graphics.Insets;
|
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
import androidx.core.view.WindowCompat;
|
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
|
||||||
import androidx.fragment.app.DialogFragment;
|
|
||||||
import androidx.fragment.app.FragmentTransaction;
|
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
|
|
||||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
|
||||||
import com.google.android.material.color.MaterialColors;
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.ActivitySettingsBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
|
|
||||||
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
|
|
||||||
import org.dolphinemu.dolphinemu.utils.InsetsHelper;
|
|
||||||
import org.dolphinemu.dolphinemu.utils.ThemeHelper;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public final class SettingsActivity extends AppCompatActivity implements SettingsActivityView
|
|
||||||
{
|
|
||||||
private static final String ARG_MENU_TAG = "menu_tag";
|
|
||||||
private static final String ARG_GAME_ID = "game_id";
|
|
||||||
private static final String ARG_REVISION = "revision";
|
|
||||||
private static final String ARG_IS_WII = "is_wii";
|
|
||||||
private static final String KEY_MAPPING_ALL_DEVICES = "all_devices";
|
|
||||||
private static final String FRAGMENT_TAG = "settings";
|
|
||||||
private static final String FRAGMENT_DIALOG_TAG = "settings_dialog";
|
|
||||||
|
|
||||||
private SettingsActivityPresenter mPresenter;
|
|
||||||
private AlertDialog dialog;
|
|
||||||
private CollapsingToolbarLayout mToolbarLayout;
|
|
||||||
|
|
||||||
private ActivitySettingsBinding mBinding;
|
|
||||||
|
|
||||||
private boolean mMappingAllDevices = false;
|
|
||||||
|
|
||||||
public static void launch(Context context, MenuTag menuTag, String gameId, int revision,
|
|
||||||
boolean isWii)
|
|
||||||
{
|
|
||||||
Intent settings = new Intent(context, SettingsActivity.class);
|
|
||||||
settings.putExtra(ARG_MENU_TAG, menuTag);
|
|
||||||
settings.putExtra(ARG_GAME_ID, gameId);
|
|
||||||
settings.putExtra(ARG_REVISION, revision);
|
|
||||||
settings.putExtra(ARG_IS_WII, isWii);
|
|
||||||
context.startActivity(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void launch(Context context, MenuTag menuTag)
|
|
||||||
{
|
|
||||||
Intent settings = new Intent(context, SettingsActivity.class);
|
|
||||||
settings.putExtra(ARG_MENU_TAG, menuTag);
|
|
||||||
settings.putExtra(ARG_IS_WII, !NativeLibrary.IsRunning() || NativeLibrary.IsEmulatingWii());
|
|
||||||
context.startActivity(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
ThemeHelper.setTheme(this);
|
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
// If we came here from the game list, we don't want to rescan when returning to the game list.
|
|
||||||
// But if we came here after UserDataActivity restarted the app, we do want to rescan.
|
|
||||||
if (savedInstanceState == null)
|
|
||||||
{
|
|
||||||
MainPresenter.skipRescanningLibrary();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mMappingAllDevices = savedInstanceState.getBoolean(KEY_MAPPING_ALL_DEVICES);
|
|
||||||
}
|
|
||||||
|
|
||||||
mBinding = ActivitySettingsBinding.inflate(getLayoutInflater());
|
|
||||||
setContentView(mBinding.getRoot());
|
|
||||||
|
|
||||||
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
|
||||||
|
|
||||||
Intent launcher = getIntent();
|
|
||||||
String gameID = launcher.getStringExtra(ARG_GAME_ID);
|
|
||||||
if (gameID == null)
|
|
||||||
gameID = "";
|
|
||||||
int revision = launcher.getIntExtra(ARG_REVISION, 0);
|
|
||||||
boolean isWii = launcher.getBooleanExtra(ARG_IS_WII, true);
|
|
||||||
MenuTag menuTag = (MenuTag) launcher.getSerializableExtra(ARG_MENU_TAG);
|
|
||||||
|
|
||||||
mPresenter = new SettingsActivityPresenter(this, getSettings());
|
|
||||||
mPresenter.onCreate(savedInstanceState, menuTag, gameID, revision, isWii, this);
|
|
||||||
|
|
||||||
mToolbarLayout = mBinding.toolbarSettingsLayout;
|
|
||||||
setSupportActionBar(mBinding.toolbarSettings);
|
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
|
|
||||||
// TODO: Remove this when CollapsingToolbarLayouts are fixed by Google
|
|
||||||
// https://github.com/material-components/material-components-android/issues/1310
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(mToolbarLayout, null);
|
|
||||||
|
|
||||||
setInsets();
|
|
||||||
ThemeHelper.enableScrollTint(this, mBinding.toolbarSettings, mBinding.appbarSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCreateOptionsMenu(Menu menu)
|
|
||||||
{
|
|
||||||
MenuInflater inflater = getMenuInflater();
|
|
||||||
inflater.inflate(R.menu.menu_settings, menu);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSaveInstanceState(@NonNull Bundle outState)
|
|
||||||
{
|
|
||||||
// Critical: If super method is not called, rotations will be busted.
|
|
||||||
super.onSaveInstanceState(outState);
|
|
||||||
|
|
||||||
mPresenter.saveState(outState);
|
|
||||||
|
|
||||||
outState.putBoolean(KEY_MAPPING_ALL_DEVICES, mMappingAllDevices);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStart()
|
|
||||||
{
|
|
||||||
super.onStart();
|
|
||||||
mPresenter.onStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If this is called, the user has left the settings screen (potentially through the
|
|
||||||
* home button) and will expect their changes to be persisted.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void onStop()
|
|
||||||
{
|
|
||||||
super.onStop();
|
|
||||||
mPresenter.onStop(isFinishing());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy()
|
|
||||||
{
|
|
||||||
super.onDestroy();
|
|
||||||
mPresenter.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showSettingsFragment(MenuTag menuTag, Bundle extras, boolean addToStack,
|
|
||||||
String gameID)
|
|
||||||
{
|
|
||||||
if (!addToStack && getFragment() != null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
|
||||||
|
|
||||||
if (addToStack)
|
|
||||||
{
|
|
||||||
if (areSystemAnimationsEnabled())
|
|
||||||
{
|
|
||||||
transaction.setCustomAnimations(
|
|
||||||
R.anim.anim_settings_fragment_in,
|
|
||||||
R.anim.anim_settings_fragment_out,
|
|
||||||
0,
|
|
||||||
R.anim.anim_pop_settings_fragment_out);
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction.addToBackStack(null);
|
|
||||||
}
|
|
||||||
transaction.replace(R.id.frame_content_settings,
|
|
||||||
SettingsFragment.newInstance(menuTag, gameID, extras), FRAGMENT_TAG);
|
|
||||||
|
|
||||||
transaction.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showDialogFragment(DialogFragment fragment)
|
|
||||||
{
|
|
||||||
fragment.show(getSupportFragmentManager(), FRAGMENT_DIALOG_TAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean areSystemAnimationsEnabled()
|
|
||||||
{
|
|
||||||
float duration = Settings.Global.getFloat(
|
|
||||||
getContentResolver(),
|
|
||||||
Settings.Global.ANIMATOR_DURATION_SCALE, 1);
|
|
||||||
float transition = Settings.Global.getFloat(
|
|
||||||
getContentResolver(),
|
|
||||||
Settings.Global.TRANSITION_ANIMATION_SCALE, 1);
|
|
||||||
return duration != 0 && transition != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent result)
|
|
||||||
{
|
|
||||||
super.onActivityResult(requestCode, resultCode, result);
|
|
||||||
|
|
||||||
// If the user picked a file, as opposed to just backing out.
|
|
||||||
if (resultCode == RESULT_OK)
|
|
||||||
{
|
|
||||||
if (requestCode != MainPresenter.REQUEST_DIRECTORY)
|
|
||||||
{
|
|
||||||
Uri uri = canonicalizeIfPossible(result.getData());
|
|
||||||
|
|
||||||
Set<String> validExtensions = requestCode == MainPresenter.REQUEST_GAME_FILE ?
|
|
||||||
FileBrowserHelper.GAME_EXTENSIONS : FileBrowserHelper.RAW_EXTENSION;
|
|
||||||
|
|
||||||
int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
|
||||||
if (requestCode != MainPresenter.REQUEST_GAME_FILE)
|
|
||||||
flags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
|
|
||||||
int takeFlags = flags & result.getFlags();
|
|
||||||
|
|
||||||
FileBrowserHelper.runAfterExtensionCheck(this, uri, validExtensions, () ->
|
|
||||||
{
|
|
||||||
getContentResolver().takePersistableUriPermission(uri, takeFlags);
|
|
||||||
getFragment().getAdapter().onFilePickerConfirmation(uri.toString());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
String path = FileBrowserHelper.getSelectedPath(result);
|
|
||||||
getFragment().getAdapter().onFilePickerConfirmation(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private Uri canonicalizeIfPossible(@NonNull Uri uri)
|
|
||||||
{
|
|
||||||
Uri canonicalizedUri = getContentResolver().canonicalize(uri);
|
|
||||||
return canonicalizedUri != null ? canonicalizedUri : uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showLoading()
|
|
||||||
{
|
|
||||||
if (dialog == null)
|
|
||||||
{
|
|
||||||
dialog = new MaterialAlertDialogBuilder(this)
|
|
||||||
.setTitle(getString(R.string.load_settings))
|
|
||||||
.setView(R.layout.dialog_indeterminate_progress)
|
|
||||||
.create();
|
|
||||||
}
|
|
||||||
dialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void hideLoading()
|
|
||||||
{
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showGameIniJunkDeletionQuestion()
|
|
||||||
{
|
|
||||||
new MaterialAlertDialogBuilder(this)
|
|
||||||
.setTitle(getString(R.string.game_ini_junk_title))
|
|
||||||
.setMessage(getString(R.string.game_ini_junk_question))
|
|
||||||
.setPositiveButton(R.string.yes, (dialogInterface, i) -> mPresenter.clearGameSettings())
|
|
||||||
.setNegativeButton(R.string.no, null)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public org.dolphinemu.dolphinemu.features.settings.model.Settings getSettings()
|
|
||||||
{
|
|
||||||
return new ViewModelProvider(this).get(SettingsViewModel.class).getSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSettingsFileLoaded(
|
|
||||||
org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
|
|
||||||
{
|
|
||||||
SettingsFragmentView fragment = getFragment();
|
|
||||||
|
|
||||||
if (fragment != null)
|
|
||||||
{
|
|
||||||
fragment.onSettingsFileLoaded(settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSettingsFileNotFound()
|
|
||||||
{
|
|
||||||
SettingsFragmentView fragment = getFragment();
|
|
||||||
|
|
||||||
if (fragment != null)
|
|
||||||
{
|
|
||||||
fragment.loadDefaultSettings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showToastMessage(String message)
|
|
||||||
{
|
|
||||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSettingChanged()
|
|
||||||
{
|
|
||||||
mPresenter.onSettingChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onControllerSettingsChanged()
|
|
||||||
{
|
|
||||||
getFragment().onControllerSettingsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMenuTagAction(@NonNull MenuTag menuTag, int value)
|
|
||||||
{
|
|
||||||
mPresenter.onMenuTagAction(menuTag, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasMenuTagActionForValue(@NonNull MenuTag menuTag, int value)
|
|
||||||
{
|
|
||||||
return mPresenter.hasMenuTagActionForValue(menuTag, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onSupportNavigateUp()
|
|
||||||
{
|
|
||||||
onBackPressed();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SettingsFragment getFragment()
|
|
||||||
{
|
|
||||||
return (SettingsFragment) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToolbarTitle(String title)
|
|
||||||
{
|
|
||||||
mBinding.toolbarSettingsLayout.setTitle(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMappingAllDevices(boolean allDevices)
|
|
||||||
{
|
|
||||||
mMappingAllDevices = allDevices;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMappingAllDevices()
|
|
||||||
{
|
|
||||||
return mMappingAllDevices;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int setOldControllerSettingsWarningVisibility(boolean visible)
|
|
||||||
{
|
|
||||||
// We use INVISIBLE instead of GONE to avoid getting a stale height for the return value
|
|
||||||
mBinding.oldControllerSettingsWarning.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
|
|
||||||
return visible ? mBinding.oldControllerSettingsWarning.getHeight() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setInsets()
|
|
||||||
{
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(mBinding.appbarSettings, (v, windowInsets) ->
|
|
||||||
{
|
|
||||||
Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
|
|
||||||
|
|
||||||
InsetsHelper.insetAppBar(insets, mBinding.appbarSettings);
|
|
||||||
|
|
||||||
mBinding.frameContentSettings.setPadding(insets.left, 0, insets.right, 0);
|
|
||||||
|
|
||||||
int textPadding = getResources().getDimensionPixelSize(R.dimen.spacing_large);
|
|
||||||
mBinding.oldControllerSettingsWarning.setPadding(textPadding + insets.left, textPadding,
|
|
||||||
textPadding + insets.right, textPadding + insets.bottom);
|
|
||||||
|
|
||||||
InsetsHelper.applyNavbarWorkaround(insets.bottom, mBinding.workaroundView);
|
|
||||||
ThemeHelper.setNavigationBarColor(this,
|
|
||||||
MaterialColors.getColor(mBinding.appbarSettings, R.attr.colorSurface));
|
|
||||||
|
|
||||||
return windowInsets;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,323 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import com.google.android.material.appbar.CollapsingToolbarLayout
|
||||||
|
import com.google.android.material.color.MaterialColors
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import org.dolphinemu.dolphinemu.NativeLibrary
|
||||||
|
import org.dolphinemu.dolphinemu.R
|
||||||
|
import org.dolphinemu.dolphinemu.databinding.ActivitySettingsBinding
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsFragment.Companion.newInstance
|
||||||
|
import org.dolphinemu.dolphinemu.ui.main.MainPresenter
|
||||||
|
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper
|
||||||
|
import org.dolphinemu.dolphinemu.utils.InsetsHelper
|
||||||
|
import org.dolphinemu.dolphinemu.utils.SerializableHelper.serializable
|
||||||
|
import org.dolphinemu.dolphinemu.utils.ThemeHelper.enableScrollTint
|
||||||
|
import org.dolphinemu.dolphinemu.utils.ThemeHelper.setNavigationBarColor
|
||||||
|
import org.dolphinemu.dolphinemu.utils.ThemeHelper.setTheme
|
||||||
|
|
||||||
|
class SettingsActivity : AppCompatActivity(), SettingsActivityView {
|
||||||
|
private var presenter: SettingsActivityPresenter? = null
|
||||||
|
private var dialog: AlertDialog? = null
|
||||||
|
private var toolbarLayout: CollapsingToolbarLayout? = null
|
||||||
|
private var binding: ActivitySettingsBinding? = null
|
||||||
|
|
||||||
|
override var isMappingAllDevices = false
|
||||||
|
|
||||||
|
override val settings: Settings
|
||||||
|
get() = ViewModelProvider(this)[SettingsViewModel::class.java].settings
|
||||||
|
|
||||||
|
private val fragment: SettingsFragment?
|
||||||
|
get() = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as SettingsFragment?
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
setTheme(this)
|
||||||
|
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
// If we came here from the game list, we don't want to rescan when returning to the game list.
|
||||||
|
// But if we came here after UserDataActivity restarted the app, we do want to rescan.
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
MainPresenter.skipRescanningLibrary()
|
||||||
|
} else {
|
||||||
|
isMappingAllDevices = savedInstanceState.getBoolean(KEY_MAPPING_ALL_DEVICES)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding = ActivitySettingsBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding!!.root)
|
||||||
|
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
|
||||||
|
val launcher = intent
|
||||||
|
var gameID = launcher.getStringExtra(ARG_GAME_ID)
|
||||||
|
if (gameID == null) gameID = ""
|
||||||
|
val revision = launcher.getIntExtra(ARG_REVISION, 0)
|
||||||
|
val isWii = launcher.getBooleanExtra(ARG_IS_WII, true)
|
||||||
|
val menuTag = launcher.serializable<MenuTag>(ARG_MENU_TAG)
|
||||||
|
|
||||||
|
presenter = SettingsActivityPresenter(this, settings)
|
||||||
|
presenter!!.onCreate(savedInstanceState, menuTag, gameID, revision, isWii, this)
|
||||||
|
toolbarLayout = binding!!.toolbarSettingsLayout
|
||||||
|
setSupportActionBar(binding!!.toolbarSettings)
|
||||||
|
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
|
// TODO: Remove this when CollapsingToolbarLayouts are fixed by Google
|
||||||
|
// https://github.com/material-components/material-components-android/issues/1310
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(toolbarLayout!!, null)
|
||||||
|
setInsets()
|
||||||
|
enableScrollTint(this, binding!!.toolbarSettings, binding!!.appbarSettings)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
|
val inflater = menuInflater
|
||||||
|
inflater.inflate(R.menu.menu_settings, menu)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
// Critical: If super method is not called, rotations will be busted.
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
presenter!!.saveState(outState)
|
||||||
|
outState.putBoolean(KEY_MAPPING_ALL_DEVICES, isMappingAllDevices)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
presenter!!.onStart()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is called, the user has left the settings screen (potentially through the
|
||||||
|
* home button) and will expect their changes to be persisted.
|
||||||
|
*/
|
||||||
|
override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
presenter!!.onStop(isFinishing)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
presenter!!.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showSettingsFragment(
|
||||||
|
menuTag: MenuTag,
|
||||||
|
extras: Bundle?,
|
||||||
|
addToStack: Boolean,
|
||||||
|
gameId: String
|
||||||
|
) {
|
||||||
|
if (!addToStack && fragment != null) return
|
||||||
|
val transaction = supportFragmentManager.beginTransaction()
|
||||||
|
if (addToStack) {
|
||||||
|
if (areSystemAnimationsEnabled()) {
|
||||||
|
transaction.setCustomAnimations(
|
||||||
|
R.anim.anim_settings_fragment_in,
|
||||||
|
R.anim.anim_settings_fragment_out,
|
||||||
|
0,
|
||||||
|
R.anim.anim_pop_settings_fragment_out
|
||||||
|
)
|
||||||
|
}
|
||||||
|
transaction.addToBackStack(null)
|
||||||
|
}
|
||||||
|
transaction.replace(
|
||||||
|
R.id.frame_content_settings,
|
||||||
|
newInstance(menuTag, gameId, extras), FRAGMENT_TAG
|
||||||
|
)
|
||||||
|
transaction.commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showDialogFragment(fragment: DialogFragment) {
|
||||||
|
fragment.show(supportFragmentManager, FRAGMENT_DIALOG_TAG)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun areSystemAnimationsEnabled(): Boolean {
|
||||||
|
val duration = android.provider.Settings.Global.getFloat(
|
||||||
|
contentResolver,
|
||||||
|
android.provider.Settings.Global.ANIMATOR_DURATION_SCALE,
|
||||||
|
1f
|
||||||
|
)
|
||||||
|
val transition = android.provider.Settings.Global.getFloat(
|
||||||
|
contentResolver,
|
||||||
|
android.provider.Settings.Global.TRANSITION_ANIMATION_SCALE,
|
||||||
|
1f
|
||||||
|
)
|
||||||
|
return duration != 0f && transition != 0f
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, result)
|
||||||
|
|
||||||
|
// If the user picked a file, as opposed to just backing out.
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
if (requestCode != MainPresenter.REQUEST_DIRECTORY) {
|
||||||
|
val uri = canonicalizeIfPossible(result!!.data!!)
|
||||||
|
val validExtensions: Set<String> =
|
||||||
|
if (requestCode == MainPresenter.REQUEST_GAME_FILE) FileBrowserHelper.GAME_EXTENSIONS else FileBrowserHelper.RAW_EXTENSION
|
||||||
|
var flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
if (requestCode != MainPresenter.REQUEST_GAME_FILE) flags =
|
||||||
|
flags or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
val takeFlags = flags and result.flags
|
||||||
|
FileBrowserHelper.runAfterExtensionCheck(this, uri, validExtensions) {
|
||||||
|
contentResolver.takePersistableUriPermission(uri, takeFlags)
|
||||||
|
fragment!!.adapter!!.onFilePickerConfirmation(uri.toString())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val path = FileBrowserHelper.getSelectedPath(result)
|
||||||
|
fragment!!.adapter!!.onFilePickerConfirmation(path!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun canonicalizeIfPossible(uri: Uri): Uri {
|
||||||
|
val canonicalizedUri = contentResolver.canonicalize(uri)
|
||||||
|
return canonicalizedUri ?: uri
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showLoading() {
|
||||||
|
if (dialog == null) {
|
||||||
|
dialog = MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle(getString(R.string.load_settings))
|
||||||
|
.setView(R.layout.dialog_indeterminate_progress)
|
||||||
|
.create()
|
||||||
|
}
|
||||||
|
dialog!!.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hideLoading() {
|
||||||
|
dialog!!.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showGameIniJunkDeletionQuestion() {
|
||||||
|
MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle(getString(R.string.game_ini_junk_title))
|
||||||
|
.setMessage(getString(R.string.game_ini_junk_question))
|
||||||
|
.setPositiveButton(R.string.yes) { _: DialogInterface?, _: Int -> presenter!!.clearGameSettings() }
|
||||||
|
.setNegativeButton(R.string.no, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSettingsFileLoaded(settings: Settings) {
|
||||||
|
val fragment: SettingsFragmentView? = fragment
|
||||||
|
fragment?.onSettingsFileLoaded(settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSettingsFileNotFound() {
|
||||||
|
val fragment: SettingsFragmentView? = fragment
|
||||||
|
fragment?.loadDefaultSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showToastMessage(message: String) {
|
||||||
|
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSettingChanged() {
|
||||||
|
presenter!!.onSettingChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onControllerSettingsChanged() {
|
||||||
|
fragment!!.onControllerSettingsChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMenuTagAction(menuTag: MenuTag, value: Int) {
|
||||||
|
presenter!!.onMenuTagAction(menuTag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasMenuTagActionForValue(menuTag: MenuTag, value: Int): Boolean {
|
||||||
|
return presenter!!.hasMenuTagActionForValue(menuTag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSupportNavigateUp(): Boolean {
|
||||||
|
onBackPressed()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setToolbarTitle(title: String) {
|
||||||
|
binding!!.toolbarSettingsLayout.title = title
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setOldControllerSettingsWarningVisibility(visible: Boolean): Int {
|
||||||
|
// We use INVISIBLE instead of GONE to avoid getting a stale height for the return value
|
||||||
|
binding!!.oldControllerSettingsWarning.visibility =
|
||||||
|
if (visible) View.VISIBLE else View.INVISIBLE
|
||||||
|
return if (visible) binding!!.oldControllerSettingsWarning.height else 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setInsets() {
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(binding!!.appbarSettings) { _: View?, windowInsets: WindowInsetsCompat ->
|
||||||
|
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||||
|
|
||||||
|
InsetsHelper.insetAppBar(insets, binding!!.appbarSettings)
|
||||||
|
|
||||||
|
binding!!.frameContentSettings.setPadding(insets.left, 0, insets.right, 0)
|
||||||
|
val textPadding = resources.getDimensionPixelSize(R.dimen.spacing_large)
|
||||||
|
binding!!.oldControllerSettingsWarning.setPadding(
|
||||||
|
textPadding + insets.left,
|
||||||
|
textPadding,
|
||||||
|
textPadding + insets.right,
|
||||||
|
textPadding + insets.bottom
|
||||||
|
)
|
||||||
|
|
||||||
|
InsetsHelper.applyNavbarWorkaround(insets.bottom, binding!!.workaroundView)
|
||||||
|
setNavigationBarColor(
|
||||||
|
this,
|
||||||
|
MaterialColors.getColor(binding!!.appbarSettings, R.attr.colorSurface)
|
||||||
|
)
|
||||||
|
|
||||||
|
windowInsets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ARG_MENU_TAG = "menu_tag"
|
||||||
|
private const val ARG_GAME_ID = "game_id"
|
||||||
|
private const val ARG_REVISION = "revision"
|
||||||
|
private const val ARG_IS_WII = "is_wii"
|
||||||
|
private const val KEY_MAPPING_ALL_DEVICES = "all_devices"
|
||||||
|
private const val FRAGMENT_TAG = "settings"
|
||||||
|
private const val FRAGMENT_DIALOG_TAG = "settings_dialog"
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun launch(
|
||||||
|
context: Context,
|
||||||
|
menuTag: MenuTag?,
|
||||||
|
gameId: String?,
|
||||||
|
revision: Int,
|
||||||
|
isWii: Boolean
|
||||||
|
) {
|
||||||
|
val settings = Intent(context, SettingsActivity::class.java)
|
||||||
|
settings.putExtra(ARG_MENU_TAG, menuTag)
|
||||||
|
settings.putExtra(ARG_GAME_ID, gameId)
|
||||||
|
settings.putExtra(ARG_REVISION, revision)
|
||||||
|
settings.putExtra(ARG_IS_WII, isWii)
|
||||||
|
context.startActivity(settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun launch(context: Context, menuTag: MenuTag?) {
|
||||||
|
val settings = Intent(context, SettingsActivity::class.java)
|
||||||
|
settings.putExtra(ARG_MENU_TAG, menuTag)
|
||||||
|
settings.putExtra(
|
||||||
|
ARG_IS_WII,
|
||||||
|
!NativeLibrary.IsRunning() || NativeLibrary.IsEmulatingWii()
|
||||||
|
)
|
||||||
|
context.startActivity(settings)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,197 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.core.app.ComponentActivity;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner;
|
|
||||||
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
|
|
||||||
import org.dolphinemu.dolphinemu.utils.Log;
|
|
||||||
|
|
||||||
public final class SettingsActivityPresenter
|
|
||||||
{
|
|
||||||
private static final String KEY_SHOULD_SAVE = "should_save";
|
|
||||||
|
|
||||||
private SettingsActivityView mView;
|
|
||||||
|
|
||||||
private Settings mSettings;
|
|
||||||
|
|
||||||
private boolean mShouldSave;
|
|
||||||
|
|
||||||
private MenuTag mMenuTag;
|
|
||||||
private String mGameId;
|
|
||||||
private int mRevision;
|
|
||||||
private boolean mIsWii;
|
|
||||||
private ComponentActivity mActivity;
|
|
||||||
|
|
||||||
SettingsActivityPresenter(SettingsActivityView view, Settings settings)
|
|
||||||
{
|
|
||||||
mView = view;
|
|
||||||
mSettings = settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onCreate(Bundle savedInstanceState, MenuTag menuTag, String gameId, int revision,
|
|
||||||
boolean isWii, ComponentActivity activity)
|
|
||||||
{
|
|
||||||
this.mMenuTag = menuTag;
|
|
||||||
this.mGameId = gameId;
|
|
||||||
this.mRevision = revision;
|
|
||||||
this.mIsWii = isWii;
|
|
||||||
this.mActivity = activity;
|
|
||||||
|
|
||||||
mShouldSave = savedInstanceState != null && savedInstanceState.getBoolean(KEY_SHOULD_SAVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDestroy()
|
|
||||||
{
|
|
||||||
if (mSettings != null)
|
|
||||||
{
|
|
||||||
mSettings.close();
|
|
||||||
mSettings = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onStart()
|
|
||||||
{
|
|
||||||
prepareDolphinDirectoriesIfNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadSettingsUI()
|
|
||||||
{
|
|
||||||
mView.hideLoading();
|
|
||||||
|
|
||||||
if (!mSettings.areSettingsLoaded())
|
|
||||||
{
|
|
||||||
if (!TextUtils.isEmpty(mGameId))
|
|
||||||
{
|
|
||||||
mSettings.loadSettings(mGameId, mRevision, mIsWii);
|
|
||||||
|
|
||||||
if (mSettings.gameIniContainsJunk())
|
|
||||||
{
|
|
||||||
mView.showGameIniJunkDeletionQuestion();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mSettings.loadSettings(mIsWii);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mView.showSettingsFragment(mMenuTag, null, false, mGameId);
|
|
||||||
mView.onSettingsFileLoaded(mSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prepareDolphinDirectoriesIfNeeded()
|
|
||||||
{
|
|
||||||
mView.showLoading();
|
|
||||||
|
|
||||||
new AfterDirectoryInitializationRunner().runWithLifecycle(mActivity, this::loadSettingsUI);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Settings getSettings()
|
|
||||||
{
|
|
||||||
return mSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearGameSettings()
|
|
||||||
{
|
|
||||||
mSettings.clearGameSettings();
|
|
||||||
onSettingChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onStop(boolean finishing)
|
|
||||||
{
|
|
||||||
if (mSettings != null && finishing && mShouldSave)
|
|
||||||
{
|
|
||||||
Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...");
|
|
||||||
mSettings.saveSettings(mActivity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSettingChanged()
|
|
||||||
{
|
|
||||||
mShouldSave = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveState(Bundle outState)
|
|
||||||
{
|
|
||||||
outState.putBoolean(KEY_SHOULD_SAVE, mShouldSave);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldSave()
|
|
||||||
{
|
|
||||||
return mShouldSave;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onMenuTagAction(@NonNull MenuTag menuTag, int value)
|
|
||||||
{
|
|
||||||
if (menuTag.isSerialPort1Menu())
|
|
||||||
{
|
|
||||||
if (value != 0 && value != 255) // Not disabled or dummy
|
|
||||||
{
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putInt(SettingsFragmentPresenter.ARG_SERIALPORT1_TYPE, value);
|
|
||||||
mView.showSettingsFragment(menuTag, bundle, true, mGameId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (menuTag.isGCPadMenu())
|
|
||||||
{
|
|
||||||
if (value != 0) // Not disabled
|
|
||||||
{
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value);
|
|
||||||
mView.showSettingsFragment(menuTag, bundle, true, mGameId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (menuTag.isWiimoteMenu())
|
|
||||||
{
|
|
||||||
if (value == 1) // Emulated Wii Remote
|
|
||||||
{
|
|
||||||
mView.showSettingsFragment(menuTag, null, true, mGameId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (menuTag.isWiimoteExtensionMenu())
|
|
||||||
{
|
|
||||||
if (value != 0) // Not disabled
|
|
||||||
{
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value);
|
|
||||||
mView.showSettingsFragment(menuTag, bundle, true, mGameId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasMenuTagActionForValue(@NonNull MenuTag menuTag, int value)
|
|
||||||
{
|
|
||||||
if (menuTag.isSerialPort1Menu())
|
|
||||||
{
|
|
||||||
return (value != 0 && value != 255); // Not disabled or dummy
|
|
||||||
}
|
|
||||||
|
|
||||||
if (menuTag.isGCPadMenu())
|
|
||||||
{
|
|
||||||
return (value != 0); // Not disabled
|
|
||||||
}
|
|
||||||
|
|
||||||
if (menuTag.isWiimoteMenu())
|
|
||||||
{
|
|
||||||
return (value == 1); // Emulated Wii Remote
|
|
||||||
}
|
|
||||||
|
|
||||||
if (menuTag.isWiimoteExtensionMenu())
|
|
||||||
{
|
|
||||||
return (value != 0); // Not disabled
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.text.TextUtils
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner
|
||||||
|
import org.dolphinemu.dolphinemu.utils.Log
|
||||||
|
|
||||||
|
class SettingsActivityPresenter(
|
||||||
|
private val activityView: SettingsActivityView,
|
||||||
|
var settings: Settings?
|
||||||
|
) {
|
||||||
|
private var shouldSave = false
|
||||||
|
private var menuTag: MenuTag? = null
|
||||||
|
private var gameId: String? = null
|
||||||
|
private var revision = 0
|
||||||
|
private var isWii = false
|
||||||
|
private lateinit var activity: AppCompatActivity
|
||||||
|
|
||||||
|
fun onCreate(
|
||||||
|
savedInstanceState: Bundle?,
|
||||||
|
menuTag: MenuTag?,
|
||||||
|
gameId: String?,
|
||||||
|
revision: Int,
|
||||||
|
isWii: Boolean,
|
||||||
|
activity: AppCompatActivity
|
||||||
|
) {
|
||||||
|
this.menuTag = menuTag
|
||||||
|
this.gameId = gameId
|
||||||
|
this.revision = revision
|
||||||
|
this.isWii = isWii
|
||||||
|
this.activity = activity
|
||||||
|
shouldSave = savedInstanceState != null && savedInstanceState.getBoolean(KEY_SHOULD_SAVE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDestroy() {
|
||||||
|
if (settings != null) {
|
||||||
|
settings!!.close()
|
||||||
|
settings = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onStart() {
|
||||||
|
prepareDolphinDirectoriesIfNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadSettingsUI() {
|
||||||
|
activityView.hideLoading()
|
||||||
|
if (!settings!!.areSettingsLoaded()) {
|
||||||
|
if (!TextUtils.isEmpty(gameId)) {
|
||||||
|
settings!!.loadSettings(gameId!!, revision, isWii)
|
||||||
|
if (settings!!.gameIniContainsJunk()) {
|
||||||
|
activityView.showGameIniJunkDeletionQuestion()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
settings!!.loadSettings(isWii)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activityView.showSettingsFragment(menuTag!!, null, false, gameId!!)
|
||||||
|
activityView.onSettingsFileLoaded(settings!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun prepareDolphinDirectoriesIfNeeded() {
|
||||||
|
activityView.showLoading()
|
||||||
|
AfterDirectoryInitializationRunner().runWithLifecycle(activity) { loadSettingsUI() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearGameSettings() {
|
||||||
|
settings!!.clearGameSettings()
|
||||||
|
onSettingChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onStop(finishing: Boolean) {
|
||||||
|
if (settings != null && finishing && shouldSave) {
|
||||||
|
Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...")
|
||||||
|
settings!!.saveSettings(activity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSettingChanged() {
|
||||||
|
shouldSave = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveState(outState: Bundle) {
|
||||||
|
outState.putBoolean(KEY_SHOULD_SAVE, shouldSave)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onMenuTagAction(menuTag: MenuTag, value: Int) {
|
||||||
|
if (menuTag.isSerialPort1Menu) {
|
||||||
|
// Not disabled or dummy
|
||||||
|
if (value != 0 && value != 255) {
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putInt(SettingsFragmentPresenter.ARG_SERIALPORT1_TYPE, value)
|
||||||
|
activityView.showSettingsFragment(menuTag, bundle, true, gameId!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (menuTag.isGCPadMenu) {
|
||||||
|
// Not disabled
|
||||||
|
if (value != 0)
|
||||||
|
{
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value)
|
||||||
|
activityView.showSettingsFragment(menuTag, bundle, true, gameId!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (menuTag.isWiimoteMenu) {
|
||||||
|
// Emulated Wii Remote
|
||||||
|
if (value == 1) {
|
||||||
|
activityView.showSettingsFragment(menuTag, null, true, gameId!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (menuTag.isWiimoteExtensionMenu) {
|
||||||
|
// Not disabled
|
||||||
|
if (value != 0) {
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value)
|
||||||
|
activityView.showSettingsFragment(menuTag, bundle, true, gameId!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasMenuTagActionForValue(menuTag: MenuTag, value: Int): Boolean {
|
||||||
|
if (menuTag.isSerialPort1Menu) {
|
||||||
|
// Not disabled or dummy
|
||||||
|
return value != 0 && value != 255
|
||||||
|
}
|
||||||
|
if (menuTag.isGCPadMenu) {
|
||||||
|
// Not disabled
|
||||||
|
return value != 0
|
||||||
|
}
|
||||||
|
if (menuTag.isWiimoteMenu) {
|
||||||
|
// Emulated Wii Remote
|
||||||
|
return value == 1
|
||||||
|
}
|
||||||
|
return if (menuTag.isWiimoteExtensionMenu) {
|
||||||
|
// Not disabled
|
||||||
|
value != 0
|
||||||
|
} else false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val KEY_SHOULD_SAVE = "should_save"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,137 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.fragment.app.DialogFragment;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstraction for the Activity that manages SettingsFragments.
|
|
||||||
*/
|
|
||||||
public interface SettingsActivityView
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Show a new SettingsFragment.
|
|
||||||
*
|
|
||||||
* @param menuTag Identifier for the settings group that should be displayed.
|
|
||||||
* @param addToStack Whether or not this fragment should replace a previous one.
|
|
||||||
*/
|
|
||||||
void showSettingsFragment(MenuTag menuTag, Bundle extras, boolean addToStack, String gameId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows a DialogFragment.
|
|
||||||
*
|
|
||||||
* Only one can be shown at a time.
|
|
||||||
*/
|
|
||||||
void showDialogFragment(DialogFragment fragment);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
* read operation.
|
|
||||||
*
|
|
||||||
* @return A possibly null HashMap of Settings.
|
|
||||||
*/
|
|
||||||
Settings getSettings();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when an asynchronous load operation completes.
|
|
||||||
*
|
|
||||||
* @param settings The (possibly null) result of the ini load operation.
|
|
||||||
*/
|
|
||||||
void onSettingsFileLoaded(Settings settings);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when an asynchronous load operation fails.
|
|
||||||
*/
|
|
||||||
void onSettingsFileNotFound();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display a popup text message on screen.
|
|
||||||
*
|
|
||||||
* @param message The contents of the onscreen message.
|
|
||||||
*/
|
|
||||||
void showToastMessage(String message);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* End the activity.
|
|
||||||
*/
|
|
||||||
void finish();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by a containing Fragment to tell the Activity that a setting was changed;
|
|
||||||
* unless this has been called, the Activity will not save to disk.
|
|
||||||
*/
|
|
||||||
void onSettingChanged();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Refetches the values of all controller settings.
|
|
||||||
*
|
|
||||||
* To be used when loading an input profile or performing some other action that changes all
|
|
||||||
* controller settings at once.
|
|
||||||
*/
|
|
||||||
void onControllerSettingsChanged();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by a containing Fragment to tell the containing Activity that the user wants to open the
|
|
||||||
* MenuTag associated with a setting.
|
|
||||||
*
|
|
||||||
* @param menuTag The MenuTag of the setting.
|
|
||||||
* @param value The current value of the setting.
|
|
||||||
*/
|
|
||||||
void onMenuTagAction(@NonNull MenuTag menuTag, int value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether anything will happen when the user wants to open the MenuTag associated with a
|
|
||||||
* setting, given the current value of the setting.
|
|
||||||
*
|
|
||||||
* @param menuTag The MenuTag of the setting.
|
|
||||||
* @param value The current value of the setting.
|
|
||||||
*/
|
|
||||||
boolean hasMenuTagActionForValue(@NonNull MenuTag menuTag, int value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show loading dialog while loading the settings
|
|
||||||
*/
|
|
||||||
void showLoading();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hide the loading dialog
|
|
||||||
*/
|
|
||||||
void hideLoading();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tell the user that there is junk in the game INI and ask if they want to delete the whole file.
|
|
||||||
*/
|
|
||||||
void showGameIniJunkDeletionQuestion();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accesses the material toolbar layout and changes the title
|
|
||||||
*/
|
|
||||||
void setToolbarTitle(String title);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the input mapping dialog should detect inputs from all devices,
|
|
||||||
* not just the device configured for the controller.
|
|
||||||
*/
|
|
||||||
void setMappingAllDevices(boolean allDevices);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the input mapping dialog should detect inputs from all devices,
|
|
||||||
* not just the device configured for the controller.
|
|
||||||
*/
|
|
||||||
boolean isMappingAllDevices();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows or hides a warning telling the user that they're using incompatible controller settings.
|
|
||||||
* The warning is hidden by default.
|
|
||||||
*
|
|
||||||
* @param visible Whether the warning should be visible.
|
|
||||||
* @return The height of the warning view, or 0 if the view is now invisible.
|
|
||||||
*/
|
|
||||||
int setOldControllerSettingsWarningVisibility(boolean visible);
|
|
||||||
}
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction for the Activity that manages SettingsFragments.
|
||||||
|
*/
|
||||||
|
interface SettingsActivityView {
|
||||||
|
/**
|
||||||
|
* Show a new SettingsFragment.
|
||||||
|
*
|
||||||
|
* @param menuTag Identifier for the settings group that should be displayed.
|
||||||
|
* @param addToStack Whether or not this fragment should replace a previous one.
|
||||||
|
*/
|
||||||
|
fun showSettingsFragment(
|
||||||
|
menuTag: MenuTag,
|
||||||
|
extras: Bundle?,
|
||||||
|
addToStack: Boolean,
|
||||||
|
gameId: String
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a DialogFragment.
|
||||||
|
*
|
||||||
|
* Only one can be shown at a time.
|
||||||
|
*/
|
||||||
|
fun showDialogFragment(fragment: DialogFragment)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* read operation.
|
||||||
|
*
|
||||||
|
* @return A possibly null HashMap of Settings.
|
||||||
|
*/
|
||||||
|
val settings: Settings
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an asynchronous load operation completes.
|
||||||
|
*
|
||||||
|
* @param settings The (possibly null) result of the ini load operation.
|
||||||
|
*/
|
||||||
|
fun onSettingsFileLoaded(settings: Settings)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an asynchronous load operation fails.
|
||||||
|
*/
|
||||||
|
fun onSettingsFileNotFound()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a popup text message on screen.
|
||||||
|
*
|
||||||
|
* @param message The contents of the onscreen message.
|
||||||
|
*/
|
||||||
|
fun showToastMessage(message: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End the activity.
|
||||||
|
*/
|
||||||
|
fun finish()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by a containing Fragment to tell the Activity that a Setting was changed;
|
||||||
|
* unless this has been called, the Activity will not save to disk.
|
||||||
|
*/
|
||||||
|
fun onSettingChanged()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refetches the values of all controller settings.
|
||||||
|
*
|
||||||
|
* To be used when loading an input profile or performing some other action that changes all
|
||||||
|
* controller settings at once.
|
||||||
|
*/
|
||||||
|
fun onControllerSettingsChanged()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by a containing Fragment to tell the containing Activity that the user wants to open the
|
||||||
|
* MenuTag associated with a Setting.
|
||||||
|
*
|
||||||
|
* @param menuTag The MenuTag of the Setting.
|
||||||
|
* @param value The current value of the Setting.
|
||||||
|
*/
|
||||||
|
fun onMenuTagAction(menuTag: MenuTag, value: Int)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether anything will happen when the user wants to open the MenuTag associated with a
|
||||||
|
* Setting, given the current value of the Setting.
|
||||||
|
*
|
||||||
|
* @param menuTag The MenuTag of the Setting.
|
||||||
|
* @param value The current value of the Setting.
|
||||||
|
*/
|
||||||
|
fun hasMenuTagActionForValue(menuTag: MenuTag, value: Int): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show loading dialog while loading the settings
|
||||||
|
*/
|
||||||
|
fun showLoading()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide the loading dialog
|
||||||
|
*/
|
||||||
|
fun hideLoading()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the user that there is junk in the game INI and ask if they want to delete the whole file.
|
||||||
|
*/
|
||||||
|
fun showGameIniJunkDeletionQuestion()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesses the material toolbar layout and changes the title
|
||||||
|
*/
|
||||||
|
fun setToolbarTitle(title: String)
|
||||||
|
/**
|
||||||
|
* Returns whether the input mapping dialog should detect inputs from all devices,
|
||||||
|
* not just the device configured for the controller.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Sets whether the input mapping dialog should detect inputs from all devices,
|
||||||
|
* not just the device configured for the controller.
|
||||||
|
*/
|
||||||
|
var isMappingAllDevices: Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows or hides a warning telling the user that they're using incompatible controller settings.
|
||||||
|
* The warning is hidden by default.
|
||||||
|
*
|
||||||
|
* @param visible Whether the warning should be visible.
|
||||||
|
* @return The height of the warning view, or 0 if the view is now invisible.
|
||||||
|
*/
|
||||||
|
fun setOldControllerSettingsWarningVisibility(visible: Boolean): Int
|
||||||
|
}
|
|
@ -1,703 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.provider.DocumentsContract;
|
|
||||||
import android.text.format.DateFormat;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.ColorInt;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.google.android.material.color.MaterialColors;
|
|
||||||
import com.google.android.material.datepicker.CalendarConstraints;
|
|
||||||
import com.google.android.material.datepicker.MaterialDatePicker;
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
|
||||||
import com.google.android.material.elevation.ElevationOverlayProvider;
|
|
||||||
import com.google.android.material.slider.Slider;
|
|
||||||
import com.google.android.material.textfield.TextInputEditText;
|
|
||||||
import com.google.android.material.timepicker.MaterialTimePicker;
|
|
||||||
import com.google.android.material.timepicker.TimeFormat;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.DialogAdvancedMappingBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.DialogInputStringBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.DialogSliderBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.ListItemHeaderBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.ListItemMappingBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.ListItemSettingSwitchBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.ListItemSubmenuBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.features.input.ui.AdvancedMappingDialog;
|
|
||||||
import org.dolphinemu.dolphinemu.features.input.ui.MotionAlertDialog;
|
|
||||||
import org.dolphinemu.dolphinemu.features.input.model.view.InputMappingControlSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.input.ui.viewholder.InputMappingControlSettingViewHolder;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.DateTimeChoiceSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SwitchSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.FloatSliderSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.IntSliderSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSettingDynamicDescriptions;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SliderSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.InputStringSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.StringSingleChoiceSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SubmenuSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.DateTimeSettingViewHolder;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.FilePickerViewHolder;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.HeaderHyperLinkViewHolder;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.HeaderViewHolder;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.InputStringSettingViewHolder;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.RunRunnableViewHolder;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SettingViewHolder;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SingleChoiceViewHolder;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SliderViewHolder;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SubmenuViewHolder;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SwitchSettingViewHolder;
|
|
||||||
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
|
|
||||||
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
|
|
||||||
import org.dolphinemu.dolphinemu.utils.Log;
|
|
||||||
import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.RandomAccessFile;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolder>
|
|
||||||
implements DialogInterface.OnClickListener, Slider.OnChangeListener
|
|
||||||
{
|
|
||||||
private final SettingsFragmentView mView;
|
|
||||||
private final Context mContext;
|
|
||||||
private ArrayList<SettingsItem> mSettings;
|
|
||||||
|
|
||||||
private SettingsItem mClickedItem;
|
|
||||||
private int mClickedPosition;
|
|
||||||
private int mSeekbarProgress;
|
|
||||||
|
|
||||||
private AlertDialog mDialog;
|
|
||||||
private TextView mTextSliderValue;
|
|
||||||
|
|
||||||
public SettingsAdapter(SettingsFragmentView view, Context context)
|
|
||||||
{
|
|
||||||
mView = view;
|
|
||||||
mContext = context;
|
|
||||||
mClickedPosition = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public SettingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
|
|
||||||
{
|
|
||||||
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
|
||||||
switch (viewType)
|
|
||||||
{
|
|
||||||
case SettingsItem.TYPE_HEADER:
|
|
||||||
return new HeaderViewHolder(ListItemHeaderBinding.inflate(inflater), this);
|
|
||||||
|
|
||||||
case SettingsItem.TYPE_SWITCH:
|
|
||||||
return new SwitchSettingViewHolder(ListItemSettingSwitchBinding.inflate(inflater),
|
|
||||||
this);
|
|
||||||
|
|
||||||
case SettingsItem.TYPE_STRING_SINGLE_CHOICE:
|
|
||||||
case SettingsItem.TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS:
|
|
||||||
case SettingsItem.TYPE_SINGLE_CHOICE:
|
|
||||||
return new SingleChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this);
|
|
||||||
|
|
||||||
case SettingsItem.TYPE_SLIDER:
|
|
||||||
return new SliderViewHolder(ListItemSettingBinding.inflate(inflater), this, mContext);
|
|
||||||
|
|
||||||
case SettingsItem.TYPE_SUBMENU:
|
|
||||||
return new SubmenuViewHolder(ListItemSubmenuBinding.inflate(inflater), this);
|
|
||||||
|
|
||||||
case SettingsItem.TYPE_INPUT_MAPPING_CONTROL:
|
|
||||||
return new InputMappingControlSettingViewHolder(ListItemMappingBinding.inflate(inflater),
|
|
||||||
this);
|
|
||||||
|
|
||||||
case SettingsItem.TYPE_FILE_PICKER:
|
|
||||||
return new FilePickerViewHolder(ListItemSettingBinding.inflate(inflater), this);
|
|
||||||
|
|
||||||
case SettingsItem.TYPE_RUN_RUNNABLE:
|
|
||||||
return new RunRunnableViewHolder(ListItemSettingBinding.inflate(inflater), this, mContext);
|
|
||||||
|
|
||||||
case SettingsItem.TYPE_STRING:
|
|
||||||
return new InputStringSettingViewHolder(ListItemSettingBinding.inflate(inflater), this);
|
|
||||||
|
|
||||||
case SettingsItem.TYPE_HYPERLINK_HEADER:
|
|
||||||
return new HeaderHyperLinkViewHolder(ListItemHeaderBinding.inflate(inflater), this);
|
|
||||||
|
|
||||||
case SettingsItem.TYPE_DATETIME_CHOICE:
|
|
||||||
return new DateTimeSettingViewHolder(ListItemSettingBinding.inflate(inflater), this);
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Invalid view type: " + viewType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull SettingViewHolder holder, int position)
|
|
||||||
{
|
|
||||||
holder.bind(getItem(position));
|
|
||||||
}
|
|
||||||
|
|
||||||
private SettingsItem getItem(int position)
|
|
||||||
{
|
|
||||||
return mSettings.get(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount()
|
|
||||||
{
|
|
||||||
if (mSettings != null)
|
|
||||||
{
|
|
||||||
return mSettings.size();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemViewType(int position)
|
|
||||||
{
|
|
||||||
return getItem(position).getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Settings getSettings()
|
|
||||||
{
|
|
||||||
return mView.getSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSettings(ArrayList<SettingsItem> settings)
|
|
||||||
{
|
|
||||||
mSettings = settings;
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearSetting(SettingsItem item)
|
|
||||||
{
|
|
||||||
item.clear(getSettings());
|
|
||||||
|
|
||||||
mView.onSettingChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notifyAllSettingsChanged()
|
|
||||||
{
|
|
||||||
notifyItemRangeChanged(0, getItemCount());
|
|
||||||
|
|
||||||
mView.onSettingChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onBooleanClick(SwitchSetting item, boolean checked)
|
|
||||||
{
|
|
||||||
item.setChecked(getSettings(), checked);
|
|
||||||
|
|
||||||
mView.onSettingChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onInputStringClick(InputStringSetting item, int position)
|
|
||||||
{
|
|
||||||
LayoutInflater inflater = LayoutInflater.from(mContext);
|
|
||||||
|
|
||||||
DialogInputStringBinding binding = DialogInputStringBinding.inflate(inflater);
|
|
||||||
TextInputEditText input = binding.input;
|
|
||||||
input.setText(item.getSelectedValue());
|
|
||||||
|
|
||||||
mDialog = new MaterialAlertDialogBuilder(mView.getActivity())
|
|
||||||
.setView(binding.getRoot())
|
|
||||||
.setMessage(item.getDescription())
|
|
||||||
.setPositiveButton(R.string.ok, (dialogInterface, i) ->
|
|
||||||
{
|
|
||||||
String editTextInput = input.getText().toString();
|
|
||||||
|
|
||||||
if (!item.getSelectedValue().equals(editTextInput))
|
|
||||||
{
|
|
||||||
notifyItemChanged(position);
|
|
||||||
mView.onSettingChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
item.setSelectedValue(mView.getSettings(), editTextInput);
|
|
||||||
})
|
|
||||||
.setNegativeButton(R.string.cancel, null)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSingleChoiceClick(SingleChoiceSetting item, int position)
|
|
||||||
{
|
|
||||||
mClickedItem = item;
|
|
||||||
mClickedPosition = position;
|
|
||||||
|
|
||||||
int value = getSelectionForSingleChoiceValue(item);
|
|
||||||
|
|
||||||
mDialog = new MaterialAlertDialogBuilder(mView.getActivity())
|
|
||||||
.setTitle(item.getName())
|
|
||||||
.setSingleChoiceItems(item.getChoicesId(), value, this)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onStringSingleChoiceClick(StringSingleChoiceSetting item, int position)
|
|
||||||
{
|
|
||||||
mClickedItem = item;
|
|
||||||
mClickedPosition = position;
|
|
||||||
|
|
||||||
item.refreshChoicesAndValues();
|
|
||||||
|
|
||||||
String[] choices = item.getChoices();
|
|
||||||
int noChoicesAvailableString = item.getNoChoicesAvailableString();
|
|
||||||
if (noChoicesAvailableString != 0 && choices.length == 0)
|
|
||||||
{
|
|
||||||
mDialog = new MaterialAlertDialogBuilder(mView.getActivity())
|
|
||||||
.setTitle(item.getName())
|
|
||||||
.setMessage(noChoicesAvailableString)
|
|
||||||
.setPositiveButton(R.string.ok, null)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mDialog = new MaterialAlertDialogBuilder(mView.getActivity())
|
|
||||||
.setTitle(item.getName())
|
|
||||||
.setSingleChoiceItems(item.getChoices(), item.getSelectedValueIndex(),
|
|
||||||
this)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSingleChoiceDynamicDescriptionsClick(SingleChoiceSettingDynamicDescriptions item,
|
|
||||||
int position)
|
|
||||||
{
|
|
||||||
mClickedItem = item;
|
|
||||||
mClickedPosition = position;
|
|
||||||
|
|
||||||
int value = getSelectionForSingleChoiceDynamicDescriptionsValue(item);
|
|
||||||
|
|
||||||
mDialog = new MaterialAlertDialogBuilder(mView.getActivity())
|
|
||||||
.setTitle(item.getName())
|
|
||||||
.setSingleChoiceItems(item.getChoicesId(), value, this)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSliderClick(SliderSetting item, int position)
|
|
||||||
{
|
|
||||||
mClickedItem = item;
|
|
||||||
mClickedPosition = position;
|
|
||||||
mSeekbarProgress = item.getSelectedValue();
|
|
||||||
|
|
||||||
LayoutInflater inflater = LayoutInflater.from(mView.getActivity());
|
|
||||||
DialogSliderBinding binding = DialogSliderBinding.inflate(inflater);
|
|
||||||
|
|
||||||
mTextSliderValue = binding.textValue;
|
|
||||||
mTextSliderValue.setText(String.valueOf(mSeekbarProgress));
|
|
||||||
|
|
||||||
binding.textUnits.setText(item.getUnits());
|
|
||||||
|
|
||||||
Slider slider = binding.slider;
|
|
||||||
slider.setValueFrom(item.getMin());
|
|
||||||
slider.setValueTo(item.getMax());
|
|
||||||
slider.setValue(mSeekbarProgress);
|
|
||||||
slider.setStepSize(item.getStepSize());
|
|
||||||
|
|
||||||
slider.addOnChangeListener(this);
|
|
||||||
|
|
||||||
mDialog = new MaterialAlertDialogBuilder(mView.getActivity())
|
|
||||||
.setTitle(item.getName())
|
|
||||||
.setView(binding.getRoot())
|
|
||||||
.setPositiveButton(R.string.ok, this)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSubmenuClick(SubmenuSetting item)
|
|
||||||
{
|
|
||||||
mView.loadSubMenu(item.getMenuKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onInputMappingClick(final InputMappingControlSetting item, final int position)
|
|
||||||
{
|
|
||||||
if (item.getController().getDefaultDevice().isEmpty() && !mView.isMappingAllDevices())
|
|
||||||
{
|
|
||||||
new MaterialAlertDialogBuilder(mView.getActivity())
|
|
||||||
.setMessage(R.string.input_binding_no_device)
|
|
||||||
.setPositiveButton(R.string.ok, this)
|
|
||||||
.show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final MotionAlertDialog dialog = new MotionAlertDialog(mView.getActivity(), item,
|
|
||||||
mView.isMappingAllDevices());
|
|
||||||
|
|
||||||
Drawable background = ContextCompat.getDrawable(mContext, R.drawable.dialog_round);
|
|
||||||
@ColorInt int color = new ElevationOverlayProvider(dialog.getContext()).compositeOverlay(
|
|
||||||
MaterialColors.getColor(dialog.getWindow().getDecorView(), R.attr.colorSurface),
|
|
||||||
dialog.getWindow().getDecorView().getElevation());
|
|
||||||
background.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
|
|
||||||
dialog.getWindow().setBackgroundDrawable(background);
|
|
||||||
|
|
||||||
dialog.setTitle(R.string.input_binding);
|
|
||||||
dialog.setMessage(String.format(mContext.getString(R.string.input_binding_description),
|
|
||||||
item.getName()));
|
|
||||||
dialog.setButton(AlertDialog.BUTTON_NEGATIVE, mContext.getString(R.string.cancel), this);
|
|
||||||
dialog.setButton(AlertDialog.BUTTON_NEUTRAL, mContext.getString(R.string.clear),
|
|
||||||
(dialogInterface, i) -> item.clearValue());
|
|
||||||
dialog.setOnDismissListener(dialog1 ->
|
|
||||||
{
|
|
||||||
notifyItemChanged(position);
|
|
||||||
mView.onSettingChanged();
|
|
||||||
});
|
|
||||||
dialog.setCanceledOnTouchOutside(false);
|
|
||||||
dialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onAdvancedInputMappingClick(final InputMappingControlSetting item, final int position)
|
|
||||||
{
|
|
||||||
LayoutInflater inflater = LayoutInflater.from(mContext);
|
|
||||||
|
|
||||||
DialogAdvancedMappingBinding binding = DialogAdvancedMappingBinding.inflate(inflater);
|
|
||||||
|
|
||||||
final AdvancedMappingDialog dialog = new AdvancedMappingDialog(mContext, binding,
|
|
||||||
item.getControlReference(), item.getController());
|
|
||||||
|
|
||||||
Drawable background = ContextCompat.getDrawable(mContext, R.drawable.dialog_round);
|
|
||||||
@ColorInt int color = new ElevationOverlayProvider(dialog.getContext()).compositeOverlay(
|
|
||||||
MaterialColors.getColor(dialog.getWindow().getDecorView(), R.attr.colorSurface),
|
|
||||||
dialog.getWindow().getDecorView().getElevation());
|
|
||||||
background.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
|
|
||||||
dialog.getWindow().setBackgroundDrawable(background);
|
|
||||||
|
|
||||||
dialog.setTitle(item.isInput() ?
|
|
||||||
R.string.input_configure_input : R.string.input_configure_output);
|
|
||||||
dialog.setView(binding.getRoot());
|
|
||||||
dialog.setButton(AlertDialog.BUTTON_POSITIVE, mContext.getString(R.string.ok),
|
|
||||||
(dialogInterface, i) ->
|
|
||||||
{
|
|
||||||
item.setValue(dialog.getExpression());
|
|
||||||
notifyItemChanged(position);
|
|
||||||
mView.onSettingChanged();
|
|
||||||
});
|
|
||||||
dialog.setButton(AlertDialog.BUTTON_NEGATIVE, mContext.getString(R.string.cancel), this);
|
|
||||||
dialog.setButton(AlertDialog.BUTTON_NEUTRAL, mContext.getString(R.string.clear),
|
|
||||||
(dialogInterface, i) ->
|
|
||||||
{
|
|
||||||
item.clearValue();
|
|
||||||
notifyItemChanged(position);
|
|
||||||
mView.onSettingChanged();
|
|
||||||
});
|
|
||||||
dialog.setCanceledOnTouchOutside(false);
|
|
||||||
dialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onFilePickerDirectoryClick(SettingsItem item, int position)
|
|
||||||
{
|
|
||||||
mClickedItem = item;
|
|
||||||
mClickedPosition = position;
|
|
||||||
|
|
||||||
if (!PermissionsHandler.isExternalStorageLegacy())
|
|
||||||
{
|
|
||||||
new MaterialAlertDialogBuilder(mContext)
|
|
||||||
.setMessage(R.string.path_not_changeable_scoped_storage)
|
|
||||||
.setPositiveButton(R.string.ok, (dialog, i) -> dialog.dismiss())
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FileBrowserHelper.openDirectoryPicker(mView.getActivity(), FileBrowserHelper.GAME_EXTENSIONS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onFilePickerFileClick(SettingsItem item, int position)
|
|
||||||
{
|
|
||||||
mClickedItem = item;
|
|
||||||
mClickedPosition = position;
|
|
||||||
FilePicker filePicker = (FilePicker) item;
|
|
||||||
|
|
||||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
|
||||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
||||||
intent.setType("*/*");
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
|
||||||
{
|
|
||||||
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, filePicker.getSelectedValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
mView.getActivity().startActivityForResult(intent, filePicker.getRequestType());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDateTimeClick(DateTimeChoiceSetting item, int position)
|
|
||||||
{
|
|
||||||
mClickedItem = item;
|
|
||||||
mClickedPosition = position;
|
|
||||||
long storedTime = Long.decode(item.getSelectedValue()) * 1000;
|
|
||||||
|
|
||||||
// Helper to extract hour and minute from epoch time
|
|
||||||
Calendar calendar = Calendar.getInstance();
|
|
||||||
calendar.setTimeInMillis(storedTime);
|
|
||||||
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
|
|
||||||
|
|
||||||
// Start and end epoch times available for the Wii's date picker
|
|
||||||
CalendarConstraints calendarConstraints = new CalendarConstraints.Builder()
|
|
||||||
.setStart(946684800000L)
|
|
||||||
.setEnd(2082672000000L)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
int timeFormat = TimeFormat.CLOCK_12H;
|
|
||||||
if (DateFormat.is24HourFormat(mView.getActivity()))
|
|
||||||
{
|
|
||||||
timeFormat = TimeFormat.CLOCK_24H;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialDatePicker<Long> datePicker = MaterialDatePicker.Builder.datePicker()
|
|
||||||
.setSelection(storedTime)
|
|
||||||
.setTitleText(R.string.select_rtc_date)
|
|
||||||
.setCalendarConstraints(calendarConstraints)
|
|
||||||
.build();
|
|
||||||
MaterialTimePicker timePicker = new MaterialTimePicker.Builder()
|
|
||||||
.setTimeFormat(timeFormat)
|
|
||||||
.setHour(calendar.get(Calendar.HOUR_OF_DAY))
|
|
||||||
.setMinute(calendar.get(Calendar.MINUTE))
|
|
||||||
.setTitleText(R.string.select_rtc_time)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
datePicker.addOnPositiveButtonClickListener(
|
|
||||||
selection -> timePicker.show(mView.getActivity().getSupportFragmentManager(),
|
|
||||||
"TimePicker"));
|
|
||||||
timePicker.addOnPositiveButtonClickListener(selection ->
|
|
||||||
{
|
|
||||||
long epochTime = datePicker.getSelection() / 1000;
|
|
||||||
epochTime += (long) timePicker.getHour() * 60 * 60;
|
|
||||||
epochTime += (long) timePicker.getMinute() * 60;
|
|
||||||
String rtcString = "0x" + Long.toHexString(epochTime);
|
|
||||||
if (!item.getSelectedValue().equals(rtcString))
|
|
||||||
{
|
|
||||||
notifyItemChanged(mClickedPosition);
|
|
||||||
mView.onSettingChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
item.setSelectedValue(mView.getSettings(), rtcString);
|
|
||||||
|
|
||||||
mClickedItem = null;
|
|
||||||
});
|
|
||||||
datePicker.show(mView.getActivity().getSupportFragmentManager(), "DatePicker");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onFilePickerConfirmation(String selectedFile)
|
|
||||||
{
|
|
||||||
FilePicker filePicker = (FilePicker) mClickedItem;
|
|
||||||
|
|
||||||
if (!filePicker.getSelectedValue().equals(selectedFile))
|
|
||||||
{
|
|
||||||
notifyItemChanged(mClickedPosition);
|
|
||||||
mView.onSettingChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
filePicker.setSelectedValue(mView.getSettings(), selectedFile);
|
|
||||||
|
|
||||||
mClickedItem = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void clearLog()
|
|
||||||
{
|
|
||||||
// Don't delete the log in case it is being monitored by another app.
|
|
||||||
File log = new File(DirectoryInitialization.getUserDirectory() + "/Logs/dolphin.log");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
RandomAccessFile raf = new RandomAccessFile(log, "rw");
|
|
||||||
raf.setLength(0);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
Log.error("[SettingsAdapter] Failed to clear log file: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onMenuTagAction(@NonNull MenuTag menuTag, int value)
|
|
||||||
{
|
|
||||||
mView.onMenuTagAction(menuTag, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasMenuTagActionForValue(@NonNull MenuTag menuTag, int value)
|
|
||||||
{
|
|
||||||
return mView.hasMenuTagActionForValue(menuTag, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which)
|
|
||||||
{
|
|
||||||
if (mClickedItem instanceof SingleChoiceSetting)
|
|
||||||
{
|
|
||||||
SingleChoiceSetting scSetting = (SingleChoiceSetting) mClickedItem;
|
|
||||||
|
|
||||||
int value = getValueForSingleChoiceSelection(scSetting, which);
|
|
||||||
if (scSetting.getSelectedValue() != value)
|
|
||||||
mView.onSettingChanged();
|
|
||||||
|
|
||||||
scSetting.setSelectedValue(getSettings(), value);
|
|
||||||
|
|
||||||
closeDialog();
|
|
||||||
}
|
|
||||||
else if (mClickedItem instanceof SingleChoiceSettingDynamicDescriptions)
|
|
||||||
{
|
|
||||||
SingleChoiceSettingDynamicDescriptions scSetting =
|
|
||||||
(SingleChoiceSettingDynamicDescriptions) mClickedItem;
|
|
||||||
|
|
||||||
int value = getValueForSingleChoiceDynamicDescriptionsSelection(scSetting, which);
|
|
||||||
if (scSetting.getSelectedValue() != value)
|
|
||||||
mView.onSettingChanged();
|
|
||||||
|
|
||||||
scSetting.setSelectedValue(getSettings(), value);
|
|
||||||
|
|
||||||
closeDialog();
|
|
||||||
}
|
|
||||||
else if (mClickedItem instanceof StringSingleChoiceSetting)
|
|
||||||
{
|
|
||||||
StringSingleChoiceSetting scSetting = (StringSingleChoiceSetting) mClickedItem;
|
|
||||||
String value = scSetting.getValueAt(which);
|
|
||||||
if (!scSetting.getSelectedValue().equals(value))
|
|
||||||
mView.onSettingChanged();
|
|
||||||
|
|
||||||
scSetting.setSelectedValue(getSettings(), value);
|
|
||||||
|
|
||||||
closeDialog();
|
|
||||||
}
|
|
||||||
else if (mClickedItem instanceof IntSliderSetting)
|
|
||||||
{
|
|
||||||
IntSliderSetting sliderSetting = (IntSliderSetting) mClickedItem;
|
|
||||||
if (sliderSetting.getSelectedValue() != mSeekbarProgress)
|
|
||||||
mView.onSettingChanged();
|
|
||||||
|
|
||||||
sliderSetting.setSelectedValue(getSettings(), mSeekbarProgress);
|
|
||||||
|
|
||||||
closeDialog();
|
|
||||||
}
|
|
||||||
else if (mClickedItem instanceof FloatSliderSetting)
|
|
||||||
{
|
|
||||||
FloatSliderSetting sliderSetting = (FloatSliderSetting) mClickedItem;
|
|
||||||
if (sliderSetting.getSelectedValue() != mSeekbarProgress)
|
|
||||||
mView.onSettingChanged();
|
|
||||||
|
|
||||||
sliderSetting.setSelectedValue(getSettings(), mSeekbarProgress);
|
|
||||||
|
|
||||||
closeDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
mClickedItem = null;
|
|
||||||
mSeekbarProgress = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void closeDialog()
|
|
||||||
{
|
|
||||||
if (mDialog != null)
|
|
||||||
{
|
|
||||||
if (mClickedPosition != -1)
|
|
||||||
{
|
|
||||||
notifyItemChanged(mClickedPosition);
|
|
||||||
mClickedPosition = -1;
|
|
||||||
}
|
|
||||||
mDialog.dismiss();
|
|
||||||
mDialog = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onValueChange(@NonNull Slider slider, float progress, boolean fromUser)
|
|
||||||
{
|
|
||||||
mSeekbarProgress = (int) progress;
|
|
||||||
mTextSliderValue.setText(String.valueOf(mSeekbarProgress));
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getValueForSingleChoiceSelection(SingleChoiceSetting item, int which)
|
|
||||||
{
|
|
||||||
int valuesId = item.getValuesId();
|
|
||||||
|
|
||||||
if (valuesId > 0)
|
|
||||||
{
|
|
||||||
int[] valuesArray = mContext.getResources().getIntArray(valuesId);
|
|
||||||
return valuesArray[which];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return which;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getSelectionForSingleChoiceValue(SingleChoiceSetting item)
|
|
||||||
{
|
|
||||||
int value = item.getSelectedValue();
|
|
||||||
int valuesId = item.getValuesId();
|
|
||||||
|
|
||||||
if (valuesId > 0)
|
|
||||||
{
|
|
||||||
int[] valuesArray = mContext.getResources().getIntArray(valuesId);
|
|
||||||
for (int index = 0; index < valuesArray.length; index++)
|
|
||||||
{
|
|
||||||
int current = valuesArray[index];
|
|
||||||
if (current == value)
|
|
||||||
{
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getValueForSingleChoiceDynamicDescriptionsSelection(
|
|
||||||
SingleChoiceSettingDynamicDescriptions item, int which)
|
|
||||||
{
|
|
||||||
int valuesId = item.getValuesId();
|
|
||||||
|
|
||||||
if (valuesId > 0)
|
|
||||||
{
|
|
||||||
int[] valuesArray = mContext.getResources().getIntArray(valuesId);
|
|
||||||
return valuesArray[which];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return which;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getSelectionForSingleChoiceDynamicDescriptionsValue(
|
|
||||||
SingleChoiceSettingDynamicDescriptions item)
|
|
||||||
{
|
|
||||||
int value = item.getSelectedValue();
|
|
||||||
int valuesId = item.getValuesId();
|
|
||||||
|
|
||||||
if (valuesId > 0)
|
|
||||||
{
|
|
||||||
int[] valuesArray = mContext.getResources().getIntArray(valuesId);
|
|
||||||
for (int index = 0; index < valuesArray.length; index++)
|
|
||||||
{
|
|
||||||
int current = valuesArray[index];
|
|
||||||
if (current == value)
|
|
||||||
{
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,590 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.PorterDuff
|
||||||
|
import android.os.Build
|
||||||
|
import android.provider.DocumentsContract
|
||||||
|
import android.text.format.DateFormat
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.ColorInt
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.google.android.material.color.MaterialColors
|
||||||
|
import com.google.android.material.datepicker.CalendarConstraints
|
||||||
|
import com.google.android.material.datepicker.MaterialDatePicker
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.google.android.material.elevation.ElevationOverlayProvider
|
||||||
|
import com.google.android.material.slider.Slider
|
||||||
|
import com.google.android.material.timepicker.MaterialTimePicker
|
||||||
|
import com.google.android.material.timepicker.TimeFormat
|
||||||
|
import org.dolphinemu.dolphinemu.R
|
||||||
|
import org.dolphinemu.dolphinemu.databinding.*
|
||||||
|
import org.dolphinemu.dolphinemu.features.input.model.view.InputMappingControlSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.input.ui.AdvancedMappingDialog
|
||||||
|
import org.dolphinemu.dolphinemu.features.input.ui.MotionAlertDialog
|
||||||
|
import org.dolphinemu.dolphinemu.features.input.ui.viewholder.InputMappingControlSettingViewHolder
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.view.*
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.*
|
||||||
|
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization
|
||||||
|
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper
|
||||||
|
import org.dolphinemu.dolphinemu.utils.Log
|
||||||
|
import org.dolphinemu.dolphinemu.utils.PermissionsHandler
|
||||||
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.RandomAccessFile
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class SettingsAdapter(
|
||||||
|
private val fragmentView: SettingsFragmentView,
|
||||||
|
private val context: Context
|
||||||
|
) :
|
||||||
|
RecyclerView.Adapter<SettingViewHolder>(), DialogInterface.OnClickListener,
|
||||||
|
Slider.OnChangeListener {
|
||||||
|
private var settingsList: ArrayList<SettingsItem>? = null
|
||||||
|
private var clickedItem: SettingsItem? = null
|
||||||
|
private var clickedPosition: Int = -1
|
||||||
|
private var seekbarProgress = 0
|
||||||
|
private var dialog: AlertDialog? = null
|
||||||
|
private var textSliderValue: TextView? = null
|
||||||
|
|
||||||
|
val settings: Settings?
|
||||||
|
get() = fragmentView.settings
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SettingViewHolder {
|
||||||
|
val inflater = LayoutInflater.from(parent.context)
|
||||||
|
return when (viewType) {
|
||||||
|
SettingsItem.TYPE_HEADER -> HeaderViewHolder(
|
||||||
|
ListItemHeaderBinding.inflate(inflater),
|
||||||
|
this
|
||||||
|
)
|
||||||
|
SettingsItem.TYPE_SWITCH -> SwitchSettingViewHolder(
|
||||||
|
ListItemSettingSwitchBinding.inflate(inflater),
|
||||||
|
this
|
||||||
|
)
|
||||||
|
SettingsItem.TYPE_STRING_SINGLE_CHOICE,
|
||||||
|
SettingsItem.TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS,
|
||||||
|
SettingsItem.TYPE_SINGLE_CHOICE -> SingleChoiceViewHolder(
|
||||||
|
ListItemSettingBinding.inflate(inflater),
|
||||||
|
this
|
||||||
|
)
|
||||||
|
SettingsItem.TYPE_SLIDER -> SliderViewHolder(
|
||||||
|
ListItemSettingBinding.inflate(
|
||||||
|
inflater
|
||||||
|
), this, context
|
||||||
|
)
|
||||||
|
SettingsItem.TYPE_SUBMENU -> SubmenuViewHolder(
|
||||||
|
ListItemSubmenuBinding.inflate(
|
||||||
|
inflater
|
||||||
|
), this
|
||||||
|
)
|
||||||
|
SettingsItem.TYPE_INPUT_MAPPING_CONTROL -> InputMappingControlSettingViewHolder(
|
||||||
|
ListItemMappingBinding.inflate(inflater),
|
||||||
|
this
|
||||||
|
)
|
||||||
|
SettingsItem.TYPE_FILE_PICKER -> FilePickerViewHolder(
|
||||||
|
ListItemSettingBinding.inflate(
|
||||||
|
inflater
|
||||||
|
), this
|
||||||
|
)
|
||||||
|
SettingsItem.TYPE_RUN_RUNNABLE -> RunRunnableViewHolder(
|
||||||
|
ListItemSettingBinding.inflate(
|
||||||
|
inflater
|
||||||
|
), this, context
|
||||||
|
)
|
||||||
|
SettingsItem.TYPE_STRING -> InputStringSettingViewHolder(
|
||||||
|
ListItemSettingBinding.inflate(
|
||||||
|
inflater
|
||||||
|
), this
|
||||||
|
)
|
||||||
|
SettingsItem.TYPE_HYPERLINK_HEADER -> HeaderHyperLinkViewHolder(
|
||||||
|
ListItemHeaderBinding.inflate(
|
||||||
|
inflater
|
||||||
|
), this
|
||||||
|
)
|
||||||
|
SettingsItem.TYPE_DATETIME_CHOICE -> DateTimeSettingViewHolder(
|
||||||
|
ListItemSettingBinding.inflate(
|
||||||
|
inflater
|
||||||
|
), this
|
||||||
|
)
|
||||||
|
else -> throw IllegalArgumentException("Invalid view type: $viewType")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: SettingViewHolder, position: Int) {
|
||||||
|
holder.bind(getItem(position))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getItem(position: Int): SettingsItem {
|
||||||
|
return settingsList!![position]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return if (settingsList != null) {
|
||||||
|
settingsList!!.size
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int {
|
||||||
|
return getItem(position).type
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSettings(settings: ArrayList<SettingsItem>?) {
|
||||||
|
settingsList = settings
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearSetting(item: SettingsItem) {
|
||||||
|
item.clear(settings!!)
|
||||||
|
fragmentView.onSettingChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun notifyAllSettingsChanged() {
|
||||||
|
notifyItemRangeChanged(0, itemCount)
|
||||||
|
fragmentView.onSettingChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onBooleanClick(item: SwitchSetting, checked: Boolean) {
|
||||||
|
item.setChecked(settings, checked)
|
||||||
|
fragmentView.onSettingChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onInputStringClick(item: InputStringSetting, position: Int) {
|
||||||
|
val inflater = LayoutInflater.from(context)
|
||||||
|
val binding = DialogInputStringBinding.inflate(inflater)
|
||||||
|
val input = binding.input
|
||||||
|
input.setText(item.selectedValue)
|
||||||
|
dialog = MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
|
||||||
|
.setView(binding.root)
|
||||||
|
.setMessage(item.description)
|
||||||
|
.setPositiveButton(R.string.ok) { _: DialogInterface?, _: Int ->
|
||||||
|
val editTextInput = input.text.toString()
|
||||||
|
if (item.selectedValue != editTextInput) {
|
||||||
|
notifyItemChanged(position)
|
||||||
|
fragmentView.onSettingChanged()
|
||||||
|
}
|
||||||
|
item.setSelectedValue(fragmentView.settings!!, editTextInput)
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSingleChoiceClick(item: SingleChoiceSetting, position: Int) {
|
||||||
|
clickedItem = item
|
||||||
|
clickedPosition = position
|
||||||
|
val value = getSelectionForSingleChoiceValue(item)
|
||||||
|
dialog = MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
|
||||||
|
.setTitle(item.name)
|
||||||
|
.setSingleChoiceItems(item.choicesId, value, this)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onStringSingleChoiceClick(item: StringSingleChoiceSetting, position: Int) {
|
||||||
|
clickedItem = item
|
||||||
|
clickedPosition = position
|
||||||
|
item.refreshChoicesAndValues()
|
||||||
|
val choices = item.choices
|
||||||
|
val noChoicesAvailableString = item.noChoicesAvailableString
|
||||||
|
dialog = if (noChoicesAvailableString != 0 && choices!!.isEmpty()) {
|
||||||
|
MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
|
||||||
|
.setTitle(item.name)
|
||||||
|
.setMessage(noChoicesAvailableString)
|
||||||
|
.setPositiveButton(R.string.ok, null)
|
||||||
|
.show()
|
||||||
|
} else {
|
||||||
|
MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
|
||||||
|
.setTitle(item.name)
|
||||||
|
.setSingleChoiceItems(
|
||||||
|
item.choices, item.selectedValueIndex,
|
||||||
|
this
|
||||||
|
)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSingleChoiceDynamicDescriptionsClick(
|
||||||
|
item: SingleChoiceSettingDynamicDescriptions,
|
||||||
|
position: Int
|
||||||
|
) {
|
||||||
|
clickedItem = item
|
||||||
|
clickedPosition = position
|
||||||
|
|
||||||
|
val value = getSelectionForSingleChoiceDynamicDescriptionsValue(item)
|
||||||
|
|
||||||
|
dialog = MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
|
||||||
|
.setTitle(item.name)
|
||||||
|
.setSingleChoiceItems(item.choicesId, value, this)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSliderClick(item: SliderSetting, position: Int) {
|
||||||
|
clickedItem = item
|
||||||
|
clickedPosition = position
|
||||||
|
seekbarProgress = item.selectedValue
|
||||||
|
|
||||||
|
val inflater = LayoutInflater.from(fragmentView.fragmentActivity)
|
||||||
|
val binding = DialogSliderBinding.inflate(inflater)
|
||||||
|
|
||||||
|
textSliderValue = binding.textValue
|
||||||
|
textSliderValue!!.text = seekbarProgress.toString()
|
||||||
|
|
||||||
|
binding.textUnits.text = item.units
|
||||||
|
|
||||||
|
val slider = binding.slider
|
||||||
|
slider.valueFrom = item.min.toFloat()
|
||||||
|
slider.valueTo = item.max.toFloat()
|
||||||
|
slider.value = seekbarProgress.toFloat()
|
||||||
|
slider.stepSize = item.stepSize.toFloat()
|
||||||
|
slider.addOnChangeListener(this)
|
||||||
|
|
||||||
|
dialog = MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
|
||||||
|
.setTitle(item.name)
|
||||||
|
.setView(binding.root)
|
||||||
|
.setPositiveButton(R.string.ok, this)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSubmenuClick(item: SubmenuSetting) {
|
||||||
|
fragmentView.loadSubMenu(item.menuKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onInputMappingClick(item: InputMappingControlSetting, position: Int) {
|
||||||
|
if (item.controller.defaultDevice.isEmpty() && !fragmentView.isMappingAllDevices) {
|
||||||
|
MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
|
||||||
|
.setMessage(R.string.input_binding_no_device)
|
||||||
|
.setPositiveButton(R.string.ok, this)
|
||||||
|
.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val dialog = MotionAlertDialog(
|
||||||
|
fragmentView.fragmentActivity, item,
|
||||||
|
fragmentView.isMappingAllDevices
|
||||||
|
)
|
||||||
|
|
||||||
|
val background = ContextCompat.getDrawable(context, R.drawable.dialog_round)
|
||||||
|
@ColorInt val color = ElevationOverlayProvider(dialog.context).compositeOverlay(
|
||||||
|
MaterialColors.getColor(dialog.window!!.decorView, R.attr.colorSurface),
|
||||||
|
dialog.window!!.decorView.elevation
|
||||||
|
)
|
||||||
|
background!!.setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
|
||||||
|
dialog.window!!.setBackgroundDrawable(background)
|
||||||
|
|
||||||
|
dialog.setTitle(R.string.input_binding)
|
||||||
|
dialog.setMessage(
|
||||||
|
String.format(
|
||||||
|
context.getString(R.string.input_binding_description),
|
||||||
|
item.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
dialog.setButton(AlertDialog.BUTTON_NEGATIVE, context.getString(R.string.cancel), this)
|
||||||
|
dialog.setButton(
|
||||||
|
AlertDialog.BUTTON_NEUTRAL,
|
||||||
|
context.getString(R.string.clear)
|
||||||
|
) { _: DialogInterface?, _: Int -> item.clearValue() }
|
||||||
|
dialog.setOnDismissListener {
|
||||||
|
notifyItemChanged(position)
|
||||||
|
fragmentView.onSettingChanged()
|
||||||
|
}
|
||||||
|
dialog.setCanceledOnTouchOutside(false)
|
||||||
|
dialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onAdvancedInputMappingClick(item: InputMappingControlSetting, position: Int) {
|
||||||
|
val inflater = LayoutInflater.from(context)
|
||||||
|
val binding = DialogAdvancedMappingBinding.inflate(inflater)
|
||||||
|
val dialog = AdvancedMappingDialog(
|
||||||
|
context,
|
||||||
|
binding,
|
||||||
|
item.controlReference,
|
||||||
|
item.controller
|
||||||
|
)
|
||||||
|
|
||||||
|
val background = ContextCompat.getDrawable(context, R.drawable.dialog_round)
|
||||||
|
@ColorInt val color = ElevationOverlayProvider(dialog.context).compositeOverlay(
|
||||||
|
MaterialColors.getColor(dialog.window!!.decorView, R.attr.colorSurface),
|
||||||
|
dialog.window!!.decorView.elevation
|
||||||
|
)
|
||||||
|
background!!.setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
|
||||||
|
dialog.window!!.setBackgroundDrawable(background)
|
||||||
|
|
||||||
|
dialog.setTitle(if (item.isInput) R.string.input_configure_input else R.string.input_configure_output)
|
||||||
|
dialog.setView(binding.root)
|
||||||
|
dialog.setButton(
|
||||||
|
AlertDialog.BUTTON_POSITIVE, context.getString(R.string.ok)
|
||||||
|
) { _: DialogInterface?, _: Int ->
|
||||||
|
item.value = dialog.expression
|
||||||
|
notifyItemChanged(position)
|
||||||
|
fragmentView.onSettingChanged()
|
||||||
|
}
|
||||||
|
dialog.setButton(AlertDialog.BUTTON_NEGATIVE, context.getString(R.string.cancel), this)
|
||||||
|
dialog.setButton(
|
||||||
|
AlertDialog.BUTTON_NEUTRAL,
|
||||||
|
context.getString(R.string.clear)
|
||||||
|
) { _: DialogInterface?, _: Int ->
|
||||||
|
item.clearValue()
|
||||||
|
notifyItemChanged(position)
|
||||||
|
fragmentView.onSettingChanged()
|
||||||
|
}
|
||||||
|
dialog.setCanceledOnTouchOutside(false)
|
||||||
|
dialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onFilePickerDirectoryClick(item: SettingsItem?, position: Int) {
|
||||||
|
clickedItem = item
|
||||||
|
clickedPosition = position
|
||||||
|
|
||||||
|
if (!PermissionsHandler.isExternalStorageLegacy()) {
|
||||||
|
MaterialAlertDialogBuilder(context)
|
||||||
|
.setMessage(R.string.path_not_changeable_scoped_storage)
|
||||||
|
.setPositiveButton(R.string.ok) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
|
||||||
|
.show()
|
||||||
|
} else {
|
||||||
|
FileBrowserHelper.openDirectoryPicker(
|
||||||
|
fragmentView.fragmentActivity,
|
||||||
|
FileBrowserHelper.GAME_EXTENSIONS
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onFilePickerFileClick(item: SettingsItem, position: Int) {
|
||||||
|
clickedItem = item
|
||||||
|
clickedPosition = position
|
||||||
|
val filePicker = item as FilePicker
|
||||||
|
|
||||||
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
|
||||||
|
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
intent.type = "*/*"
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, filePicker.getSelectedValue())
|
||||||
|
}
|
||||||
|
|
||||||
|
fragmentView.fragmentActivity.startActivityForResult(intent, filePicker.requestType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDateTimeClick(item: DateTimeChoiceSetting, position: Int) {
|
||||||
|
clickedItem = item
|
||||||
|
clickedPosition = position
|
||||||
|
val storedTime = java.lang.Long.decode(item.getSelectedValue()) * 1000
|
||||||
|
|
||||||
|
// Helper to extract hour and minute from epoch time
|
||||||
|
val calendar = Calendar.getInstance()
|
||||||
|
calendar.timeInMillis = storedTime
|
||||||
|
calendar.timeZone = TimeZone.getTimeZone("UTC")
|
||||||
|
|
||||||
|
// Start and end epoch times available for the Wii's date picker
|
||||||
|
val calendarConstraints = CalendarConstraints.Builder()
|
||||||
|
.setStart(946684800000L)
|
||||||
|
.setEnd(2082672000000L)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
var timeFormat = TimeFormat.CLOCK_12H
|
||||||
|
if (DateFormat.is24HourFormat(fragmentView.fragmentActivity)) {
|
||||||
|
timeFormat = TimeFormat.CLOCK_24H
|
||||||
|
}
|
||||||
|
|
||||||
|
val datePicker = MaterialDatePicker.Builder.datePicker()
|
||||||
|
.setSelection(storedTime)
|
||||||
|
.setTitleText(R.string.select_rtc_date)
|
||||||
|
.setCalendarConstraints(calendarConstraints)
|
||||||
|
.build()
|
||||||
|
val timePicker = MaterialTimePicker.Builder()
|
||||||
|
.setTimeFormat(timeFormat)
|
||||||
|
.setHour(calendar[Calendar.HOUR_OF_DAY])
|
||||||
|
.setMinute(calendar[Calendar.MINUTE])
|
||||||
|
.setTitleText(R.string.select_rtc_time)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
datePicker.addOnPositiveButtonClickListener {
|
||||||
|
timePicker.show(
|
||||||
|
fragmentView.fragmentActivity.supportFragmentManager,
|
||||||
|
"TimePicker"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
timePicker.addOnPositiveButtonClickListener {
|
||||||
|
var epochTime = datePicker.selection!! / 1000
|
||||||
|
epochTime += timePicker.hour.toLong() * 60 * 60
|
||||||
|
epochTime += timePicker.minute.toLong() * 60
|
||||||
|
val rtcString = "0x" + java.lang.Long.toHexString(epochTime)
|
||||||
|
if (item.getSelectedValue() != rtcString) {
|
||||||
|
notifyItemChanged(clickedPosition)
|
||||||
|
fragmentView.onSettingChanged()
|
||||||
|
}
|
||||||
|
item.setSelectedValue(fragmentView.settings!!, rtcString)
|
||||||
|
clickedItem = null
|
||||||
|
}
|
||||||
|
datePicker.show(fragmentView.fragmentActivity.supportFragmentManager, "DatePicker")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onFilePickerConfirmation(selectedFile: String) {
|
||||||
|
val filePicker = clickedItem as FilePicker?
|
||||||
|
|
||||||
|
if (filePicker!!.getSelectedValue() != selectedFile) {
|
||||||
|
notifyItemChanged(clickedPosition)
|
||||||
|
fragmentView.onSettingChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
filePicker.setSelectedValue(fragmentView.settings!!, selectedFile)
|
||||||
|
|
||||||
|
clickedItem = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onMenuTagAction(menuTag: MenuTag, value: Int) {
|
||||||
|
fragmentView.onMenuTagAction(menuTag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasMenuTagActionForValue(menuTag: MenuTag, value: Int): Boolean {
|
||||||
|
return fragmentView.hasMenuTagActionForValue(menuTag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(dialog: DialogInterface, which: Int) {
|
||||||
|
when (clickedItem) {
|
||||||
|
is SingleChoiceSetting -> {
|
||||||
|
val scSetting = clickedItem as SingleChoiceSetting
|
||||||
|
|
||||||
|
val value = getValueForSingleChoiceSelection(scSetting, which)
|
||||||
|
if (scSetting.selectedValue != value) fragmentView.onSettingChanged()
|
||||||
|
|
||||||
|
scSetting.setSelectedValue(settings, value)
|
||||||
|
|
||||||
|
closeDialog()
|
||||||
|
}
|
||||||
|
is SingleChoiceSettingDynamicDescriptions -> {
|
||||||
|
val scSetting = clickedItem as SingleChoiceSettingDynamicDescriptions
|
||||||
|
|
||||||
|
val value = getValueForSingleChoiceDynamicDescriptionsSelection(scSetting, which)
|
||||||
|
if (scSetting.selectedValue != value) fragmentView.onSettingChanged()
|
||||||
|
|
||||||
|
scSetting.setSelectedValue(settings!!, value)
|
||||||
|
|
||||||
|
closeDialog()
|
||||||
|
}
|
||||||
|
is StringSingleChoiceSetting -> {
|
||||||
|
val scSetting = clickedItem as StringSingleChoiceSetting
|
||||||
|
|
||||||
|
val value = scSetting.getValueAt(which)
|
||||||
|
if (scSetting.selectedValue != value) fragmentView.onSettingChanged()
|
||||||
|
|
||||||
|
scSetting.setSelectedValue(settings, value)
|
||||||
|
|
||||||
|
closeDialog()
|
||||||
|
}
|
||||||
|
is IntSliderSetting -> {
|
||||||
|
val sliderSetting = clickedItem as IntSliderSetting
|
||||||
|
if (sliderSetting.selectedValue != seekbarProgress) fragmentView.onSettingChanged()
|
||||||
|
sliderSetting.setSelectedValue(settings, seekbarProgress)
|
||||||
|
closeDialog()
|
||||||
|
}
|
||||||
|
is FloatSliderSetting -> {
|
||||||
|
val sliderSetting = clickedItem as FloatSliderSetting
|
||||||
|
|
||||||
|
if (sliderSetting.selectedValue != seekbarProgress) fragmentView.onSettingChanged()
|
||||||
|
|
||||||
|
sliderSetting.setSelectedValue(settings, seekbarProgress.toFloat())
|
||||||
|
|
||||||
|
closeDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clickedItem = null
|
||||||
|
seekbarProgress = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun closeDialog() {
|
||||||
|
if (dialog != null) {
|
||||||
|
if (clickedPosition != -1) {
|
||||||
|
notifyItemChanged(clickedPosition)
|
||||||
|
clickedPosition = -1
|
||||||
|
}
|
||||||
|
dialog!!.dismiss()
|
||||||
|
dialog = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onValueChange(slider: Slider, progress: Float, fromUser: Boolean) {
|
||||||
|
seekbarProgress = progress.toInt()
|
||||||
|
textSliderValue!!.text = seekbarProgress.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getValueForSingleChoiceSelection(item: SingleChoiceSetting, which: Int): Int {
|
||||||
|
val valuesId = item.valuesId
|
||||||
|
|
||||||
|
return if (valuesId > 0) {
|
||||||
|
val valuesArray = context.resources.getIntArray(valuesId)
|
||||||
|
valuesArray[which]
|
||||||
|
} else {
|
||||||
|
which
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSelectionForSingleChoiceValue(item: SingleChoiceSetting): Int {
|
||||||
|
val value = item.selectedValue
|
||||||
|
val valuesId = item.valuesId
|
||||||
|
|
||||||
|
if (valuesId > 0) {
|
||||||
|
val valuesArray = context.resources.getIntArray(valuesId)
|
||||||
|
for (index in valuesArray.indices) {
|
||||||
|
val current = valuesArray[index]
|
||||||
|
if (current == value) {
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getValueForSingleChoiceDynamicDescriptionsSelection(
|
||||||
|
item: SingleChoiceSettingDynamicDescriptions,
|
||||||
|
which: Int
|
||||||
|
): Int {
|
||||||
|
val valuesId = item.valuesId
|
||||||
|
return if (valuesId > 0) {
|
||||||
|
val valuesArray = context.resources.getIntArray(valuesId)
|
||||||
|
valuesArray[which]
|
||||||
|
} else {
|
||||||
|
which
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSelectionForSingleChoiceDynamicDescriptionsValue(
|
||||||
|
item: SingleChoiceSettingDynamicDescriptions
|
||||||
|
): Int {
|
||||||
|
val value = item.selectedValue
|
||||||
|
val valuesId = item.valuesId
|
||||||
|
if (valuesId > 0) {
|
||||||
|
val valuesArray = context.resources.getIntArray(valuesId)
|
||||||
|
for (index in valuesArray.indices) {
|
||||||
|
val current = valuesArray[index]
|
||||||
|
if (current == value) {
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun clearLog() {
|
||||||
|
// Don't delete the log in case it is being monitored by another app.
|
||||||
|
val log = File(DirectoryInitialization.getUserDirectory() + "/Logs/dolphin.log")
|
||||||
|
try {
|
||||||
|
val raf = RandomAccessFile(log, "rw")
|
||||||
|
raf.setLength(0)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Log.error("[SettingsAdapter] Failed to clear log file: " + e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,295 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.core.graphics.Insets;
|
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
|
||||||
import androidx.fragment.app.DialogFragment;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.FragmentSettingsBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public final class SettingsFragment extends Fragment implements SettingsFragmentView
|
|
||||||
{
|
|
||||||
private static final String ARGUMENT_MENU_TAG = "menu_tag";
|
|
||||||
private static final String ARGUMENT_GAME_ID = "game_id";
|
|
||||||
|
|
||||||
private SettingsFragmentPresenter mPresenter;
|
|
||||||
private SettingsActivityView mActivity;
|
|
||||||
|
|
||||||
private SettingsAdapter mAdapter;
|
|
||||||
|
|
||||||
private int mOldControllerSettingsWarningHeight = 0;
|
|
||||||
|
|
||||||
private static final Map<MenuTag, Integer> titles = new HashMap<>();
|
|
||||||
|
|
||||||
static
|
|
||||||
{
|
|
||||||
titles.put(MenuTag.SETTINGS, R.string.settings);
|
|
||||||
titles.put(MenuTag.CONFIG, R.string.config);
|
|
||||||
titles.put(MenuTag.CONFIG_GENERAL, R.string.general_submenu);
|
|
||||||
titles.put(MenuTag.CONFIG_INTERFACE, R.string.interface_submenu);
|
|
||||||
titles.put(MenuTag.CONFIG_AUDIO, R.string.audio_submenu);
|
|
||||||
titles.put(MenuTag.CONFIG_PATHS, R.string.paths_submenu);
|
|
||||||
titles.put(MenuTag.CONFIG_GAME_CUBE, R.string.gamecube_submenu);
|
|
||||||
titles.put(MenuTag.CONFIG_SERIALPORT1, R.string.serialport1_submenu);
|
|
||||||
titles.put(MenuTag.CONFIG_WII, R.string.wii_submenu);
|
|
||||||
titles.put(MenuTag.CONFIG_ADVANCED, R.string.advanced_submenu);
|
|
||||||
titles.put(MenuTag.DEBUG, R.string.debug_submenu);
|
|
||||||
titles.put(MenuTag.GRAPHICS, R.string.graphics_settings);
|
|
||||||
titles.put(MenuTag.ENHANCEMENTS, R.string.enhancements_submenu);
|
|
||||||
titles.put(MenuTag.STEREOSCOPY, R.string.stereoscopy_submenu);
|
|
||||||
titles.put(MenuTag.HACKS, R.string.hacks_submenu);
|
|
||||||
titles.put(MenuTag.STATISTICS, R.string.statistics_submenu);
|
|
||||||
titles.put(MenuTag.ADVANCED_GRAPHICS, R.string.advanced_graphics_submenu);
|
|
||||||
titles.put(MenuTag.CONFIG_LOG, R.string.log_submenu);
|
|
||||||
titles.put(MenuTag.GCPAD_TYPE, R.string.gcpad_settings);
|
|
||||||
titles.put(MenuTag.WIIMOTE, R.string.wiimote_settings);
|
|
||||||
titles.put(MenuTag.WIIMOTE_EXTENSION, R.string.wiimote_extensions);
|
|
||||||
titles.put(MenuTag.GCPAD_1, R.string.controller_0);
|
|
||||||
titles.put(MenuTag.GCPAD_2, R.string.controller_1);
|
|
||||||
titles.put(MenuTag.GCPAD_3, R.string.controller_2);
|
|
||||||
titles.put(MenuTag.GCPAD_4, R.string.controller_3);
|
|
||||||
titles.put(MenuTag.WIIMOTE_1, R.string.wiimote_0);
|
|
||||||
titles.put(MenuTag.WIIMOTE_2, R.string.wiimote_1);
|
|
||||||
titles.put(MenuTag.WIIMOTE_3, R.string.wiimote_2);
|
|
||||||
titles.put(MenuTag.WIIMOTE_4, R.string.wiimote_3);
|
|
||||||
titles.put(MenuTag.WIIMOTE_EXTENSION_1, R.string.wiimote_extension_0);
|
|
||||||
titles.put(MenuTag.WIIMOTE_EXTENSION_2, R.string.wiimote_extension_1);
|
|
||||||
titles.put(MenuTag.WIIMOTE_EXTENSION_3, R.string.wiimote_extension_2);
|
|
||||||
titles.put(MenuTag.WIIMOTE_EXTENSION_4, R.string.wiimote_extension_3);
|
|
||||||
titles.put(MenuTag.WIIMOTE_GENERAL_1, R.string.wiimote_general);
|
|
||||||
titles.put(MenuTag.WIIMOTE_GENERAL_2, R.string.wiimote_general);
|
|
||||||
titles.put(MenuTag.WIIMOTE_GENERAL_3, R.string.wiimote_general);
|
|
||||||
titles.put(MenuTag.WIIMOTE_GENERAL_4, R.string.wiimote_general);
|
|
||||||
titles.put(MenuTag.WIIMOTE_MOTION_SIMULATION_1, R.string.wiimote_motion_simulation);
|
|
||||||
titles.put(MenuTag.WIIMOTE_MOTION_SIMULATION_2, R.string.wiimote_motion_simulation);
|
|
||||||
titles.put(MenuTag.WIIMOTE_MOTION_SIMULATION_3, R.string.wiimote_motion_simulation);
|
|
||||||
titles.put(MenuTag.WIIMOTE_MOTION_SIMULATION_4, R.string.wiimote_motion_simulation);
|
|
||||||
titles.put(MenuTag.WIIMOTE_MOTION_INPUT_1, R.string.wiimote_motion_input);
|
|
||||||
titles.put(MenuTag.WIIMOTE_MOTION_INPUT_2, R.string.wiimote_motion_input);
|
|
||||||
titles.put(MenuTag.WIIMOTE_MOTION_INPUT_3, R.string.wiimote_motion_input);
|
|
||||||
titles.put(MenuTag.WIIMOTE_MOTION_INPUT_4, R.string.wiimote_motion_input);
|
|
||||||
}
|
|
||||||
|
|
||||||
private FragmentSettingsBinding mBinding;
|
|
||||||
|
|
||||||
public static Fragment newInstance(MenuTag menuTag, String gameId, Bundle extras)
|
|
||||||
{
|
|
||||||
SettingsFragment fragment = new SettingsFragment();
|
|
||||||
|
|
||||||
Bundle arguments = new Bundle();
|
|
||||||
if (extras != null)
|
|
||||||
{
|
|
||||||
arguments.putAll(extras);
|
|
||||||
}
|
|
||||||
|
|
||||||
arguments.putSerializable(ARGUMENT_MENU_TAG, menuTag);
|
|
||||||
arguments.putString(ARGUMENT_GAME_ID, gameId);
|
|
||||||
|
|
||||||
fragment.setArguments(arguments);
|
|
||||||
return fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttach(@NonNull Context context)
|
|
||||||
{
|
|
||||||
super.onAttach(context);
|
|
||||||
|
|
||||||
mActivity = (SettingsActivityView) context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
Bundle args = getArguments();
|
|
||||||
MenuTag menuTag = (MenuTag) args.getSerializable(ARGUMENT_MENU_TAG);
|
|
||||||
String gameId = getArguments().getString(ARGUMENT_GAME_ID);
|
|
||||||
|
|
||||||
mPresenter = new SettingsFragmentPresenter(this, getContext());
|
|
||||||
mAdapter = new SettingsAdapter(this, getContext());
|
|
||||||
|
|
||||||
mPresenter.onCreate(menuTag, gameId, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
mBinding = FragmentSettingsBinding.inflate(inflater, container, false);
|
|
||||||
return mBinding.getRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
Bundle args = getArguments();
|
|
||||||
MenuTag menuTag = (MenuTag) args.getSerializable(ARGUMENT_MENU_TAG);
|
|
||||||
|
|
||||||
if (titles.containsKey(menuTag))
|
|
||||||
{
|
|
||||||
mActivity.setToolbarTitle(getString(titles.get(menuTag)));
|
|
||||||
}
|
|
||||||
|
|
||||||
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
|
|
||||||
|
|
||||||
RecyclerView recyclerView = mBinding.listSettings;
|
|
||||||
|
|
||||||
recyclerView.setAdapter(mAdapter);
|
|
||||||
recyclerView.setLayoutManager(manager);
|
|
||||||
|
|
||||||
SettingsDividerItemDecoration divider = new SettingsDividerItemDecoration(requireActivity());
|
|
||||||
recyclerView.addItemDecoration(divider);
|
|
||||||
|
|
||||||
setInsets();
|
|
||||||
|
|
||||||
SettingsActivityView activity = (SettingsActivityView) getActivity();
|
|
||||||
mPresenter.onViewCreated(menuTag, activity.getSettings());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView()
|
|
||||||
{
|
|
||||||
super.onDestroyView();
|
|
||||||
mBinding = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDetach()
|
|
||||||
{
|
|
||||||
super.onDetach();
|
|
||||||
mActivity = null;
|
|
||||||
|
|
||||||
if (mAdapter != null)
|
|
||||||
{
|
|
||||||
mAdapter.closeDialog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSettingsFileLoaded(
|
|
||||||
org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
|
|
||||||
{
|
|
||||||
mPresenter.setSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showSettingsList(ArrayList<SettingsItem> settingsList)
|
|
||||||
{
|
|
||||||
mAdapter.setSettings(settingsList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadDefaultSettings()
|
|
||||||
{
|
|
||||||
mPresenter.loadDefaultSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SettingsAdapter getAdapter()
|
|
||||||
{
|
|
||||||
return mAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadSubMenu(MenuTag menuKey)
|
|
||||||
{
|
|
||||||
mActivity.showSettingsFragment(menuKey, null, true, getArguments().getString(ARGUMENT_GAME_ID));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showDialogFragment(DialogFragment fragment)
|
|
||||||
{
|
|
||||||
mActivity.showDialogFragment(fragment);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showToastMessage(String message)
|
|
||||||
{
|
|
||||||
mActivity.showToastMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Settings getSettings()
|
|
||||||
{
|
|
||||||
return mPresenter.getSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSettingChanged()
|
|
||||||
{
|
|
||||||
mActivity.onSettingChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onControllerSettingsChanged()
|
|
||||||
{
|
|
||||||
mAdapter.notifyAllSettingsChanged();
|
|
||||||
mPresenter.updateOldControllerSettingsWarningVisibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMenuTagAction(@NonNull MenuTag menuTag, int value)
|
|
||||||
{
|
|
||||||
mActivity.onMenuTagAction(menuTag, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasMenuTagActionForValue(@NonNull MenuTag menuTag, int value)
|
|
||||||
{
|
|
||||||
return mActivity.hasMenuTagActionForValue(menuTag, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMappingAllDevices(boolean allDevices)
|
|
||||||
{
|
|
||||||
mActivity.setMappingAllDevices(allDevices);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMappingAllDevices()
|
|
||||||
{
|
|
||||||
return mActivity.isMappingAllDevices();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setOldControllerSettingsWarningVisibility(boolean visible)
|
|
||||||
{
|
|
||||||
mOldControllerSettingsWarningHeight =
|
|
||||||
mActivity.setOldControllerSettingsWarningVisibility(visible);
|
|
||||||
|
|
||||||
// Trigger the insets listener we've registered
|
|
||||||
mBinding.listSettings.requestApplyInsets();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setInsets()
|
|
||||||
{
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(mBinding.listSettings, (v, windowInsets) ->
|
|
||||||
{
|
|
||||||
Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
|
|
||||||
int listSpacing = getResources().getDimensionPixelSize(R.dimen.spacing_list);
|
|
||||||
v.setPadding(0, 0, 0, insets.bottom + listSpacing + mOldControllerSettingsWarningHeight);
|
|
||||||
return windowInsets;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,242 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.updatePadding
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import org.dolphinemu.dolphinemu.R
|
||||||
|
import org.dolphinemu.dolphinemu.databinding.FragmentSettingsBinding
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
|
||||||
|
import org.dolphinemu.dolphinemu.utils.SerializableHelper.serializable
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
class SettingsFragment : Fragment(), SettingsFragmentView {
|
||||||
|
private lateinit var presenter: SettingsFragmentPresenter
|
||||||
|
private var activityView: SettingsActivityView? = null
|
||||||
|
|
||||||
|
private lateinit var menuTag: MenuTag
|
||||||
|
|
||||||
|
override val fragmentActivity: FragmentActivity
|
||||||
|
get() = requireActivity()
|
||||||
|
|
||||||
|
override var adapter: SettingsAdapter? = null
|
||||||
|
|
||||||
|
private var oldControllerSettingsWarningHeight = 0
|
||||||
|
|
||||||
|
private var binding: FragmentSettingsBinding? = null
|
||||||
|
|
||||||
|
override fun onAttach(context: Context) {
|
||||||
|
super.onAttach(context)
|
||||||
|
|
||||||
|
activityView = context as SettingsActivityView
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
menuTag = requireArguments().serializable(ARGUMENT_MENU_TAG)!!
|
||||||
|
|
||||||
|
val gameId = requireArguments().getString(ARGUMENT_GAME_ID)
|
||||||
|
presenter = SettingsFragmentPresenter(this, requireContext())
|
||||||
|
adapter = SettingsAdapter(this, requireContext())
|
||||||
|
|
||||||
|
presenter.onCreate(menuTag, gameId, requireArguments())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
binding = FragmentSettingsBinding.inflate(inflater, container, false)
|
||||||
|
return binding!!.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
if (titles.containsKey(menuTag)) {
|
||||||
|
activityView!!.setToolbarTitle(getString(titles[menuTag]!!))
|
||||||
|
}
|
||||||
|
|
||||||
|
val manager = LinearLayoutManager(activity)
|
||||||
|
|
||||||
|
val recyclerView = binding!!.listSettings
|
||||||
|
recyclerView.adapter = adapter
|
||||||
|
recyclerView.layoutManager = manager
|
||||||
|
|
||||||
|
val divider = SettingsDividerItemDecoration(requireActivity())
|
||||||
|
recyclerView.addItemDecoration(divider)
|
||||||
|
|
||||||
|
setInsets()
|
||||||
|
|
||||||
|
val activity = activity as SettingsActivityView?
|
||||||
|
presenter.onViewCreated(menuTag, activity!!.settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
binding = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetach() {
|
||||||
|
super.onDetach()
|
||||||
|
activityView = null
|
||||||
|
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter!!.closeDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSettingsFileLoaded(settings: Settings) {
|
||||||
|
presenter.settings = settings
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showSettingsList(settingsList: ArrayList<SettingsItem>) {
|
||||||
|
adapter!!.setSettings(settingsList)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadDefaultSettings() {
|
||||||
|
presenter.loadDefaultSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadSubMenu(menuKey: MenuTag) {
|
||||||
|
activityView!!.showSettingsFragment(
|
||||||
|
menuKey,
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
requireArguments().getString(ARGUMENT_GAME_ID)!!
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showDialogFragment(fragment: DialogFragment) {
|
||||||
|
activityView!!.showDialogFragment(fragment)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showToastMessage(message: String) {
|
||||||
|
activityView!!.showToastMessage(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val settings: Settings?
|
||||||
|
get() = presenter.settings
|
||||||
|
|
||||||
|
override fun onSettingChanged() {
|
||||||
|
activityView!!.onSettingChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onControllerSettingsChanged() {
|
||||||
|
adapter!!.notifyAllSettingsChanged()
|
||||||
|
presenter.updateOldControllerSettingsWarningVisibility()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMenuTagAction(menuTag: MenuTag, value: Int) {
|
||||||
|
activityView!!.onMenuTagAction(menuTag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasMenuTagActionForValue(menuTag: MenuTag, value: Int): Boolean {
|
||||||
|
return activityView!!.hasMenuTagActionForValue(menuTag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override var isMappingAllDevices: Boolean
|
||||||
|
get() = activityView!!.isMappingAllDevices
|
||||||
|
set(allDevices) {
|
||||||
|
activityView!!.isMappingAllDevices = allDevices
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setOldControllerSettingsWarningVisibility(visible: Boolean) {
|
||||||
|
oldControllerSettingsWarningHeight =
|
||||||
|
activityView!!.setOldControllerSettingsWarningVisibility(visible)
|
||||||
|
|
||||||
|
// Trigger the insets listener we've registered
|
||||||
|
binding!!.listSettings.requestApplyInsets()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setInsets() {
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(binding!!.listSettings) { v: View, windowInsets: WindowInsetsCompat ->
|
||||||
|
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||||
|
val listSpacing = resources.getDimensionPixelSize(R.dimen.spacing_list)
|
||||||
|
v.updatePadding(bottom = insets.bottom + listSpacing + oldControllerSettingsWarningHeight)
|
||||||
|
windowInsets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ARGUMENT_MENU_TAG = "menu_tag"
|
||||||
|
private const val ARGUMENT_GAME_ID = "game_id"
|
||||||
|
private val titles: MutableMap<MenuTag, Int> = EnumMap(MenuTag::class.java)
|
||||||
|
|
||||||
|
init {
|
||||||
|
titles[MenuTag.SETTINGS] = R.string.settings
|
||||||
|
titles[MenuTag.CONFIG] = R.string.config
|
||||||
|
titles[MenuTag.CONFIG_GENERAL] = R.string.general_submenu
|
||||||
|
titles[MenuTag.CONFIG_INTERFACE] = R.string.interface_submenu
|
||||||
|
titles[MenuTag.CONFIG_AUDIO] = R.string.audio_submenu
|
||||||
|
titles[MenuTag.CONFIG_PATHS] = R.string.paths_submenu
|
||||||
|
titles[MenuTag.CONFIG_GAME_CUBE] = R.string.gamecube_submenu
|
||||||
|
titles[MenuTag.CONFIG_SERIALPORT1] = R.string.serialport1_submenu
|
||||||
|
titles[MenuTag.CONFIG_WII] = R.string.wii_submenu
|
||||||
|
titles[MenuTag.CONFIG_ADVANCED] = R.string.advanced_submenu
|
||||||
|
titles[MenuTag.DEBUG] = R.string.debug_submenu
|
||||||
|
titles[MenuTag.GRAPHICS] = R.string.graphics_settings
|
||||||
|
titles[MenuTag.ENHANCEMENTS] = R.string.enhancements_submenu
|
||||||
|
titles[MenuTag.STEREOSCOPY] = R.string.stereoscopy_submenu
|
||||||
|
titles[MenuTag.HACKS] = R.string.hacks_submenu
|
||||||
|
titles[MenuTag.STATISTICS] = R.string.statistics_submenu
|
||||||
|
titles[MenuTag.ADVANCED_GRAPHICS] = R.string.advanced_graphics_submenu
|
||||||
|
titles[MenuTag.CONFIG_LOG] = R.string.log_submenu
|
||||||
|
titles[MenuTag.GCPAD_TYPE] = R.string.gcpad_settings
|
||||||
|
titles[MenuTag.WIIMOTE] = R.string.wiimote_settings
|
||||||
|
titles[MenuTag.WIIMOTE_EXTENSION] = R.string.wiimote_extensions
|
||||||
|
titles[MenuTag.GCPAD_1] = R.string.controller_0
|
||||||
|
titles[MenuTag.GCPAD_2] = R.string.controller_1
|
||||||
|
titles[MenuTag.GCPAD_3] = R.string.controller_2
|
||||||
|
titles[MenuTag.GCPAD_4] = R.string.controller_3
|
||||||
|
titles[MenuTag.WIIMOTE_1] = R.string.wiimote_0
|
||||||
|
titles[MenuTag.WIIMOTE_2] = R.string.wiimote_1
|
||||||
|
titles[MenuTag.WIIMOTE_3] = R.string.wiimote_2
|
||||||
|
titles[MenuTag.WIIMOTE_4] = R.string.wiimote_3
|
||||||
|
titles[MenuTag.WIIMOTE_EXTENSION_1] = R.string.wiimote_extension_0
|
||||||
|
titles[MenuTag.WIIMOTE_EXTENSION_2] = R.string.wiimote_extension_1
|
||||||
|
titles[MenuTag.WIIMOTE_EXTENSION_3] = R.string.wiimote_extension_2
|
||||||
|
titles[MenuTag.WIIMOTE_EXTENSION_4] = R.string.wiimote_extension_3
|
||||||
|
titles[MenuTag.WIIMOTE_GENERAL_1] = R.string.wiimote_general
|
||||||
|
titles[MenuTag.WIIMOTE_GENERAL_2] = R.string.wiimote_general
|
||||||
|
titles[MenuTag.WIIMOTE_GENERAL_3] = R.string.wiimote_general
|
||||||
|
titles[MenuTag.WIIMOTE_GENERAL_4] = R.string.wiimote_general
|
||||||
|
titles[MenuTag.WIIMOTE_MOTION_SIMULATION_1] = R.string.wiimote_motion_simulation
|
||||||
|
titles[MenuTag.WIIMOTE_MOTION_SIMULATION_2] = R.string.wiimote_motion_simulation
|
||||||
|
titles[MenuTag.WIIMOTE_MOTION_SIMULATION_3] = R.string.wiimote_motion_simulation
|
||||||
|
titles[MenuTag.WIIMOTE_MOTION_SIMULATION_4] = R.string.wiimote_motion_simulation
|
||||||
|
titles[MenuTag.WIIMOTE_MOTION_INPUT_1] = R.string.wiimote_motion_input
|
||||||
|
titles[MenuTag.WIIMOTE_MOTION_INPUT_2] = R.string.wiimote_motion_input
|
||||||
|
titles[MenuTag.WIIMOTE_MOTION_INPUT_3] = R.string.wiimote_motion_input
|
||||||
|
titles[MenuTag.WIIMOTE_MOTION_INPUT_4] = R.string.wiimote_motion_input
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun newInstance(menuTag: MenuTag?, gameId: String?, extras: Bundle?): Fragment {
|
||||||
|
val fragment = SettingsFragment()
|
||||||
|
|
||||||
|
val arguments = Bundle()
|
||||||
|
if (extras != null) {
|
||||||
|
arguments.putAll(extras)
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments.putSerializable(ARGUMENT_MENU_TAG, menuTag)
|
||||||
|
arguments.putString(ARGUMENT_GAME_ID, gameId)
|
||||||
|
|
||||||
|
fragment.arguments = arguments
|
||||||
|
return fragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,123 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.fragment.app.DialogFragment;
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstraction for a screen showing a list of settings. Instances of
|
|
||||||
* this type of view will each display a layer of the setting hierarchy.
|
|
||||||
*/
|
|
||||||
public interface SettingsFragmentView
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Called by the containing Activity to notify the Fragment that an
|
|
||||||
* asynchronous load operation completed.
|
|
||||||
*
|
|
||||||
* @param settings The (possibly null) result of the ini load operation.
|
|
||||||
*/
|
|
||||||
void onSettingsFileLoaded(Settings settings);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pass an ArrayList of settings to the View so that it can be displayed on screen.
|
|
||||||
*
|
|
||||||
* @param settingsList The settings to display
|
|
||||||
*/
|
|
||||||
void showSettingsList(ArrayList<SettingsItem> settingsList);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the containing Activity when an asynchronous load operation fails.
|
|
||||||
* Instructs the Fragment to load the settings screen with defaults selected.
|
|
||||||
*/
|
|
||||||
void loadDefaultSettings();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The Fragment's containing activity.
|
|
||||||
*/
|
|
||||||
FragmentActivity getActivity();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The Fragment's SettingsAdapter.
|
|
||||||
*/
|
|
||||||
SettingsAdapter getAdapter();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tell the Fragment to tell the containing Activity to show a new
|
|
||||||
* Fragment containing a submenu of settings.
|
|
||||||
*
|
|
||||||
* @param menuKey Identifier for the settings group that should be shown.
|
|
||||||
*/
|
|
||||||
void loadSubMenu(MenuTag menuKey);
|
|
||||||
|
|
||||||
void showDialogFragment(DialogFragment fragment);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tell the Fragment to tell the containing activity to display a toast message.
|
|
||||||
*
|
|
||||||
* @param message Text to be shown in the Toast
|
|
||||||
*/
|
|
||||||
void showToastMessage(String message);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The backing settings store.
|
|
||||||
*/
|
|
||||||
Settings getSettings();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Have the fragment tell the containing Activity that a setting was modified.
|
|
||||||
*/
|
|
||||||
void onSettingChanged();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Refetches the values of all controller settings.
|
|
||||||
*
|
|
||||||
* To be used when loading an input profile or performing some other action that changes all
|
|
||||||
* controller settings at once.
|
|
||||||
*/
|
|
||||||
void onControllerSettingsChanged();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Have the fragment tell the containing Activity that the user wants to open the MenuTag
|
|
||||||
* associated with a setting.
|
|
||||||
*
|
|
||||||
* @param menuTag The MenuTag of the setting.
|
|
||||||
* @param value The current value of the setting.
|
|
||||||
*/
|
|
||||||
void onMenuTagAction(@NonNull MenuTag menuTag, int value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether anything will happen when the user wants to open the MenuTag associated with a
|
|
||||||
* setting, given the current value of the setting.
|
|
||||||
*
|
|
||||||
* @param menuTag The MenuTag of the setting.
|
|
||||||
* @param value The current value of the setting.
|
|
||||||
*/
|
|
||||||
boolean hasMenuTagActionForValue(@NonNull MenuTag menuTag, int value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the input mapping dialog should detect inputs from all devices,
|
|
||||||
* not just the device configured for the controller.
|
|
||||||
*/
|
|
||||||
void setMappingAllDevices(boolean allDevices);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the input mapping dialog should detect inputs from all devices,
|
|
||||||
* not just the device configured for the controller.
|
|
||||||
*/
|
|
||||||
boolean isMappingAllDevices();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows or hides a warning telling the user that they're using incompatible controller settings.
|
|
||||||
* The warning is hidden by default.
|
|
||||||
*
|
|
||||||
* @param visible Whether the warning should be visible.
|
|
||||||
*/
|
|
||||||
void setOldControllerSettingsWarningVisibility(boolean visible);
|
|
||||||
}
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui
|
||||||
|
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction for a screen showing a list of settings. Instances of
|
||||||
|
* this type of view will each display a layer of the Setting hierarchy.
|
||||||
|
*/
|
||||||
|
interface SettingsFragmentView {
|
||||||
|
/**
|
||||||
|
* Called by the containing Activity to notify the Fragment that an
|
||||||
|
* asynchronous load operation completed.
|
||||||
|
*
|
||||||
|
* @param settings The (possibly null) result of the ini load operation.
|
||||||
|
*/
|
||||||
|
fun onSettingsFileLoaded(settings: Settings)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass an ArrayList of settings to the View so that it can be displayed on screen.
|
||||||
|
*
|
||||||
|
* @param settingsList The settings to display
|
||||||
|
*/
|
||||||
|
fun showSettingsList(settingsList: ArrayList<SettingsItem>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the containing Activity when an asynchronous load operation fails.
|
||||||
|
* Instructs the Fragment to load the settings screen with defaults selected.
|
||||||
|
*/
|
||||||
|
fun loadDefaultSettings()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The Fragment's containing activity.
|
||||||
|
*/
|
||||||
|
val fragmentActivity: FragmentActivity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The Fragment's SettingsAdapter.
|
||||||
|
*/
|
||||||
|
val adapter: SettingsAdapter?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the Fragment to tell the containing Activity to show a new
|
||||||
|
* Fragment containing a submenu of settings.
|
||||||
|
*
|
||||||
|
* @param menuKey Identifier for the settings group that should be shown.
|
||||||
|
*/
|
||||||
|
fun loadSubMenu(menuKey: MenuTag)
|
||||||
|
fun showDialogFragment(fragment: DialogFragment)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the Fragment to tell the containing activity to display a toast message.
|
||||||
|
*
|
||||||
|
* @param message Text to be shown in the Toast
|
||||||
|
*/
|
||||||
|
fun showToastMessage(message: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The backing settings store.
|
||||||
|
*/
|
||||||
|
val settings: Settings?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Have the fragment tell the containing Activity that a Setting was modified.
|
||||||
|
*/
|
||||||
|
fun onSettingChanged()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refetches the values of all controller settings.
|
||||||
|
*
|
||||||
|
* To be used when loading an input profile or performing some other action that changes all
|
||||||
|
* controller settings at once.
|
||||||
|
*/
|
||||||
|
fun onControllerSettingsChanged()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Have the fragment tell the containing Activity that the user wants to open the MenuTag
|
||||||
|
* associated with a Setting.
|
||||||
|
*
|
||||||
|
* @param menuTag The MenuTag of the Setting.
|
||||||
|
* @param value The current value of the Setting.
|
||||||
|
*/
|
||||||
|
fun onMenuTagAction(menuTag: MenuTag, value: Int)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether anything will happen when the user wants to open the MenuTag associated with a
|
||||||
|
* stringSetting, given the current value of the Setting.
|
||||||
|
*
|
||||||
|
* @param menuTag The MenuTag of the Setting.
|
||||||
|
* @param value The current value of the Setting.
|
||||||
|
*/
|
||||||
|
fun hasMenuTagActionForValue(menuTag: MenuTag, value: Int): Boolean
|
||||||
|
/**
|
||||||
|
* Returns whether the input mapping dialog should detect inputs from all devices,
|
||||||
|
* not just the device configured for the controller.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Sets whether the input mapping dialog should detect inputs from all devices,
|
||||||
|
* not just the device configured for the controller.
|
||||||
|
*/
|
||||||
|
var isMappingAllDevices: Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows or hides a warning telling the user that they're using incompatible controller settings.
|
||||||
|
* The warning is hidden by default.
|
||||||
|
*
|
||||||
|
* @param visible Whether the warning should be visible.
|
||||||
|
*/
|
||||||
|
fun setOldControllerSettingsWarningVisibility(visible: Boolean)
|
||||||
|
}
|
|
@ -1,17 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui;
|
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
|
|
||||||
public class SettingsViewModel extends ViewModel
|
|
||||||
{
|
|
||||||
private final Settings mSettings = new Settings();
|
|
||||||
|
|
||||||
public Settings getSettings()
|
|
||||||
{
|
|
||||||
return mSettings;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.Settings
|
||||||
|
|
||||||
|
class SettingsViewModel : ViewModel() {
|
||||||
|
val settings = Settings()
|
||||||
|
}
|
|
@ -18,12 +18,15 @@ class DateTimeSettingViewHolder(
|
||||||
private val binding: ListItemSettingBinding,
|
private val binding: ListItemSettingBinding,
|
||||||
adapter: SettingsAdapter
|
adapter: SettingsAdapter
|
||||||
) : SettingViewHolder(binding.root, adapter) {
|
) : SettingViewHolder(binding.root, adapter) {
|
||||||
private var mItem: DateTimeChoiceSetting? = null
|
lateinit var setting: DateTimeChoiceSetting
|
||||||
|
|
||||||
|
override val item: SettingsItem
|
||||||
|
get() = setting
|
||||||
|
|
||||||
override fun bind(item: SettingsItem) {
|
override fun bind(item: SettingsItem) {
|
||||||
mItem = item as DateTimeChoiceSetting
|
setting = item as DateTimeChoiceSetting
|
||||||
val inputTime = mItem!!.getSelectedValue()
|
val inputTime = setting.getSelectedValue()
|
||||||
binding.textSettingName.text = item.getName()
|
binding.textSettingName.text = item.name
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(inputTime)) {
|
if (!TextUtils.isEmpty(inputTime)) {
|
||||||
val epochTime = inputTime.substring(2).toLong(16)
|
val epochTime = inputTime.substring(2).toLong(16)
|
||||||
|
@ -32,21 +35,17 @@ class DateTimeSettingViewHolder(
|
||||||
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
|
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
|
||||||
binding.textSettingDescription.text = dateFormatter.format(zonedTime)
|
binding.textSettingDescription.text = dateFormatter.format(zonedTime)
|
||||||
} else {
|
} else {
|
||||||
binding.textSettingDescription.text = item.getDescription()
|
binding.textSettingDescription.text = item.description
|
||||||
}
|
}
|
||||||
setStyle(binding.textSettingName, mItem)
|
setStyle(binding.textSettingName, setting)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
if (!mItem!!.isEditable) {
|
if (!setting.isEditable) {
|
||||||
showNotRuntimeEditableError()
|
showNotRuntimeEditableError()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
adapter.onDateTimeClick(mItem, bindingAdapterPosition)
|
adapter.onDateTimeClick(setting, bindingAdapterPosition)
|
||||||
setStyle(binding.textSettingName, mItem)
|
setStyle(binding.textSettingName, setting)
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItem(): SettingsItem? {
|
|
||||||
return mItem
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
|
|
||||||
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|
||||||
import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
|
|
||||||
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
|
|
||||||
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
|
|
||||||
|
|
||||||
public final class FilePickerViewHolder extends SettingViewHolder
|
|
||||||
{
|
|
||||||
private FilePicker mFilePicker;
|
|
||||||
private SettingsItem mItem;
|
|
||||||
|
|
||||||
private final ListItemSettingBinding mBinding;
|
|
||||||
|
|
||||||
public FilePickerViewHolder(ListItemSettingBinding binding, SettingsAdapter adapter)
|
|
||||||
{
|
|
||||||
super(binding.getRoot(), adapter);
|
|
||||||
mBinding = binding;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bind(SettingsItem item)
|
|
||||||
{
|
|
||||||
mFilePicker = (FilePicker) item;
|
|
||||||
mItem = item;
|
|
||||||
|
|
||||||
String path = mFilePicker.getSelectedValue();
|
|
||||||
|
|
||||||
if (FileBrowserHelper.isPathEmptyOrValid(path))
|
|
||||||
{
|
|
||||||
itemView.setBackground(mBinding.getRoot().getBackground());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
itemView.setBackgroundResource(R.drawable.invalid_setting_background);
|
|
||||||
}
|
|
||||||
|
|
||||||
mBinding.textSettingName.setText(item.getName());
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(item.getDescription()))
|
|
||||||
{
|
|
||||||
mBinding.textSettingDescription.setText(item.getDescription());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (TextUtils.isEmpty(path))
|
|
||||||
{
|
|
||||||
String defaultPathRelative = mFilePicker.getDefaultPathRelativeToUserDirectory();
|
|
||||||
if (defaultPathRelative != null)
|
|
||||||
{
|
|
||||||
path = DirectoryInitialization.getUserDirectory() + defaultPathRelative;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mBinding.textSettingDescription.setText(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
setStyle(mBinding.textSettingName, mItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View clicked)
|
|
||||||
{
|
|
||||||
if (!mItem.isEditable())
|
|
||||||
{
|
|
||||||
showNotRuntimeEditableError();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int position = getBindingAdapterPosition();
|
|
||||||
if (mFilePicker.getRequestType() == MainPresenter.REQUEST_DIRECTORY)
|
|
||||||
{
|
|
||||||
getAdapter().onFilePickerDirectoryClick(mItem, position);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
getAdapter().onFilePickerFileClick(mItem, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
setStyle(mBinding.textSettingName, mItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable @Override
|
|
||||||
protected SettingsItem getItem()
|
|
||||||
{
|
|
||||||
return mItem;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
|
||||||
|
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.view.View
|
||||||
|
import org.dolphinemu.dolphinemu.R
|
||||||
|
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
|
||||||
|
import org.dolphinemu.dolphinemu.ui.main.MainPresenter
|
||||||
|
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization
|
||||||
|
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper
|
||||||
|
|
||||||
|
class FilePickerViewHolder(
|
||||||
|
private val binding: ListItemSettingBinding,
|
||||||
|
adapter: SettingsAdapter?
|
||||||
|
) : SettingViewHolder(binding.getRoot(), adapter!!) {
|
||||||
|
lateinit var setting: FilePicker
|
||||||
|
|
||||||
|
override val item: SettingsItem
|
||||||
|
get() = setting
|
||||||
|
|
||||||
|
override fun bind(item: SettingsItem) {
|
||||||
|
setting = item as FilePicker
|
||||||
|
|
||||||
|
var path = setting.getSelectedValue()
|
||||||
|
|
||||||
|
if (FileBrowserHelper.isPathEmptyOrValid(path)) {
|
||||||
|
itemView.background = binding.getRoot().background
|
||||||
|
} else {
|
||||||
|
itemView.setBackgroundResource(R.drawable.invalid_setting_background)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.textSettingName.text = setting.name
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(setting.description)) {
|
||||||
|
binding.textSettingDescription.text = setting.description
|
||||||
|
} else {
|
||||||
|
if (TextUtils.isEmpty(path)) {
|
||||||
|
val defaultPathRelative = setting.defaultPathRelativeToUserDirectory
|
||||||
|
if (defaultPathRelative != null) {
|
||||||
|
path = DirectoryInitialization.getUserDirectory() + defaultPathRelative
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.textSettingDescription.text = path
|
||||||
|
}
|
||||||
|
|
||||||
|
setStyle(binding.textSettingName, setting)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(clicked: View) {
|
||||||
|
if (!setting.isEditable) {
|
||||||
|
showNotRuntimeEditableError()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val position = bindingAdapterPosition
|
||||||
|
if (setting.requestType == MainPresenter.REQUEST_DIRECTORY) {
|
||||||
|
adapter.onFilePickerDirectoryClick(setting, position)
|
||||||
|
} else {
|
||||||
|
adapter.onFilePickerFileClick(setting, position)
|
||||||
|
}
|
||||||
|
|
||||||
|
setStyle(binding.textSettingName, setting)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,36 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
|
|
||||||
|
|
||||||
import android.text.method.LinkMovementMethod;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.google.android.material.color.MaterialColors;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.ListItemHeaderBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|
||||||
|
|
||||||
public final class HeaderHyperLinkViewHolder extends HeaderViewHolder
|
|
||||||
{
|
|
||||||
private final ListItemHeaderBinding mBinding;
|
|
||||||
|
|
||||||
public HeaderHyperLinkViewHolder(@NonNull ListItemHeaderBinding binding, SettingsAdapter adapter)
|
|
||||||
{
|
|
||||||
super(binding, adapter);
|
|
||||||
mBinding = binding;
|
|
||||||
itemView.setOnClickListener(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bind(@NonNull SettingsItem item)
|
|
||||||
{
|
|
||||||
super.bind(item);
|
|
||||||
|
|
||||||
mBinding.textHeaderName.setMovementMethod(LinkMovementMethod.getInstance());
|
|
||||||
mBinding.textHeaderName.setLinkTextColor(
|
|
||||||
MaterialColors.getColor(itemView, R.attr.colorTertiary));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
|
||||||
|
|
||||||
|
import android.text.method.LinkMovementMethod
|
||||||
|
import com.google.android.material.color.MaterialColors
|
||||||
|
import org.dolphinemu.dolphinemu.R
|
||||||
|
import org.dolphinemu.dolphinemu.databinding.ListItemHeaderBinding
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
|
||||||
|
|
||||||
|
class HeaderHyperLinkViewHolder(
|
||||||
|
private val binding: ListItemHeaderBinding,
|
||||||
|
adapter: SettingsAdapter?
|
||||||
|
) : HeaderViewHolder(binding, adapter) {
|
||||||
|
init {
|
||||||
|
itemView.setOnClickListener(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bind(item: SettingsItem) {
|
||||||
|
super.bind(item)
|
||||||
|
binding.textHeaderName.movementMethod = LinkMovementMethod.getInstance()
|
||||||
|
binding.textHeaderName.setLinkTextColor(
|
||||||
|
MaterialColors.getColor(itemView, R.attr.colorTertiary)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,42 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.ListItemHeaderBinding;
|
|
||||||
|
|
||||||
public class HeaderViewHolder extends SettingViewHolder
|
|
||||||
{
|
|
||||||
private final ListItemHeaderBinding mBinding;
|
|
||||||
|
|
||||||
public HeaderViewHolder(@NonNull ListItemHeaderBinding binding, SettingsAdapter adapter)
|
|
||||||
{
|
|
||||||
super(binding.getRoot(), adapter);
|
|
||||||
itemView.setOnClickListener(null);
|
|
||||||
mBinding = binding;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bind(@NonNull SettingsItem item)
|
|
||||||
{
|
|
||||||
mBinding.textHeaderName.setText(item.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View clicked)
|
|
||||||
{
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable @Override
|
|
||||||
protected SettingsItem getItem()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import org.dolphinemu.dolphinemu.databinding.ListItemHeaderBinding
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
|
||||||
|
|
||||||
|
open class HeaderViewHolder(
|
||||||
|
private val binding: ListItemHeaderBinding,
|
||||||
|
adapter: SettingsAdapter?
|
||||||
|
) : SettingViewHolder(binding.root, adapter!!) {
|
||||||
|
override val item: SettingsItem? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
itemView.setOnClickListener(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bind(item: SettingsItem) {
|
||||||
|
binding.textHeaderName.text = item.name
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(clicked: View) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,71 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
|
|
||||||
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.InputStringSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|
||||||
|
|
||||||
public final class InputStringSettingViewHolder extends SettingViewHolder
|
|
||||||
{
|
|
||||||
private InputStringSetting mInputString;
|
|
||||||
|
|
||||||
private final ListItemSettingBinding mBinding;
|
|
||||||
|
|
||||||
public InputStringSettingViewHolder(@NonNull ListItemSettingBinding binding,
|
|
||||||
SettingsAdapter adapter)
|
|
||||||
{
|
|
||||||
super(binding.getRoot(), adapter);
|
|
||||||
mBinding = binding;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bind(SettingsItem item)
|
|
||||||
{
|
|
||||||
mInputString = (InputStringSetting) item;
|
|
||||||
|
|
||||||
String inputString = mInputString.getSelectedValue();
|
|
||||||
|
|
||||||
mBinding.textSettingName.setText(item.getName());
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(inputString))
|
|
||||||
{
|
|
||||||
mBinding.textSettingDescription.setText(inputString);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mBinding.textSettingDescription.setText(item.getDescription());
|
|
||||||
}
|
|
||||||
|
|
||||||
setStyle(mBinding.textSettingName, mInputString);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View clicked)
|
|
||||||
{
|
|
||||||
if (!mInputString.isEditable())
|
|
||||||
{
|
|
||||||
showNotRuntimeEditableError();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int position = getBindingAdapterPosition();
|
|
||||||
|
|
||||||
getAdapter().onInputStringClick(mInputString, position);
|
|
||||||
|
|
||||||
setStyle(mBinding.textSettingName, mInputString);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable @Override
|
|
||||||
protected SettingsItem getItem()
|
|
||||||
{
|
|
||||||
return mInputString;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
|
||||||
|
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.view.View
|
||||||
|
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.view.InputStringSetting
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
|
||||||
|
|
||||||
|
class InputStringSettingViewHolder(
|
||||||
|
private val binding: ListItemSettingBinding,
|
||||||
|
adapter: SettingsAdapter
|
||||||
|
) : SettingViewHolder(binding.getRoot(), adapter) {
|
||||||
|
private lateinit var setting: InputStringSetting
|
||||||
|
|
||||||
|
override val item: SettingsItem
|
||||||
|
get() = setting
|
||||||
|
|
||||||
|
override fun bind(item: SettingsItem) {
|
||||||
|
setting = item as InputStringSetting
|
||||||
|
|
||||||
|
val inputString = setting.selectedValue
|
||||||
|
|
||||||
|
binding.textSettingName.text = setting.name
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(inputString)) {
|
||||||
|
binding.textSettingDescription.text = inputString
|
||||||
|
} else {
|
||||||
|
binding.textSettingDescription.text = setting.description
|
||||||
|
}
|
||||||
|
|
||||||
|
setStyle(binding.textSettingName, setting)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(clicked: View) {
|
||||||
|
if (!setting.isEditable) {
|
||||||
|
showNotRuntimeEditableError()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val position = bindingAdapterPosition
|
||||||
|
|
||||||
|
adapter.onInputStringClick(setting, position)
|
||||||
|
|
||||||
|
setStyle(binding.textSettingName, setting)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,93 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.RunRunnable;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|
||||||
|
|
||||||
public final class RunRunnableViewHolder extends SettingViewHolder
|
|
||||||
{
|
|
||||||
private RunRunnable mItem;
|
|
||||||
|
|
||||||
private final Context mContext;
|
|
||||||
|
|
||||||
private final ListItemSettingBinding mBinding;
|
|
||||||
|
|
||||||
public RunRunnableViewHolder(@NonNull ListItemSettingBinding binding, SettingsAdapter adapter,
|
|
||||||
Context context)
|
|
||||||
{
|
|
||||||
super(binding.getRoot(), adapter);
|
|
||||||
mBinding = binding;
|
|
||||||
mContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bind(SettingsItem item)
|
|
||||||
{
|
|
||||||
mItem = (RunRunnable) item;
|
|
||||||
|
|
||||||
mBinding.textSettingName.setText(item.getName());
|
|
||||||
mBinding.textSettingDescription.setText(item.getDescription());
|
|
||||||
|
|
||||||
setStyle(mBinding.textSettingName, mItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View clicked)
|
|
||||||
{
|
|
||||||
if (!mItem.isEditable())
|
|
||||||
{
|
|
||||||
showNotRuntimeEditableError();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int alertTextID = mItem.getAlertText();
|
|
||||||
|
|
||||||
if (alertTextID > 0)
|
|
||||||
{
|
|
||||||
new MaterialAlertDialogBuilder(mContext)
|
|
||||||
.setTitle(mItem.getName())
|
|
||||||
.setMessage(alertTextID)
|
|
||||||
.setPositiveButton(R.string.ok, (dialog, whichButton) ->
|
|
||||||
{
|
|
||||||
runRunnable();
|
|
||||||
dialog.dismiss();
|
|
||||||
})
|
|
||||||
.setNegativeButton(R.string.cancel, (dialog, whichButton) -> dialog.dismiss())
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
runRunnable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable @Override
|
|
||||||
protected SettingsItem getItem()
|
|
||||||
{
|
|
||||||
return mItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runRunnable()
|
|
||||||
{
|
|
||||||
mItem.getRunnable().run();
|
|
||||||
|
|
||||||
if (mItem.getToastTextAfterRun() > 0)
|
|
||||||
{
|
|
||||||
Toast.makeText(mContext, mContext.getString(mItem.getToastTextAfterRun()), Toast.LENGTH_SHORT)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.Toast
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import org.dolphinemu.dolphinemu.R
|
||||||
|
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.view.RunRunnable
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
|
||||||
|
|
||||||
|
class RunRunnableViewHolder(
|
||||||
|
private val mBinding: ListItemSettingBinding, adapter: SettingsAdapter?,
|
||||||
|
private val mContext: Context
|
||||||
|
) : SettingViewHolder(mBinding.getRoot(), adapter!!) {
|
||||||
|
private lateinit var setting: RunRunnable
|
||||||
|
|
||||||
|
override val item: SettingsItem
|
||||||
|
get() = setting
|
||||||
|
|
||||||
|
override fun bind(item: SettingsItem) {
|
||||||
|
setting = item as RunRunnable
|
||||||
|
|
||||||
|
mBinding.textSettingName.text = setting.name
|
||||||
|
mBinding.textSettingDescription.text = setting.description
|
||||||
|
|
||||||
|
setStyle(mBinding.textSettingName, setting)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(clicked: View) {
|
||||||
|
if (!setting.isEditable) {
|
||||||
|
showNotRuntimeEditableError()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val alertTextID = setting.alertText
|
||||||
|
|
||||||
|
if (alertTextID > 0) {
|
||||||
|
MaterialAlertDialogBuilder(mContext)
|
||||||
|
.setTitle(setting.name)
|
||||||
|
.setMessage(alertTextID)
|
||||||
|
.setPositiveButton(R.string.ok) { dialog: DialogInterface, _: Int ->
|
||||||
|
runRunnable()
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.cancel) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
|
||||||
|
.show()
|
||||||
|
} else {
|
||||||
|
runRunnable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runRunnable() {
|
||||||
|
setting.runnable.run()
|
||||||
|
|
||||||
|
if (setting.toastTextAfterRun > 0) {
|
||||||
|
Toast.makeText(
|
||||||
|
mContext,
|
||||||
|
mContext.getString(setting.toastTextAfterRun),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,111 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.DolphinApplication;
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|
||||||
|
|
||||||
public abstract class SettingViewHolder extends RecyclerView.ViewHolder
|
|
||||||
implements View.OnClickListener, View.OnLongClickListener
|
|
||||||
{
|
|
||||||
private SettingsAdapter mAdapter;
|
|
||||||
|
|
||||||
public SettingViewHolder(View itemView, SettingsAdapter adapter)
|
|
||||||
{
|
|
||||||
super(itemView);
|
|
||||||
|
|
||||||
mAdapter = adapter;
|
|
||||||
|
|
||||||
itemView.setOnClickListener(this);
|
|
||||||
itemView.setOnLongClickListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SettingsAdapter getAdapter()
|
|
||||||
{
|
|
||||||
return mAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setStyle(TextView textView, SettingsItem settingsItem)
|
|
||||||
{
|
|
||||||
boolean overridden = settingsItem.isOverridden();
|
|
||||||
textView.setTypeface(null, overridden ? Typeface.BOLD : Typeface.NORMAL);
|
|
||||||
|
|
||||||
if (!settingsItem.isEditable())
|
|
||||||
textView.setPaintFlags(textView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static void showNotRuntimeEditableError()
|
|
||||||
{
|
|
||||||
Toast.makeText(DolphinApplication.getAppContext(), R.string.setting_not_runtime_editable,
|
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static void showIplNotAvailableError()
|
|
||||||
{
|
|
||||||
Toast.makeText(DolphinApplication.getAppContext(), R.string.ipl_not_found, Toast.LENGTH_SHORT)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the adapter to set this ViewHolder's child views to display the list item
|
|
||||||
* it must now represent.
|
|
||||||
*
|
|
||||||
* @param item The list item that should be represented by this ViewHolder.
|
|
||||||
*/
|
|
||||||
public abstract void bind(SettingsItem item);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when this ViewHolder's view is clicked on. Implementations should usually pass
|
|
||||||
* this event up to the adapter.
|
|
||||||
*
|
|
||||||
* @param clicked The view that was clicked on.
|
|
||||||
*/
|
|
||||||
public abstract void onClick(View clicked);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
protected abstract SettingsItem getItem();
|
|
||||||
|
|
||||||
public boolean onLongClick(View clicked)
|
|
||||||
{
|
|
||||||
SettingsItem item = getItem();
|
|
||||||
|
|
||||||
if (item == null || !item.canClear())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!item.isEditable())
|
|
||||||
{
|
|
||||||
showNotRuntimeEditableError();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Context context = clicked.getContext();
|
|
||||||
|
|
||||||
new MaterialAlertDialogBuilder(context)
|
|
||||||
.setMessage(R.string.setting_clear_confirm)
|
|
||||||
.setPositiveButton(R.string.ok, (dialog, whichButton) ->
|
|
||||||
{
|
|
||||||
getAdapter().clearSetting(item);
|
|
||||||
bind(item);
|
|
||||||
Toast.makeText(context, R.string.setting_cleared, Toast.LENGTH_SHORT).show();
|
|
||||||
dialog.dismiss();
|
|
||||||
})
|
|
||||||
.setNegativeButton(R.string.cancel, (dialog, whichButton) -> dialog.dismiss())
|
|
||||||
.show();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
|
||||||
|
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.view.View
|
||||||
|
import android.view.View.OnLongClickListener
|
||||||
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import org.dolphinemu.dolphinemu.DolphinApplication
|
||||||
|
import org.dolphinemu.dolphinemu.R
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
|
||||||
|
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
|
||||||
|
|
||||||
|
abstract class SettingViewHolder(itemView: View, protected val adapter: SettingsAdapter) :
|
||||||
|
RecyclerView.ViewHolder(itemView), View.OnClickListener, OnLongClickListener {
|
||||||
|
|
||||||
|
init {
|
||||||
|
itemView.setOnClickListener(this)
|
||||||
|
itemView.setOnLongClickListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun setStyle(textView: TextView, settingsItem: SettingsItem) {
|
||||||
|
val overridden = settingsItem.isOverridden
|
||||||
|
textView.setTypeface(null, if (overridden) Typeface.BOLD else Typeface.NORMAL)
|
||||||
|
|
||||||
|
if (!settingsItem.isEditable) textView.paintFlags =
|
||||||
|
textView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the adapter to set this ViewHolder's child views to display the list item
|
||||||
|
* it must now represent.
|
||||||
|
*
|
||||||
|
* @param item The list item that should be represented by this ViewHolder.
|
||||||
|
*/
|
||||||
|
abstract fun bind(item: SettingsItem)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when this ViewHolder's view is clicked on. Implementations should usually pass
|
||||||
|
* this event up to the adapter.
|
||||||
|
*
|
||||||
|
* @param clicked The view that was clicked on.
|
||||||
|
*/
|
||||||
|
abstract override fun onClick(clicked: View)
|
||||||
|
|
||||||
|
protected abstract val item: SettingsItem?
|
||||||
|
|
||||||
|
override fun onLongClick(clicked: View): Boolean {
|
||||||
|
val item = item
|
||||||
|
|
||||||
|
if (item == null || !item.canClear()) return false
|
||||||
|
|
||||||
|
if (!item.isEditable) {
|
||||||
|
showNotRuntimeEditableError()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
val context = clicked.context
|
||||||
|
|
||||||
|
MaterialAlertDialogBuilder(context)
|
||||||
|
.setMessage(R.string.setting_clear_confirm)
|
||||||
|
.setPositiveButton(R.string.ok) { dialog: DialogInterface, _: Int ->
|
||||||
|
adapter.clearSetting(item)
|
||||||
|
bind(item)
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
R.string.setting_cleared,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.cancel) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
|
||||||
|
.show()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun showIplNotAvailableError() {
|
||||||
|
Toast.makeText(
|
||||||
|
DolphinApplication.getAppContext(),
|
||||||
|
R.string.ipl_not_found,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun showNotRuntimeEditableError() {
|
||||||
|
Toast.makeText(
|
||||||
|
DolphinApplication.getAppContext(),
|
||||||
|
R.string.setting_not_runtime_editable,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,148 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
|
|
||||||
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSettingDynamicDescriptions;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.model.view.StringSingleChoiceSetting;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
|
||||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public final class SingleChoiceViewHolder extends SettingViewHolder
|
|
||||||
{
|
|
||||||
private SettingsItem mItem;
|
|
||||||
|
|
||||||
private final ListItemSettingBinding mBinding;
|
|
||||||
|
|
||||||
public SingleChoiceViewHolder(@NonNull ListItemSettingBinding binding, SettingsAdapter adapter)
|
|
||||||
{
|
|
||||||
super(binding.getRoot(), adapter);
|
|
||||||
mBinding = binding;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bind(SettingsItem item)
|
|
||||||
{
|
|
||||||
mItem = item;
|
|
||||||
|
|
||||||
mBinding.textSettingName.setText(item.getName());
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(item.getDescription()))
|
|
||||||
{
|
|
||||||
mBinding.textSettingDescription.setText(item.getDescription());
|
|
||||||
}
|
|
||||||
else if (item instanceof SingleChoiceSetting)
|
|
||||||
{
|
|
||||||
SingleChoiceSetting setting = (SingleChoiceSetting) item;
|
|
||||||
int selected = setting.getSelectedValue();
|
|
||||||
Resources resMgr = mBinding.textSettingDescription.getContext().getResources();
|
|
||||||
String[] choices = resMgr.getStringArray(setting.getChoicesId());
|
|
||||||
int[] values = resMgr.getIntArray(setting.getValuesId());
|
|
||||||
for (int i = 0; i < values.length; ++i)
|
|
||||||
{
|
|
||||||
if (values[i] == selected)
|
|
||||||
{
|
|
||||||
mBinding.textSettingDescription.setText(choices[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (item instanceof StringSingleChoiceSetting)
|
|
||||||
{
|
|
||||||
StringSingleChoiceSetting setting = (StringSingleChoiceSetting) item;
|
|
||||||
String choice = setting.getSelectedChoice();
|
|
||||||
mBinding.textSettingDescription.setText(choice);
|
|
||||||
}
|
|
||||||
else if (item instanceof SingleChoiceSettingDynamicDescriptions)
|
|
||||||
{
|
|
||||||
SingleChoiceSettingDynamicDescriptions setting =
|
|
||||||
(SingleChoiceSettingDynamicDescriptions) item;
|
|
||||||
int selected = setting.getSelectedValue();
|
|
||||||
Resources resMgr = mBinding.textSettingDescription.getContext().getResources();
|
|
||||||
String[] choices = resMgr.getStringArray(setting.getDescriptionChoicesId());
|
|
||||||
int[] values = resMgr.getIntArray(setting.getDescriptionValuesId());
|
|
||||||
for (int i = 0; i < values.length; ++i)
|
|
||||||
{
|
|
||||||
if (values[i] == selected)
|
|
||||||
{
|
|
||||||
mBinding.textSettingDescription.setText(choices[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuTag menuTag = null;
|
|
||||||
Supplier<Integer> getSelectedValue = null;
|
|
||||||
if (item instanceof SingleChoiceSetting)
|
|
||||||
{
|
|
||||||
SingleChoiceSetting setting = (SingleChoiceSetting) item;
|
|
||||||
menuTag = setting.getMenuTag();
|
|
||||||
getSelectedValue = setting::getSelectedValue;
|
|
||||||
}
|
|
||||||
else if (item instanceof StringSingleChoiceSetting)
|
|
||||||
{
|
|
||||||
StringSingleChoiceSetting setting = (StringSingleChoiceSetting) item;
|
|
||||||
menuTag = setting.getMenuTag();
|
|
||||||
getSelectedValue = setting::getSelectedValueIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (menuTag != null && getAdapter().hasMenuTagActionForValue(menuTag, getSelectedValue.get()))
|
|
||||||
{
|
|
||||||
mBinding.buttonMoreSettings.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
final MenuTag finalMenuTag = menuTag;
|
|
||||||
final Supplier<Integer> finalGetSelectedValue = getSelectedValue;
|
|
||||||
mBinding.buttonMoreSettings.setOnClickListener((view) ->
|
|
||||||
getAdapter().onMenuTagAction(finalMenuTag, finalGetSelectedValue.get()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mBinding.buttonMoreSettings.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
setStyle(mBinding.textSettingName, mItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View clicked)
|
|
||||||
{
|
|
||||||
if (!mItem.isEditable())
|
|
||||||
{
|
|
||||||
showNotRuntimeEditableError();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int position = getBindingAdapterPosition();
|
|
||||||
if (mItem instanceof SingleChoiceSetting)
|
|
||||||
{
|
|
||||||
getAdapter().onSingleChoiceClick((SingleChoiceSetting) mItem, position);
|
|
||||||
}
|
|
||||||
else if (mItem instanceof StringSingleChoiceSetting)
|
|
||||||
{
|
|
||||||
getAdapter().onStringSingleChoiceClick((StringSingleChoiceSetting) mItem, position);
|
|
||||||
}
|
|
||||||
else if (mItem instanceof SingleChoiceSettingDynamicDescriptions)
|
|
||||||
{
|
|
||||||
getAdapter().onSingleChoiceDynamicDescriptionsClick(
|
|
||||||
(SingleChoiceSettingDynamicDescriptions) mItem, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
setStyle(mBinding.textSettingName, mItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable @Override
|
|
||||||
protected SettingsItem getItem()
|
|
||||||
{
|
|
||||||
return mItem;
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue