128 changed files with 934 additions and 2509 deletions
-
2src/android/app/build.gradle
-
2src/android/app/src/androidTest/java/org/yuzu/yuzu_emu/ExampleInstrumentedTest.java
-
34src/android/app/src/main/AndroidManifest.xml
-
122src/android/app/src/main/java/org/citra/citra_emu/applets/MiiSelector.java
-
65src/android/app/src/main/java/org/citra/citra_emu/camera/StillImageCameraHelper.java
-
138src/android/app/src/main/java/org/citra/citra_emu/disk_shader_cache/DiskShaderCacheProgress.java
-
57src/android/app/src/main/java/org/citra/citra_emu/features/cheats/model/Cheat.java
-
13src/android/app/src/main/java/org/citra/citra_emu/features/cheats/model/CheatEngine.java
-
177src/android/app/src/main/java/org/citra/citra_emu/features/cheats/model/CheatsViewModel.java
-
174src/android/app/src/main/java/org/citra/citra_emu/features/cheats/ui/CheatDetailsFragment.java
-
46src/android/app/src/main/java/org/citra/citra_emu/features/cheats/ui/CheatListFragment.java
-
56src/android/app/src/main/java/org/citra/citra_emu/features/cheats/ui/CheatViewHolder.java
-
161src/android/app/src/main/java/org/citra/citra_emu/features/cheats/ui/CheatsActivity.java
-
72src/android/app/src/main/java/org/citra/citra_emu/features/cheats/ui/CheatsAdapter.java
-
14src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java
-
12src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.java
-
4src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/CustomFilePickerActivity.java
-
452src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.java
-
18src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.java
-
18src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/SoftwareKeyboard.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/MotionAlertDialog.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/FloatSetting.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.java
-
4src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Setting.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingSection.java
-
17src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.java
-
16src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/CheckBoxSetting.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/DateTimeSetting.java
-
4src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/HeaderSetting.java
-
32src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/InputBindingSetting.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/PremiumHeader.java
-
14src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/PremiumSingleChoiceSetting.java
-
8src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SingleChoiceSetting.java
-
10src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SliderSetting.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringSingleChoiceSetting.java
-
4src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SubmenuSetting.java
-
18src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.java
-
29src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.java
-
52src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.java
-
12src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.java
-
134src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.java
-
8src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFrameLayout.java
-
10src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/CheckBoxSettingViewHolder.java
-
12src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.java
-
8src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/HeaderViewHolder.java
-
10src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/InputBindingSettingViewHolder.java
-
12src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/PremiumViewHolder.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SettingViewHolder.java
-
14src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.java
-
10src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.java
-
10src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SubmenuViewHolder.java
-
36src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.java
-
4src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/CustomFilePickerFragment.java
-
28src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.java
-
129src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MenuFragment.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GameDatabase.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GameProvider.java
-
14src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/DividerItemDecoration.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/TwoPaneOnBackPressedCallback.java
-
28src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java
-
18src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainPresenter.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainView.java
-
12src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.java
-
10src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesPresenter.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesView.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/Action1.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/AddDirectoryHelper.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/BiMap.java
-
14src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/BillingManager.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ControllerMappingHelper.java
-
34src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.java
-
4src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryStateReceiver.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/EmulationMenuSettings.java
-
4src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileBrowserHelper.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ForegroundService.java
-
4src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconRequestHandler.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/Log.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/PermissionsHandler.java
-
2src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/PicassoRoundedCornersTransformation.java
-
8src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/PicassoUtils.java
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/StartupHandler.java
-
8src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ThemeUtil.java
-
4src/android/app/src/main/java/org/yuzu/yuzu_emu/viewholders/GameViewHolder.java
-
64src/android/app/src/main/jni/native.cpp
-
68src/android/app/src/main/jni/native.h
-
20src/android/app/src/main/res/animator/menu_slide_in_from_end.xml
-
20src/android/app/src/main/res/animator/menu_slide_in_from_start.xml
-
21src/android/app/src/main/res/animator/menu_slide_out_to_end.xml
-
21src/android/app/src/main/res/animator/menu_slide_out_to_start.xml
@ -1,3 +1,3 @@ |
|||
package org.citra.citra_emu; |
|||
package org.yuzu.yuzu_emu; |
|||
|
|||
import android.content.Context; |
|||
@ -1,122 +0,0 @@ |
|||
// Copyright 2020 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
package org.citra.citra_emu.applets; |
|||
|
|||
import android.app.Activity; |
|||
import android.app.Dialog; |
|||
import android.os.Bundle; |
|||
|
|||
import org.citra.citra_emu.NativeLibrary; |
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.activities.EmulationActivity; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.Arrays; |
|||
import java.util.Objects; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.appcompat.app.AlertDialog; |
|||
import androidx.fragment.app.DialogFragment; |
|||
|
|||
public final class MiiSelector { |
|||
public static class MiiSelectorConfig implements java.io.Serializable { |
|||
public boolean enable_cancel_button; |
|||
public String title; |
|||
public long initially_selected_mii_index; |
|||
// List of Miis to display |
|||
public String[] mii_names; |
|||
} |
|||
|
|||
public static class MiiSelectorData { |
|||
public long return_code; |
|||
public int index; |
|||
|
|||
private MiiSelectorData(long return_code, int index) { |
|||
this.return_code = return_code; |
|||
this.index = index; |
|||
} |
|||
} |
|||
|
|||
public static class MiiSelectorDialogFragment extends DialogFragment { |
|||
static MiiSelectorDialogFragment newInstance(MiiSelectorConfig config) { |
|||
MiiSelectorDialogFragment frag = new MiiSelectorDialogFragment(); |
|||
Bundle args = new Bundle(); |
|||
args.putSerializable("config", config); |
|||
frag.setArguments(args); |
|||
return frag; |
|||
} |
|||
|
|||
@NonNull |
|||
@Override |
|||
public Dialog onCreateDialog(Bundle savedInstanceState) { |
|||
final Activity emulationActivity = Objects.requireNonNull(getActivity()); |
|||
|
|||
MiiSelectorConfig config = |
|||
Objects.requireNonNull((MiiSelectorConfig) Objects.requireNonNull(getArguments()) |
|||
.getSerializable("config")); |
|||
|
|||
// Note: we intentionally leave out the Standard Mii in the native code so that |
|||
// the string can get translated |
|||
ArrayList<String> list = new ArrayList<>(); |
|||
list.add(emulationActivity.getString(R.string.standard_mii)); |
|||
list.addAll(Arrays.asList(config.mii_names)); |
|||
|
|||
final int initialIndex = config.initially_selected_mii_index < list.size() |
|||
? (int) config.initially_selected_mii_index |
|||
: 0; |
|||
data.index = initialIndex; |
|||
AlertDialog.Builder builder = |
|||
new AlertDialog.Builder(emulationActivity) |
|||
.setTitle(config.title.isEmpty() |
|||
? emulationActivity.getString(R.string.mii_selector) |
|||
: config.title) |
|||
.setSingleChoiceItems(list.toArray(new String[]{}), initialIndex, |
|||
(dialog, which) -> { |
|||
data.index = which; |
|||
}) |
|||
.setPositiveButton(android.R.string.ok, (dialog, which) -> { |
|||
data.return_code = 0; |
|||
synchronized (finishLock) { |
|||
finishLock.notifyAll(); |
|||
} |
|||
}); |
|||
if (config.enable_cancel_button) { |
|||
builder.setNegativeButton(android.R.string.cancel, (dialog, which) -> { |
|||
data.return_code = 1; |
|||
synchronized (finishLock) { |
|||
finishLock.notifyAll(); |
|||
} |
|||
}); |
|||
} |
|||
setCancelable(false); |
|||
return builder.create(); |
|||
} |
|||
} |
|||
|
|||
private static MiiSelectorData data; |
|||
private static final Object finishLock = new Object(); |
|||
|
|||
private static void ExecuteImpl(MiiSelectorConfig config) { |
|||
final EmulationActivity emulationActivity = NativeLibrary.sEmulationActivity.get(); |
|||
|
|||
data = new MiiSelectorData(0, 0); |
|||
|
|||
MiiSelectorDialogFragment fragment = MiiSelectorDialogFragment.newInstance(config); |
|||
fragment.show(emulationActivity.getSupportFragmentManager(), "mii_selector"); |
|||
} |
|||
|
|||
public static MiiSelectorData Execute(MiiSelectorConfig config) { |
|||
NativeLibrary.sEmulationActivity.get().runOnUiThread(() -> ExecuteImpl(config)); |
|||
|
|||
synchronized (finishLock) { |
|||
try { |
|||
finishLock.wait(); |
|||
} catch (Exception ignored) { |
|||
} |
|||
} |
|||
|
|||
return data; |
|||
} |
|||
} |
|||
@ -1,65 +0,0 @@ |
|||
// Copyright 2020 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
package org.citra.citra_emu.camera; |
|||
|
|||
import android.content.Intent; |
|||
import android.graphics.Bitmap; |
|||
import android.provider.MediaStore; |
|||
|
|||
import org.citra.citra_emu.NativeLibrary; |
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.activities.EmulationActivity; |
|||
import org.citra.citra_emu.utils.PicassoUtils; |
|||
|
|||
import androidx.annotation.Nullable; |
|||
|
|||
// Used in native code. |
|||
public final class StillImageCameraHelper { |
|||
public static final int REQUEST_CAMERA_FILE_PICKER = 1; |
|||
private static final Object filePickerLock = new Object(); |
|||
private static @Nullable |
|||
String filePickerPath; |
|||
|
|||
// Opens file picker for camera. |
|||
public static @Nullable |
|||
String OpenFilePicker() { |
|||
final EmulationActivity emulationActivity = NativeLibrary.sEmulationActivity.get(); |
|||
|
|||
// At this point, we are assuming that we already have permissions as they are |
|||
// needed to launch a game |
|||
emulationActivity.runOnUiThread(() -> { |
|||
Intent intent = new Intent(Intent.ACTION_PICK); |
|||
intent.setDataAndType(MediaStore.Images.Media.INTERNAL_CONTENT_URI, "image/*"); |
|||
emulationActivity.startActivityForResult( |
|||
Intent.createChooser(intent, |
|||
emulationActivity.getString(R.string.camera_select_image)), |
|||
REQUEST_CAMERA_FILE_PICKER); |
|||
}); |
|||
|
|||
synchronized (filePickerLock) { |
|||
try { |
|||
filePickerLock.wait(); |
|||
} catch (InterruptedException ignored) { |
|||
} |
|||
} |
|||
|
|||
return filePickerPath; |
|||
} |
|||
|
|||
// Called from EmulationActivity. |
|||
public static void OnFilePickerResult(Intent result) { |
|||
filePickerPath = result == null ? null : result.getDataString(); |
|||
|
|||
synchronized (filePickerLock) { |
|||
filePickerLock.notifyAll(); |
|||
} |
|||
} |
|||
|
|||
// Blocking call. Load image from file and crop/resize it to fit in width x height. |
|||
@Nullable |
|||
public static Bitmap LoadImageFromFile(String uri, int width, int height) { |
|||
return PicassoUtils.LoadBitmapFromFile(uri, width, height); |
|||
} |
|||
} |
|||
@ -1,138 +0,0 @@ |
|||
// Copyright 2021 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
package org.citra.citra_emu.disk_shader_cache; |
|||
|
|||
import android.app.Activity; |
|||
import android.app.Dialog; |
|||
import android.content.DialogInterface; |
|||
import android.os.Bundle; |
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
import android.widget.ProgressBar; |
|||
import android.widget.TextView; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.appcompat.app.AlertDialog; |
|||
import androidx.fragment.app.DialogFragment; |
|||
|
|||
import org.citra.citra_emu.NativeLibrary; |
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.activities.EmulationActivity; |
|||
import org.citra.citra_emu.utils.Log; |
|||
|
|||
import java.util.Objects; |
|||
|
|||
public class DiskShaderCacheProgress { |
|||
|
|||
// Equivalent to VideoCore::LoadCallbackStage |
|||
public enum LoadCallbackStage { |
|||
Prepare, |
|||
Decompile, |
|||
Build, |
|||
Complete, |
|||
} |
|||
|
|||
private static final Object finishLock = new Object(); |
|||
private static ProgressDialogFragment fragment; |
|||
|
|||
public static class ProgressDialogFragment extends DialogFragment { |
|||
ProgressBar progressBar; |
|||
TextView progressText; |
|||
AlertDialog dialog; |
|||
|
|||
static ProgressDialogFragment newInstance(String title, String message) { |
|||
ProgressDialogFragment frag = new ProgressDialogFragment(); |
|||
Bundle args = new Bundle(); |
|||
args.putString("title", title); |
|||
args.putString("message", message); |
|||
frag.setArguments(args); |
|||
return frag; |
|||
} |
|||
|
|||
@NonNull |
|||
@Override |
|||
public Dialog onCreateDialog(Bundle savedInstanceState) { |
|||
final Activity emulationActivity = Objects.requireNonNull(getActivity()); |
|||
|
|||
final String title = Objects.requireNonNull(Objects.requireNonNull(getArguments()).getString("title")); |
|||
final String message = Objects.requireNonNull(Objects.requireNonNull(getArguments()).getString("message")); |
|||
|
|||
LayoutInflater inflater = LayoutInflater.from(emulationActivity); |
|||
View view = inflater.inflate(R.layout.dialog_progress_bar, null); |
|||
|
|||
progressBar = view.findViewById(R.id.progress_bar); |
|||
progressText = view.findViewById(R.id.progress_text); |
|||
progressText.setText(""); |
|||
|
|||
setCancelable(false); |
|||
setRetainInstance(true); |
|||
|
|||
AlertDialog.Builder builder = new AlertDialog.Builder(emulationActivity); |
|||
builder.setTitle(title); |
|||
builder.setMessage(message); |
|||
builder.setView(view); |
|||
builder.setNegativeButton(android.R.string.cancel, null); |
|||
|
|||
dialog = builder.create(); |
|||
dialog.create(); |
|||
|
|||
dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener((v) -> emulationActivity.onBackPressed()); |
|||
|
|||
synchronized (finishLock) { |
|||
finishLock.notifyAll(); |
|||
} |
|||
|
|||
return dialog; |
|||
} |
|||
|
|||
private void onUpdateProgress(String msg, int progress, int max) { |
|||
Objects.requireNonNull(getActivity()).runOnUiThread(() -> { |
|||
progressBar.setProgress(progress); |
|||
progressBar.setMax(max); |
|||
progressText.setText(String.format("%d/%d", progress, max)); |
|||
dialog.setMessage(msg); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
private static void prepareDialog() { |
|||
NativeLibrary.sEmulationActivity.get().runOnUiThread(() -> { |
|||
final EmulationActivity emulationActivity = NativeLibrary.sEmulationActivity.get(); |
|||
fragment = ProgressDialogFragment.newInstance(emulationActivity.getString(R.string.loading), emulationActivity.getString(R.string.preparing_shaders)); |
|||
fragment.show(emulationActivity.getSupportFragmentManager(), "diskShaders"); |
|||
}); |
|||
|
|||
synchronized (finishLock) { |
|||
try { |
|||
finishLock.wait(); |
|||
} catch (Exception ignored) { |
|||
} |
|||
} |
|||
} |
|||
|
|||
public static void loadProgress(LoadCallbackStage stage, int progress, int max) { |
|||
final EmulationActivity emulationActivity = NativeLibrary.sEmulationActivity.get(); |
|||
if (emulationActivity == null) { |
|||
Log.error("[DiskShaderCacheProgress] EmulationActivity not present"); |
|||
return; |
|||
} |
|||
|
|||
switch (stage) { |
|||
case Prepare: |
|||
prepareDialog(); |
|||
break; |
|||
case Decompile: |
|||
fragment.onUpdateProgress(emulationActivity.getString(R.string.preparing_shaders), progress, max); |
|||
break; |
|||
case Build: |
|||
fragment.onUpdateProgress(emulationActivity.getString(R.string.building_shaders), progress, max); |
|||
break; |
|||
case Complete: |
|||
// Workaround for when dialog is dismissed when the app is in the background |
|||
fragment.dismissAllowingStateLoss(); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
package org.citra.citra_emu.features.cheats.model; |
|||
|
|||
import androidx.annotation.Keep; |
|||
import androidx.annotation.NonNull; |
|||
import androidx.annotation.Nullable; |
|||
|
|||
public class Cheat { |
|||
@Keep |
|||
private final long mPointer; |
|||
|
|||
private Runnable mEnabledChangedCallback = null; |
|||
|
|||
@Keep |
|||
private Cheat(long pointer) { |
|||
mPointer = pointer; |
|||
} |
|||
|
|||
@Override |
|||
protected native void finalize(); |
|||
|
|||
@NonNull |
|||
public native String getName(); |
|||
|
|||
@NonNull |
|||
public native String getNotes(); |
|||
|
|||
@NonNull |
|||
public native String getCode(); |
|||
|
|||
public native boolean getEnabled(); |
|||
|
|||
public void setEnabled(boolean enabled) { |
|||
setEnabledImpl(enabled); |
|||
onEnabledChanged(); |
|||
} |
|||
|
|||
private native void setEnabledImpl(boolean enabled); |
|||
|
|||
public void setEnabledChangedCallback(@Nullable Runnable callback) { |
|||
mEnabledChangedCallback = callback; |
|||
} |
|||
|
|||
private void onEnabledChanged() { |
|||
if (mEnabledChangedCallback != null) { |
|||
mEnabledChangedCallback.run(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* If the code is valid, returns 0. Otherwise, returns the 1-based index |
|||
* for the line containing the error. |
|||
*/ |
|||
public static native int isValidGatewayCode(@NonNull String code); |
|||
|
|||
public static native Cheat createGatewayCode(@NonNull String name, @NonNull String notes, |
|||
@NonNull String code); |
|||
} |
|||
@ -1,13 +0,0 @@ |
|||
package org.citra.citra_emu.features.cheats.model; |
|||
|
|||
public class CheatEngine { |
|||
public static native Cheat[] getCheats(); |
|||
|
|||
public static native void addCheat(Cheat cheat); |
|||
|
|||
public static native void removeCheat(int index); |
|||
|
|||
public static native void updateCheat(int index, Cheat newCheat); |
|||
|
|||
public static native void saveCheatFile(); |
|||
} |
|||
@ -1,177 +0,0 @@ |
|||
package org.citra.citra_emu.features.cheats.model; |
|||
|
|||
import androidx.lifecycle.LiveData; |
|||
import androidx.lifecycle.MutableLiveData; |
|||
import androidx.lifecycle.ViewModel; |
|||
|
|||
public class CheatsViewModel extends ViewModel { |
|||
private int mSelectedCheatPosition = -1; |
|||
private final MutableLiveData<Cheat> mSelectedCheat = new MutableLiveData<>(null); |
|||
private final MutableLiveData<Boolean> mIsAdding = new MutableLiveData<>(false); |
|||
private final MutableLiveData<Boolean> mIsEditing = new MutableLiveData<>(false); |
|||
|
|||
private final MutableLiveData<Integer> mCheatAddedEvent = new MutableLiveData<>(null); |
|||
private final MutableLiveData<Integer> mCheatChangedEvent = new MutableLiveData<>(null); |
|||
private final MutableLiveData<Integer> mCheatDeletedEvent = new MutableLiveData<>(null); |
|||
private final MutableLiveData<Boolean> mOpenDetailsViewEvent = new MutableLiveData<>(false); |
|||
|
|||
private Cheat[] mCheats; |
|||
private boolean mCheatsNeedSaving = false; |
|||
|
|||
public void load() { |
|||
mCheats = CheatEngine.getCheats(); |
|||
|
|||
for (int i = 0; i < mCheats.length; i++) { |
|||
int position = i; |
|||
mCheats[i].setEnabledChangedCallback(() -> { |
|||
mCheatsNeedSaving = true; |
|||
notifyCheatUpdated(position); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
public void saveIfNeeded() { |
|||
if (mCheatsNeedSaving) { |
|||
CheatEngine.saveCheatFile(); |
|||
mCheatsNeedSaving = false; |
|||
} |
|||
} |
|||
|
|||
public Cheat[] getCheats() { |
|||
return mCheats; |
|||
} |
|||
|
|||
public LiveData<Cheat> getSelectedCheat() { |
|||
return mSelectedCheat; |
|||
} |
|||
|
|||
public void setSelectedCheat(Cheat cheat, int position) { |
|||
if (mIsEditing.getValue()) { |
|||
setIsEditing(false); |
|||
} |
|||
|
|||
mSelectedCheat.setValue(cheat); |
|||
mSelectedCheatPosition = position; |
|||
} |
|||
|
|||
public LiveData<Boolean> getIsAdding() { |
|||
return mIsAdding; |
|||
} |
|||
|
|||
public LiveData<Boolean> getIsEditing() { |
|||
return mIsEditing; |
|||
} |
|||
|
|||
public void setIsEditing(boolean isEditing) { |
|||
mIsEditing.setValue(isEditing); |
|||
|
|||
if (mIsAdding.getValue() && !isEditing) { |
|||
mIsAdding.setValue(false); |
|||
setSelectedCheat(null, -1); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* When a cheat is added, the integer stored in the returned LiveData |
|||
* changes to the position of that cheat, then changes back to null. |
|||
*/ |
|||
public LiveData<Integer> getCheatAddedEvent() { |
|||
return mCheatAddedEvent; |
|||
} |
|||
|
|||
private void notifyCheatAdded(int position) { |
|||
mCheatAddedEvent.setValue(position); |
|||
mCheatAddedEvent.setValue(null); |
|||
} |
|||
|
|||
public void startAddingCheat() { |
|||
mSelectedCheat.setValue(null); |
|||
mSelectedCheatPosition = -1; |
|||
|
|||
mIsAdding.setValue(true); |
|||
mIsEditing.setValue(true); |
|||
} |
|||
|
|||
public void finishAddingCheat(Cheat cheat) { |
|||
if (!mIsAdding.getValue()) { |
|||
throw new IllegalStateException(); |
|||
} |
|||
|
|||
mIsAdding.setValue(false); |
|||
mIsEditing.setValue(false); |
|||
|
|||
int position = mCheats.length; |
|||
|
|||
CheatEngine.addCheat(cheat); |
|||
|
|||
mCheatsNeedSaving = true; |
|||
load(); |
|||
|
|||
notifyCheatAdded(position); |
|||
setSelectedCheat(mCheats[position], position); |
|||
} |
|||
|
|||
/** |
|||
* When a cheat is edited, the integer stored in the returned LiveData |
|||
* changes to the position of that cheat, then changes back to null. |
|||
*/ |
|||
public LiveData<Integer> getCheatUpdatedEvent() { |
|||
return mCheatChangedEvent; |
|||
} |
|||
|
|||
/** |
|||
* Notifies that an edit has been made to the contents of the cheat at the given position. |
|||
*/ |
|||
private void notifyCheatUpdated(int position) { |
|||
mCheatChangedEvent.setValue(position); |
|||
mCheatChangedEvent.setValue(null); |
|||
} |
|||
|
|||
public void updateSelectedCheat(Cheat newCheat) { |
|||
CheatEngine.updateCheat(mSelectedCheatPosition, newCheat); |
|||
|
|||
mCheatsNeedSaving = true; |
|||
load(); |
|||
|
|||
notifyCheatUpdated(mSelectedCheatPosition); |
|||
setSelectedCheat(mCheats[mSelectedCheatPosition], mSelectedCheatPosition); |
|||
} |
|||
|
|||
/** |
|||
* When a cheat is deleted, the integer stored in the returned LiveData |
|||
* changes to the position of that cheat, then changes back to null. |
|||
*/ |
|||
public LiveData<Integer> getCheatDeletedEvent() { |
|||
return mCheatDeletedEvent; |
|||
} |
|||
|
|||
/** |
|||
* Notifies that the cheat at the given position has been deleted. |
|||
*/ |
|||
private void notifyCheatDeleted(int position) { |
|||
mCheatDeletedEvent.setValue(position); |
|||
mCheatDeletedEvent.setValue(null); |
|||
} |
|||
|
|||
public void deleteSelectedCheat() { |
|||
int position = mSelectedCheatPosition; |
|||
|
|||
setSelectedCheat(null, -1); |
|||
|
|||
CheatEngine.removeCheat(position); |
|||
|
|||
mCheatsNeedSaving = true; |
|||
load(); |
|||
|
|||
notifyCheatDeleted(position); |
|||
} |
|||
|
|||
public LiveData<Boolean> getOpenDetailsViewEvent() { |
|||
return mOpenDetailsViewEvent; |
|||
} |
|||
|
|||
public void openDetailsView() { |
|||
mOpenDetailsViewEvent.setValue(true); |
|||
mOpenDetailsViewEvent.setValue(false); |
|||
} |
|||
} |
|||
@ -1,174 +0,0 @@ |
|||
package org.citra.citra_emu.features.cheats.ui; |
|||
|
|||
import android.os.Bundle; |
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
import android.widget.Button; |
|||
import android.widget.EditText; |
|||
import android.widget.ScrollView; |
|||
import android.widget.TextView; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.annotation.Nullable; |
|||
import androidx.appcompat.app.AlertDialog; |
|||
import androidx.fragment.app.Fragment; |
|||
import androidx.lifecycle.ViewModelProvider; |
|||
|
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.features.cheats.model.Cheat; |
|||
import org.citra.citra_emu.features.cheats.model.CheatsViewModel; |
|||
|
|||
public class CheatDetailsFragment extends Fragment { |
|||
private View mRoot; |
|||
private ScrollView mScrollView; |
|||
private TextView mLabelName; |
|||
private EditText mEditName; |
|||
private EditText mEditNotes; |
|||
private EditText mEditCode; |
|||
private Button mButtonDelete; |
|||
private Button mButtonEdit; |
|||
private Button mButtonCancel; |
|||
private Button mButtonOk; |
|||
|
|||
private CheatsViewModel mViewModel; |
|||
|
|||
@Nullable |
|||
@Override |
|||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, |
|||
@Nullable Bundle savedInstanceState) { |
|||
return inflater.inflate(R.layout.fragment_cheat_details, container, false); |
|||
} |
|||
|
|||
@Override |
|||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { |
|||
mRoot = view.findViewById(R.id.root); |
|||
mScrollView = view.findViewById(R.id.scroll_view); |
|||
mLabelName = view.findViewById(R.id.label_name); |
|||
mEditName = view.findViewById(R.id.edit_name); |
|||
mEditNotes = view.findViewById(R.id.edit_notes); |
|||
mEditCode = view.findViewById(R.id.edit_code); |
|||
mButtonDelete = view.findViewById(R.id.button_delete); |
|||
mButtonEdit = view.findViewById(R.id.button_edit); |
|||
mButtonCancel = view.findViewById(R.id.button_cancel); |
|||
mButtonOk = view.findViewById(R.id.button_ok); |
|||
|
|||
CheatsActivity activity = (CheatsActivity) requireActivity(); |
|||
mViewModel = new ViewModelProvider(activity).get(CheatsViewModel.class); |
|||
|
|||
mViewModel.getSelectedCheat().observe(getViewLifecycleOwner(), |
|||
this::onSelectedCheatUpdated); |
|||
mViewModel.getIsEditing().observe(getViewLifecycleOwner(), this::onIsEditingUpdated); |
|||
|
|||
mButtonDelete.setOnClickListener(this::onDeleteClicked); |
|||
mButtonEdit.setOnClickListener(this::onEditClicked); |
|||
mButtonCancel.setOnClickListener(this::onCancelClicked); |
|||
mButtonOk.setOnClickListener(this::onOkClicked); |
|||
|
|||
// On a portrait phone screen (or other narrow screen), only one of the two panes are shown |
|||
// at the same time. If the user is navigating using a d-pad and moves focus to an element |
|||
// in the currently hidden pane, we need to manually show that pane. |
|||
CheatsActivity.setOnFocusChangeListenerRecursively(view, |
|||
(v, hasFocus) -> activity.onDetailsViewFocusChange(hasFocus)); |
|||
} |
|||
|
|||
private void clearEditErrors() { |
|||
mEditName.setError(null); |
|||
mEditCode.setError(null); |
|||
} |
|||
|
|||
private void onDeleteClicked(View view) { |
|||
String name = mEditName.getText().toString(); |
|||
|
|||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); |
|||
builder.setMessage(getString(R.string.cheats_delete_confirmation, name)); |
|||
builder.setPositiveButton(android.R.string.yes, |
|||
(dialog, i) -> mViewModel.deleteSelectedCheat()); |
|||
builder.setNegativeButton(android.R.string.no, null); |
|||
builder.show(); |
|||
} |
|||
|
|||
private void onEditClicked(View view) { |
|||
mViewModel.setIsEditing(true); |
|||
mButtonOk.requestFocus(); |
|||
} |
|||
|
|||
private void onCancelClicked(View view) { |
|||
mViewModel.setIsEditing(false); |
|||
onSelectedCheatUpdated(mViewModel.getSelectedCheat().getValue()); |
|||
mButtonDelete.requestFocus(); |
|||
} |
|||
|
|||
private void onOkClicked(View view) { |
|||
clearEditErrors(); |
|||
|
|||
String name = mEditName.getText().toString(); |
|||
String notes = mEditNotes.getText().toString(); |
|||
String code = mEditCode.getText().toString(); |
|||
|
|||
if (name.isEmpty()) { |
|||
mEditName.setError(getString(R.string.cheats_error_no_name)); |
|||
mScrollView.smoothScrollTo(0, mLabelName.getTop()); |
|||
return; |
|||
} else if (code.isEmpty()) { |
|||
mEditCode.setError(getString(R.string.cheats_error_no_code_lines)); |
|||
mScrollView.smoothScrollTo(0, mEditCode.getBottom()); |
|||
return; |
|||
} |
|||
|
|||
int validityResult = Cheat.isValidGatewayCode(code); |
|||
|
|||
if (validityResult != 0) { |
|||
mEditCode.setError(getString(R.string.cheats_error_on_line, validityResult)); |
|||
mScrollView.smoothScrollTo(0, mEditCode.getBottom()); |
|||
return; |
|||
} |
|||
|
|||
Cheat newCheat = Cheat.createGatewayCode(name, notes, code); |
|||
|
|||
if (mViewModel.getIsAdding().getValue()) { |
|||
mViewModel.finishAddingCheat(newCheat); |
|||
} else { |
|||
mViewModel.updateSelectedCheat(newCheat); |
|||
} |
|||
|
|||
mButtonEdit.requestFocus(); |
|||
} |
|||
|
|||
private void onSelectedCheatUpdated(@Nullable Cheat cheat) { |
|||
clearEditErrors(); |
|||
|
|||
boolean isEditing = mViewModel.getIsEditing().getValue(); |
|||
|
|||
mRoot.setVisibility(isEditing || cheat != null ? View.VISIBLE : View.GONE); |
|||
|
|||
// If the fragment was recreated while editing a cheat, it's vital that we |
|||
// don't repopulate the fields, otherwise the user's changes will be lost |
|||
if (!isEditing) { |
|||
if (cheat == null) { |
|||
mEditName.setText(""); |
|||
mEditNotes.setText(""); |
|||
mEditCode.setText(""); |
|||
} else { |
|||
mEditName.setText(cheat.getName()); |
|||
mEditNotes.setText(cheat.getNotes()); |
|||
mEditCode.setText(cheat.getCode()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void onIsEditingUpdated(boolean isEditing) { |
|||
if (isEditing) { |
|||
mRoot.setVisibility(View.VISIBLE); |
|||
} |
|||
|
|||
mEditName.setEnabled(isEditing); |
|||
mEditNotes.setEnabled(isEditing); |
|||
mEditCode.setEnabled(isEditing); |
|||
|
|||
mButtonDelete.setVisibility(isEditing ? View.GONE : View.VISIBLE); |
|||
mButtonEdit.setVisibility(isEditing ? View.GONE : View.VISIBLE); |
|||
mButtonCancel.setVisibility(isEditing ? View.VISIBLE : View.GONE); |
|||
mButtonOk.setVisibility(isEditing ? View.VISIBLE : View.GONE); |
|||
} |
|||
} |
|||
@ -1,46 +0,0 @@ |
|||
package org.citra.citra_emu.features.cheats.ui; |
|||
|
|||
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.fragment.app.Fragment; |
|||
import androidx.lifecycle.ViewModelProvider; |
|||
import androidx.recyclerview.widget.LinearLayoutManager; |
|||
import androidx.recyclerview.widget.RecyclerView; |
|||
|
|||
import com.google.android.material.floatingactionbutton.FloatingActionButton; |
|||
|
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.features.cheats.model.CheatsViewModel; |
|||
import org.citra.citra_emu.ui.DividerItemDecoration; |
|||
|
|||
public class CheatListFragment extends Fragment { |
|||
@Nullable |
|||
@Override |
|||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, |
|||
@Nullable Bundle savedInstanceState) { |
|||
return inflater.inflate(R.layout.fragment_cheat_list, container, false); |
|||
} |
|||
|
|||
@Override |
|||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { |
|||
RecyclerView recyclerView = view.findViewById(R.id.cheat_list); |
|||
FloatingActionButton fab = view.findViewById(R.id.fab); |
|||
|
|||
CheatsActivity activity = (CheatsActivity) requireActivity(); |
|||
CheatsViewModel viewModel = new ViewModelProvider(activity).get(CheatsViewModel.class); |
|||
|
|||
recyclerView.setAdapter(new CheatsAdapter(activity, viewModel)); |
|||
recyclerView.setLayoutManager(new LinearLayoutManager(activity)); |
|||
recyclerView.addItemDecoration(new DividerItemDecoration(activity, null)); |
|||
|
|||
fab.setOnClickListener(v -> { |
|||
viewModel.startAddingCheat(); |
|||
viewModel.openDetailsView(); |
|||
}); |
|||
} |
|||
} |
|||
@ -1,56 +0,0 @@ |
|||
package org.citra.citra_emu.features.cheats.ui; |
|||
|
|||
import android.view.View; |
|||
import android.widget.CheckBox; |
|||
import android.widget.CompoundButton; |
|||
import android.widget.TextView; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.lifecycle.ViewModelProvider; |
|||
import androidx.recyclerview.widget.RecyclerView; |
|||
|
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.features.cheats.model.Cheat; |
|||
import org.citra.citra_emu.features.cheats.model.CheatsViewModel; |
|||
|
|||
public class CheatViewHolder extends RecyclerView.ViewHolder |
|||
implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { |
|||
private final View mRoot; |
|||
private final TextView mName; |
|||
private final CheckBox mCheckbox; |
|||
|
|||
private CheatsViewModel mViewModel; |
|||
private Cheat mCheat; |
|||
private int mPosition; |
|||
|
|||
public CheatViewHolder(@NonNull View itemView) { |
|||
super(itemView); |
|||
|
|||
mRoot = itemView.findViewById(R.id.root); |
|||
mName = itemView.findViewById(R.id.text_name); |
|||
mCheckbox = itemView.findViewById(R.id.checkbox); |
|||
} |
|||
|
|||
public void bind(CheatsActivity activity, Cheat cheat, int position) { |
|||
mCheckbox.setOnCheckedChangeListener(null); |
|||
|
|||
mViewModel = new ViewModelProvider(activity).get(CheatsViewModel.class); |
|||
mCheat = cheat; |
|||
mPosition = position; |
|||
|
|||
mName.setText(mCheat.getName()); |
|||
mCheckbox.setChecked(mCheat.getEnabled()); |
|||
|
|||
mRoot.setOnClickListener(this); |
|||
mCheckbox.setOnCheckedChangeListener(this); |
|||
} |
|||
|
|||
public void onClick(View root) { |
|||
mViewModel.setSelectedCheat(mCheat, mPosition); |
|||
mViewModel.openDetailsView(); |
|||
} |
|||
|
|||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { |
|||
mCheat.setEnabled(isChecked); |
|||
} |
|||
} |
|||
@ -1,161 +0,0 @@ |
|||
package org.citra.citra_emu.features.cheats.ui; |
|||
|
|||
import android.content.Context; |
|||
import android.content.Intent; |
|||
import android.os.Bundle; |
|||
import android.view.Menu; |
|||
import android.view.MenuInflater; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.appcompat.app.AppCompatActivity; |
|||
import androidx.core.view.ViewCompat; |
|||
import androidx.lifecycle.ViewModelProvider; |
|||
import androidx.slidingpanelayout.widget.SlidingPaneLayout; |
|||
|
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.features.cheats.model.Cheat; |
|||
import org.citra.citra_emu.features.cheats.model.CheatsViewModel; |
|||
import org.citra.citra_emu.ui.TwoPaneOnBackPressedCallback; |
|||
|
|||
public class CheatsActivity extends AppCompatActivity |
|||
implements SlidingPaneLayout.PanelSlideListener { |
|||
private CheatsViewModel mViewModel; |
|||
|
|||
private SlidingPaneLayout mSlidingPaneLayout; |
|||
private View mCheatList; |
|||
private View mCheatDetails; |
|||
|
|||
private View mCheatListLastFocus; |
|||
private View mCheatDetailsLastFocus; |
|||
|
|||
public static void launch(Context context) { |
|||
Intent intent = new Intent(context, CheatsActivity.class); |
|||
context.startActivity(intent); |
|||
} |
|||
|
|||
@Override |
|||
protected void onCreate(Bundle savedInstanceState) { |
|||
super.onCreate(savedInstanceState); |
|||
|
|||
mViewModel = new ViewModelProvider(this).get(CheatsViewModel.class); |
|||
mViewModel.load(); |
|||
|
|||
setContentView(R.layout.activity_cheats); |
|||
|
|||
mSlidingPaneLayout = findViewById(R.id.sliding_pane_layout); |
|||
mCheatList = findViewById(R.id.cheat_list); |
|||
mCheatDetails = findViewById(R.id.cheat_details); |
|||
|
|||
mCheatListLastFocus = mCheatList; |
|||
mCheatDetailsLastFocus = mCheatDetails; |
|||
|
|||
mSlidingPaneLayout.addPanelSlideListener(this); |
|||
|
|||
getOnBackPressedDispatcher().addCallback(this, |
|||
new TwoPaneOnBackPressedCallback(mSlidingPaneLayout)); |
|||
|
|||
mViewModel.getSelectedCheat().observe(this, this::onSelectedCheatChanged); |
|||
mViewModel.getIsEditing().observe(this, this::onIsEditingChanged); |
|||
onSelectedCheatChanged(mViewModel.getSelectedCheat().getValue()); |
|||
|
|||
mViewModel.getOpenDetailsViewEvent().observe(this, this::openDetailsView); |
|||
|
|||
// Show "Up" button in the action bar for navigation |
|||
getSupportActionBar().setDisplayHomeAsUpEnabled(true); |
|||
} |
|||
|
|||
@Override |
|||
public boolean onCreateOptionsMenu(Menu menu) { |
|||
MenuInflater inflater = getMenuInflater(); |
|||
inflater.inflate(R.menu.menu_settings, menu); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
@Override |
|||
protected void onStop() { |
|||
super.onStop(); |
|||
|
|||
mViewModel.saveIfNeeded(); |
|||
} |
|||
|
|||
@Override |
|||
public void onPanelSlide(@NonNull View panel, float slideOffset) { |
|||
} |
|||
|
|||
@Override |
|||
public void onPanelOpened(@NonNull View panel) { |
|||
boolean rtl = ViewCompat.getLayoutDirection(panel) == ViewCompat.LAYOUT_DIRECTION_RTL; |
|||
mCheatDetailsLastFocus.requestFocus(rtl ? View.FOCUS_LEFT : View.FOCUS_RIGHT); |
|||
} |
|||
|
|||
@Override |
|||
public void onPanelClosed(@NonNull View panel) { |
|||
boolean rtl = ViewCompat.getLayoutDirection(panel) == ViewCompat.LAYOUT_DIRECTION_RTL; |
|||
mCheatListLastFocus.requestFocus(rtl ? View.FOCUS_RIGHT : View.FOCUS_LEFT); |
|||
} |
|||
|
|||
private void onIsEditingChanged(boolean isEditing) { |
|||
if (isEditing) { |
|||
mSlidingPaneLayout.setLockMode(SlidingPaneLayout.LOCK_MODE_UNLOCKED); |
|||
} |
|||
} |
|||
|
|||
private void onSelectedCheatChanged(Cheat selectedCheat) { |
|||
boolean cheatSelected = selectedCheat != null || mViewModel.getIsEditing().getValue(); |
|||
|
|||
if (!cheatSelected && mSlidingPaneLayout.isOpen()) { |
|||
mSlidingPaneLayout.close(); |
|||
} |
|||
|
|||
mSlidingPaneLayout.setLockMode(cheatSelected ? |
|||
SlidingPaneLayout.LOCK_MODE_UNLOCKED : SlidingPaneLayout.LOCK_MODE_LOCKED_CLOSED); |
|||
} |
|||
|
|||
public void onListViewFocusChange(boolean hasFocus) { |
|||
if (hasFocus) { |
|||
mCheatListLastFocus = mCheatList.findFocus(); |
|||
if (mCheatListLastFocus == null) |
|||
throw new NullPointerException(); |
|||
|
|||
mSlidingPaneLayout.close(); |
|||
} |
|||
} |
|||
|
|||
public void onDetailsViewFocusChange(boolean hasFocus) { |
|||
if (hasFocus) { |
|||
mCheatDetailsLastFocus = mCheatDetails.findFocus(); |
|||
if (mCheatDetailsLastFocus == null) |
|||
throw new NullPointerException(); |
|||
|
|||
mSlidingPaneLayout.open(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public boolean onSupportNavigateUp() { |
|||
onBackPressed(); |
|||
return true; |
|||
} |
|||
|
|||
private void openDetailsView(boolean open) { |
|||
if (open) { |
|||
mSlidingPaneLayout.open(); |
|||
} |
|||
} |
|||
|
|||
public static void setOnFocusChangeListenerRecursively(@NonNull View view, |
|||
View.OnFocusChangeListener listener) { |
|||
view.setOnFocusChangeListener(listener); |
|||
|
|||
if (view instanceof ViewGroup) { |
|||
ViewGroup viewGroup = (ViewGroup) view; |
|||
for (int i = 0; i < viewGroup.getChildCount(); i++) { |
|||
View child = viewGroup.getChildAt(i); |
|||
setOnFocusChangeListenerRecursively(child, listener); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,72 +0,0 @@ |
|||
package org.citra.citra_emu.features.cheats.ui; |
|||
|
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.recyclerview.widget.RecyclerView; |
|||
|
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.features.cheats.model.Cheat; |
|||
import org.citra.citra_emu.features.cheats.model.CheatsViewModel; |
|||
|
|||
public class CheatsAdapter extends RecyclerView.Adapter<CheatViewHolder> { |
|||
private final CheatsActivity mActivity; |
|||
private final CheatsViewModel mViewModel; |
|||
|
|||
public CheatsAdapter(CheatsActivity activity, CheatsViewModel viewModel) { |
|||
mActivity = activity; |
|||
mViewModel = viewModel; |
|||
|
|||
mViewModel.getCheatAddedEvent().observe(activity, (position) -> { |
|||
if (position != null) { |
|||
notifyItemInserted(position); |
|||
} |
|||
}); |
|||
|
|||
mViewModel.getCheatUpdatedEvent().observe(activity, (position) -> { |
|||
if (position != null) { |
|||
notifyItemChanged(position); |
|||
} |
|||
}); |
|||
|
|||
mViewModel.getCheatDeletedEvent().observe(activity, (position) -> { |
|||
if (position != null) { |
|||
notifyItemRemoved(position); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
@NonNull |
|||
@Override |
|||
public CheatViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { |
|||
LayoutInflater inflater = LayoutInflater.from(parent.getContext()); |
|||
|
|||
View cheatView = inflater.inflate(R.layout.list_item_cheat, parent, false); |
|||
addViewListeners(cheatView); |
|||
return new CheatViewHolder(cheatView); |
|||
} |
|||
|
|||
@Override |
|||
public void onBindViewHolder(@NonNull CheatViewHolder holder, int position) { |
|||
holder.bind(mActivity, getItemAt(position), position); |
|||
} |
|||
|
|||
@Override |
|||
public int getItemCount() { |
|||
return mViewModel.getCheats().length; |
|||
} |
|||
|
|||
private void addViewListeners(View view) { |
|||
// On a portrait phone screen (or other narrow screen), only one of the two panes are shown |
|||
// at the same time. If the user is navigating using a d-pad and moves focus to an element |
|||
// in the currently hidden pane, we need to manually show that pane. |
|||
CheatsActivity.setOnFocusChangeListenerRecursively(view, |
|||
(v, hasFocus) -> mActivity.onListViewFocusChange(hasFocus)); |
|||
} |
|||
|
|||
private Cheat getItemAt(int position) { |
|||
return mViewModel.getCheats()[position]; |
|||
} |
|||
} |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.features.settings.model; |
|||
package org.yuzu.yuzu_emu.features.settings.model; |
|||
|
|||
public final class BooleanSetting extends Setting { |
|||
private boolean mValue; |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.features.settings.model; |
|||
package org.yuzu.yuzu_emu.features.settings.model; |
|||
|
|||
public final class FloatSetting extends Setting { |
|||
private float mValue; |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.features.settings.model; |
|||
package org.yuzu.yuzu_emu.features.settings.model; |
|||
|
|||
public final class IntSetting extends Setting { |
|||
private int mValue; |
|||
@ -1,7 +1,7 @@ |
|||
package org.citra.citra_emu.features.settings.model; |
|||
package org.yuzu.yuzu_emu.features.settings.model; |
|||
|
|||
/** |
|||
* Abstraction for a setting item as read from / written to Citra's configuration ini files. |
|||
* Abstraction for a setting item as read from / written to yuzu's configuration ini files. |
|||
* These files generally consist of a key/value pair, though the type of value is ambiguous and |
|||
* must be inferred at read-time. The type of value determines which child of this class is used |
|||
* to represent the Setting. |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.features.settings.model; |
|||
package org.yuzu.yuzu_emu.features.settings.model; |
|||
|
|||
import java.util.HashMap; |
|||
|
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.features.settings.model; |
|||
package org.yuzu.yuzu_emu.features.settings.model; |
|||
|
|||
public final class StringSetting extends Setting { |
|||
private String mValue; |
|||
@ -1,7 +1,7 @@ |
|||
package org.citra.citra_emu.features.settings.model.view; |
|||
package org.yuzu.yuzu_emu.features.settings.model.view; |
|||
|
|||
import org.citra.citra_emu.features.settings.model.Setting; |
|||
import org.citra.citra_emu.features.settings.model.StringSetting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.Setting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting; |
|||
|
|||
public final class DateTimeSetting extends SettingsItem { |
|||
private String mDefaultValue; |
|||
@ -1,6 +1,6 @@ |
|||
package org.citra.citra_emu.features.settings.model.view; |
|||
package org.yuzu.yuzu_emu.features.settings.model.view; |
|||
|
|||
import org.citra.citra_emu.features.settings.model.Setting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.Setting; |
|||
|
|||
public final class HeaderSetting extends SettingsItem { |
|||
public HeaderSetting(String key, Setting setting, int titleId, int descriptionId) { |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.features.settings.model.view; |
|||
package org.yuzu.yuzu_emu.features.settings.model.view; |
|||
|
|||
public final class PremiumHeader extends SettingsItem { |
|||
public PremiumHeader() { |
|||
@ -1,8 +1,8 @@ |
|||
package org.citra.citra_emu.features.settings.model.view; |
|||
package org.yuzu.yuzu_emu.features.settings.model.view; |
|||
|
|||
import org.citra.citra_emu.features.settings.model.Setting; |
|||
import org.citra.citra_emu.features.settings.model.Settings; |
|||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter; |
|||
import org.yuzu.yuzu_emu.features.settings.model.Setting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.Settings; |
|||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter; |
|||
|
|||
/** |
|||
* ViewModel abstraction for an Item in the RecyclerView powering SettingsFragments. |
|||
@ -1,7 +1,7 @@ |
|||
package org.citra.citra_emu.features.settings.model.view; |
|||
package org.yuzu.yuzu_emu.features.settings.model.view; |
|||
|
|||
import org.citra.citra_emu.features.settings.model.IntSetting; |
|||
import org.citra.citra_emu.features.settings.model.Setting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.IntSetting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.Setting; |
|||
|
|||
public final class SingleChoiceSetting extends SettingsItem { |
|||
private int mDefaultValue; |
|||
@ -1,9 +1,9 @@ |
|||
package org.citra.citra_emu.features.settings.model.view; |
|||
package org.yuzu.yuzu_emu.features.settings.model.view; |
|||
|
|||
import org.citra.citra_emu.features.settings.model.FloatSetting; |
|||
import org.citra.citra_emu.features.settings.model.IntSetting; |
|||
import org.citra.citra_emu.features.settings.model.Setting; |
|||
import org.citra.citra_emu.utils.Log; |
|||
import org.yuzu.yuzu_emu.features.settings.model.FloatSetting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.IntSetting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.Setting; |
|||
import org.yuzu.yuzu_emu.utils.Log; |
|||
|
|||
public final class SliderSetting extends SettingsItem { |
|||
private int mMin; |
|||
@ -1,7 +1,7 @@ |
|||
package org.citra.citra_emu.features.settings.model.view; |
|||
package org.yuzu.yuzu_emu.features.settings.model.view; |
|||
|
|||
import org.citra.citra_emu.features.settings.model.Setting; |
|||
import org.citra.citra_emu.features.settings.model.StringSetting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.Setting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting; |
|||
|
|||
public class StringSingleChoiceSetting extends SettingsItem { |
|||
private String mDefaultValue; |
|||
@ -1,6 +1,6 @@ |
|||
package org.citra.citra_emu.features.settings.model.view; |
|||
package org.yuzu.yuzu_emu.features.settings.model.view; |
|||
|
|||
import org.citra.citra_emu.features.settings.model.Setting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.Setting; |
|||
|
|||
public final class SubmenuSetting extends SettingsItem { |
|||
private String mMenuKey; |
|||
@ -1,9 +1,9 @@ |
|||
package org.citra.citra_emu.features.settings.ui; |
|||
package org.yuzu.yuzu_emu.features.settings.ui; |
|||
|
|||
import android.content.IntentFilter; |
|||
|
|||
import org.citra.citra_emu.features.settings.model.Settings; |
|||
import org.citra.citra_emu.utils.DirectoryStateReceiver; |
|||
import org.yuzu.yuzu_emu.features.settings.model.Settings; |
|||
import org.yuzu.yuzu_emu.utils.DirectoryStateReceiver; |
|||
|
|||
/** |
|||
* Abstraction for the Activity that manages SettingsFragments. |
|||
@ -1,10 +1,10 @@ |
|||
package org.citra.citra_emu.features.settings.ui; |
|||
package org.yuzu.yuzu_emu.features.settings.ui; |
|||
|
|||
import androidx.fragment.app.FragmentActivity; |
|||
|
|||
import org.citra.citra_emu.features.settings.model.Setting; |
|||
import org.citra.citra_emu.features.settings.model.Settings; |
|||
import org.citra.citra_emu.features.settings.model.view.SettingsItem; |
|||
import org.yuzu.yuzu_emu.features.settings.model.Setting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.Settings; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem; |
|||
|
|||
import java.util.ArrayList; |
|||
|
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.features.settings.ui; |
|||
package org.yuzu.yuzu_emu.features.settings.ui; |
|||
|
|||
import android.content.Context; |
|||
import android.util.AttributeSet; |
|||
@ -1,13 +1,13 @@ |
|||
package org.citra.citra_emu.features.settings.ui.viewholder; |
|||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder; |
|||
|
|||
import android.view.View; |
|||
import android.widget.CheckBox; |
|||
import android.widget.TextView; |
|||
|
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.features.settings.model.view.CheckBoxSetting; |
|||
import org.citra.citra_emu.features.settings.model.view.SettingsItem; |
|||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter; |
|||
import org.yuzu.yuzu_emu.R; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.CheckBoxSetting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem; |
|||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter; |
|||
|
|||
public final class CheckBoxSettingViewHolder extends SettingViewHolder { |
|||
private CheckBoxSetting mItem; |
|||
@ -1,13 +1,13 @@ |
|||
package org.citra.citra_emu.features.settings.ui.viewholder; |
|||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder; |
|||
|
|||
import android.view.View; |
|||
import android.widget.TextView; |
|||
|
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.features.settings.model.view.DateTimeSetting; |
|||
import org.citra.citra_emu.features.settings.model.view.SettingsItem; |
|||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter; |
|||
import org.citra.citra_emu.utils.Log; |
|||
import org.yuzu.yuzu_emu.R; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.DateTimeSetting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem; |
|||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter; |
|||
import org.yuzu.yuzu_emu.utils.Log; |
|||
|
|||
public final class DateTimeViewHolder extends SettingViewHolder { |
|||
private DateTimeSetting mItem; |
|||
@ -1,11 +1,11 @@ |
|||
package org.citra.citra_emu.features.settings.ui.viewholder; |
|||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder; |
|||
|
|||
import android.view.View; |
|||
import android.widget.TextView; |
|||
|
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.features.settings.model.view.SettingsItem; |
|||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter; |
|||
import org.yuzu.yuzu_emu.R; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem; |
|||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter; |
|||
|
|||
public final class HeaderViewHolder extends SettingViewHolder { |
|||
private TextView mHeaderName; |
|||
@ -1,13 +1,13 @@ |
|||
package org.citra.citra_emu.features.settings.ui.viewholder; |
|||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder; |
|||
|
|||
import android.view.View; |
|||
import android.widget.TextView; |
|||
|
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.features.settings.model.view.SettingsItem; |
|||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter; |
|||
import org.citra.citra_emu.features.settings.ui.SettingsFragmentView; |
|||
import org.citra.citra_emu.ui.main.MainActivity; |
|||
import org.yuzu.yuzu_emu.R; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem; |
|||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter; |
|||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsFragmentView; |
|||
import org.yuzu.yuzu_emu.ui.main.MainActivity; |
|||
|
|||
public final class PremiumViewHolder extends SettingViewHolder { |
|||
private TextView mHeaderName; |
|||
@ -1,11 +1,11 @@ |
|||
package org.citra.citra_emu.features.settings.ui.viewholder; |
|||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder; |
|||
|
|||
import android.view.View; |
|||
|
|||
import androidx.recyclerview.widget.RecyclerView; |
|||
|
|||
import org.citra.citra_emu.features.settings.model.view.SettingsItem; |
|||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem; |
|||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter; |
|||
|
|||
public abstract class SettingViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { |
|||
private SettingsAdapter mAdapter; |
|||
@ -1,15 +1,15 @@ |
|||
package org.citra.citra_emu.features.settings.ui.viewholder; |
|||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder; |
|||
|
|||
import android.content.res.Resources; |
|||
import android.view.View; |
|||
import android.widget.TextView; |
|||
|
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.features.settings.model.view.PremiumSingleChoiceSetting; |
|||
import org.citra.citra_emu.features.settings.model.view.SettingsItem; |
|||
import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting; |
|||
import org.citra.citra_emu.features.settings.model.view.StringSingleChoiceSetting; |
|||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter; |
|||
import org.yuzu.yuzu_emu.R; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.PremiumSingleChoiceSetting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting; |
|||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter; |
|||
|
|||
public final class SingleChoiceViewHolder extends SettingViewHolder { |
|||
private SettingsItem mItem; |
|||
@ -1,12 +1,12 @@ |
|||
package org.citra.citra_emu.features.settings.ui.viewholder; |
|||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder; |
|||
|
|||
import android.view.View; |
|||
import android.widget.TextView; |
|||
|
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.features.settings.model.view.SettingsItem; |
|||
import org.citra.citra_emu.features.settings.model.view.SliderSetting; |
|||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter; |
|||
import org.yuzu.yuzu_emu.R; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting; |
|||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter; |
|||
|
|||
public final class SliderViewHolder extends SettingViewHolder { |
|||
private SliderSetting mItem; |
|||
@ -1,12 +1,12 @@ |
|||
package org.citra.citra_emu.features.settings.ui.viewholder; |
|||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder; |
|||
|
|||
import android.view.View; |
|||
import android.widget.TextView; |
|||
|
|||
import org.citra.citra_emu.R; |
|||
import org.citra.citra_emu.features.settings.model.view.SettingsItem; |
|||
import org.citra.citra_emu.features.settings.model.view.SubmenuSetting; |
|||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter; |
|||
import org.yuzu.yuzu_emu.R; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem; |
|||
import org.yuzu.yuzu_emu.features.settings.model.view.SubmenuSetting; |
|||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter; |
|||
|
|||
public final class SubmenuViewHolder extends SettingViewHolder { |
|||
private SubmenuSetting mItem; |
|||
@ -0,0 +1,129 @@ |
|||
package org.yuzu.yuzu_emu.fragments; |
|||
|
|||
import android.content.pm.PackageManager; |
|||
import android.graphics.Rect; |
|||
import android.os.Bundle; |
|||
import android.util.SparseIntArray; |
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
import android.widget.Button; |
|||
import android.widget.LinearLayout; |
|||
|
|||
import androidx.annotation.ColorInt; |
|||
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.Fragment; |
|||
|
|||
import com.google.android.material.color.MaterialColors; |
|||
import com.google.android.material.elevation.ElevationOverlayProvider; |
|||
|
|||
import org.yuzu.yuzu_emu.R; |
|||
import org.yuzu.yuzu_emu.activities.EmulationActivity; |
|||
|
|||
|
|||
public final class MenuFragment extends Fragment implements View.OnClickListener |
|||
{ |
|||
private static final String KEY_TITLE = "title"; |
|||
private static final String KEY_WII = "wii"; |
|||
private static SparseIntArray buttonsActionsMap = new SparseIntArray(); |
|||
|
|||
private int mCutInset = 0; |
|||
|
|||
static |
|||
{ |
|||
buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT); |
|||
} |
|||
|
|||
public static MenuFragment newInstance() |
|||
{ |
|||
MenuFragment fragment = new MenuFragment(); |
|||
|
|||
Bundle arguments = new Bundle(); |
|||
fragment.setArguments(arguments); |
|||
|
|||
return fragment; |
|||
} |
|||
|
|||
// This is primarily intended to account for any navigation bar at the bottom of the screen |
|||
private int getBottomPaddingRequired() |
|||
{ |
|||
Rect visibleFrame = new Rect(); |
|||
requireActivity().getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleFrame); |
|||
return visibleFrame.bottom - visibleFrame.top - getResources().getDisplayMetrics().heightPixels; |
|||
} |
|||
|
|||
@NonNull |
|||
@Override |
|||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, |
|||
Bundle savedInstanceState) |
|||
{ |
|||
View rootView = inflater.inflate(R.layout.fragment_ingame_menu, container, false); |
|||
|
|||
LinearLayout options = rootView.findViewById(R.id.layout_options); |
|||
|
|||
// mPauseEmulation = options.findViewById(R.id.menu_pause_emulation); |
|||
// mUnpauseEmulation = options.findViewById(R.id.menu_unpause_emulation); |
|||
// |
|||
// updatePauseUnpauseVisibility(); |
|||
// |
|||
// if (!requireActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) |
|||
// { |
|||
// options.findViewById(R.id.menu_overlay_controls).setVisibility(View.GONE); |
|||
// } |
|||
// |
|||
// if (!getArguments().getBoolean(KEY_WII, true)) |
|||
// { |
|||
// options.findViewById(R.id.menu_refresh_wiimotes).setVisibility(View.GONE); |
|||
// } |
|||
|
|||
int bottomPaddingRequired = getBottomPaddingRequired(); |
|||
|
|||
// Provide a safe zone between the navigation bar and Exit Emulation to avoid accidental touches |
|||
float density = getResources().getDisplayMetrics().density; |
|||
if (bottomPaddingRequired >= 32 * density) |
|||
{ |
|||
bottomPaddingRequired += 32 * density; |
|||
} |
|||
|
|||
if (bottomPaddingRequired > rootView.getPaddingBottom()) |
|||
{ |
|||
rootView.setPadding(rootView.getPaddingLeft(), rootView.getPaddingTop(), |
|||
rootView.getPaddingRight(), bottomPaddingRequired); |
|||
} |
|||
|
|||
for (int childIndex = 0; childIndex < options.getChildCount(); childIndex++) |
|||
{ |
|||
Button button = (Button) options.getChildAt(childIndex); |
|||
|
|||
button.setOnClickListener(this); |
|||
} |
|||
|
|||
rootView.findViewById(R.id.menu_exit).setOnClickListener(this); |
|||
|
|||
// mTitleText = rootView.findViewById(R.id.text_game_title); |
|||
// String title = getArguments().getString(KEY_TITLE, null); |
|||
// if (title != null) |
|||
// { |
|||
// mTitleText.setText(title); |
|||
// } |
|||
|
|||
if (getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) |
|||
{ |
|||
// rootView.post(() -> NativeLibrary.SetObscuredPixelsLeft(rootView.getWidth())); |
|||
} |
|||
|
|||
return rootView; |
|||
} |
|||
|
|||
@Override |
|||
public void onClick(View button) |
|||
{ |
|||
int action = buttonsActionsMap.get(button.getId()); |
|||
EmulationActivity activity = (EmulationActivity) requireActivity(); |
|||
activity.handleMenuAction(action); |
|||
} |
|||
} |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.model; |
|||
package org.yuzu.yuzu_emu.model; |
|||
|
|||
import android.content.ContentValues; |
|||
import android.database.Cursor; |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.ui; |
|||
package org.yuzu.yuzu_emu.ui; |
|||
|
|||
import android.content.Context; |
|||
import android.content.res.TypedArray; |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.ui; |
|||
package org.yuzu.yuzu_emu.ui; |
|||
|
|||
import android.view.View; |
|||
|
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.ui.main; |
|||
package org.yuzu.yuzu_emu.ui.main; |
|||
|
|||
/** |
|||
* Abstraction for the screen that shows on application launch. |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.ui.platform; |
|||
package org.yuzu.yuzu_emu.ui.platform; |
|||
|
|||
import android.database.Cursor; |
|||
|
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.utils; |
|||
package org.yuzu.yuzu_emu.utils; |
|||
|
|||
public interface Action1<T> { |
|||
void call(T t); |
|||
@ -1,12 +1,12 @@ |
|||
package org.citra.citra_emu.utils; |
|||
package org.yuzu.yuzu_emu.utils; |
|||
|
|||
import android.content.AsyncQueryHandler; |
|||
import android.content.ContentValues; |
|||
import android.content.Context; |
|||
import android.net.Uri; |
|||
|
|||
import org.citra.citra_emu.model.GameDatabase; |
|||
import org.citra.citra_emu.model.GameProvider; |
|||
import org.yuzu.yuzu_emu.model.GameDatabase; |
|||
import org.yuzu.yuzu_emu.model.GameProvider; |
|||
|
|||
public class AddDirectoryHelper { |
|||
private Context mContext; |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.utils; |
|||
package org.yuzu.yuzu_emu.utils; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.utils; |
|||
package org.yuzu.yuzu_emu.utils; |
|||
|
|||
import android.view.InputDevice; |
|||
import android.view.KeyEvent; |
|||
@ -1,10 +1,10 @@ |
|||
package org.citra.citra_emu.utils; |
|||
package org.yuzu.yuzu_emu.utils; |
|||
|
|||
import android.content.BroadcastReceiver; |
|||
import android.content.Context; |
|||
import android.content.Intent; |
|||
|
|||
import org.citra.citra_emu.utils.DirectoryInitialization.DirectoryInitializationState; |
|||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization.DirectoryInitializationState; |
|||
|
|||
public class DirectoryStateReceiver extends BroadcastReceiver { |
|||
Action1<DirectoryInitializationState> callback; |
|||
@ -1,12 +1,12 @@ |
|||
package org.citra.citra_emu.utils; |
|||
package org.yuzu.yuzu_emu.utils; |
|||
|
|||
import android.content.SharedPreferences; |
|||
import android.preference.PreferenceManager; |
|||
|
|||
import org.citra.citra_emu.CitraApplication; |
|||
import org.yuzu.yuzu_emu.YuzuApplication; |
|||
|
|||
public class EmulationMenuSettings { |
|||
private static SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(CitraApplication.getAppContext()); |
|||
private static SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.getAppContext()); |
|||
|
|||
// These must match what is defined in src/core/settings.h |
|||
public static final int LayoutOption_Default = 0; |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.utils; |
|||
package org.yuzu.yuzu_emu.utils; |
|||
|
|||
import java.io.File; |
|||
import java.io.FileInputStream; |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.utils; |
|||
package org.yuzu.yuzu_emu.utils; |
|||
|
|||
import android.annotation.TargetApi; |
|||
import android.content.Context; |
|||
@ -1,4 +1,4 @@ |
|||
package org.citra.citra_emu.utils; |
|||
package org.yuzu.yuzu_emu.utils; |
|||
|
|||
import android.graphics.Bitmap; |
|||
import android.graphics.BitmapShader; |
|||
@ -0,0 +1,20 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<set xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
|
|||
<objectAnimator |
|||
android:propertyName="translationX" |
|||
android:valueType="floatType" |
|||
android:valueFrom="1280dp" |
|||
android:valueTo="0" |
|||
android:interpolator="@android:interpolator/decelerate_quad" |
|||
android:duration="300"/> |
|||
|
|||
<objectAnimator |
|||
android:propertyName="alpha" |
|||
android:valueType="floatType" |
|||
android:valueFrom="0" |
|||
android:valueTo="1" |
|||
android:interpolator="@android:interpolator/accelerate_quad" |
|||
android:duration="300"/> |
|||
|
|||
</set> |
|||
@ -0,0 +1,20 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<set xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
|
|||
<objectAnimator |
|||
android:propertyName="translationX" |
|||
android:valueType="floatType" |
|||
android:valueFrom="-1280dp" |
|||
android:valueTo="0" |
|||
android:interpolator="@android:interpolator/decelerate_quad" |
|||
android:duration="300"/> |
|||
|
|||
<objectAnimator |
|||
android:propertyName="alpha" |
|||
android:valueType="floatType" |
|||
android:valueFrom="0" |
|||
android:valueTo="1" |
|||
android:interpolator="@android:interpolator/accelerate_quad" |
|||
android:duration="300"/> |
|||
|
|||
</set> |
|||
@ -0,0 +1,21 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<set xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
|
|||
<!-- This animation is used ONLY when a submenu is replaced. --> |
|||
<objectAnimator |
|||
android:propertyName="translationX" |
|||
android:valueType="floatType" |
|||
android:valueFrom="0" |
|||
android:valueTo="1280dp" |
|||
android:interpolator="@android:interpolator/decelerate_quad" |
|||
android:duration="200"/> |
|||
|
|||
<objectAnimator |
|||
android:propertyName="alpha" |
|||
android:valueType="floatType" |
|||
android:valueFrom="1" |
|||
android:valueTo="0" |
|||
android:interpolator="@android:interpolator/decelerate_quad" |
|||
android:duration="200"/> |
|||
|
|||
</set> |
|||
@ -0,0 +1,21 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<set xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
|
|||
<!-- This animation is used ONLY when a submenu is replaced. --> |
|||
<objectAnimator |
|||
android:propertyName="translationX" |
|||
android:valueType="floatType" |
|||
android:valueFrom="0" |
|||
android:valueTo="-1280dp" |
|||
android:interpolator="@android:interpolator/decelerate_quad" |
|||
android:duration="200"/> |
|||
|
|||
<objectAnimator |
|||
android:propertyName="alpha" |
|||
android:valueType="floatType" |
|||
android:valueFrom="1" |
|||
android:valueTo="0" |
|||
android:interpolator="@android:interpolator/decelerate_quad" |
|||
android:duration="200"/> |
|||
|
|||
</set> |
|||
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue