mirror of https://git.suyu.dev/suyu/suyu
android: Minimize frontend & convert to yuzu.
parent
18527a8c42
commit
5e198d1421
@ -1,3 +1,3 @@
|
|||||||
package org.citra.citra_emu;
|
package org.yuzu.yuzu_emu;
|
||||||
|
|
||||||
import android.content.Context;
|
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 {
|
public final class BooleanSetting extends Setting {
|
||||||
private boolean mValue;
|
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 {
|
public final class FloatSetting extends Setting {
|
||||||
private float mValue;
|
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 {
|
public final class IntSetting extends Setting {
|
||||||
private int mValue;
|
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
|
* 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
|
* must be inferred at read-time. The type of value determines which child of this class is used
|
||||||
* to represent the Setting.
|
* 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;
|
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 {
|
public final class StringSetting extends Setting {
|
||||||
private String mValue;
|
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.yuzu.yuzu_emu.features.settings.model.Setting;
|
||||||
import org.citra.citra_emu.features.settings.model.StringSetting;
|
import org.yuzu.yuzu_emu.features.settings.model.StringSetting;
|
||||||
|
|
||||||
public final class DateTimeSetting extends SettingsItem {
|
public final class DateTimeSetting extends SettingsItem {
|
||||||
private String mDefaultValue;
|
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 final class HeaderSetting extends SettingsItem {
|
||||||
public HeaderSetting(String key, Setting setting, int titleId, int descriptionId) {
|
public HeaderSetting(String key, Setting setting, int titleId, int descriptionId) {
|
@ -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 final class PremiumHeader extends SettingsItem {
|
||||||
public PremiumHeader() {
|
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.yuzu.yuzu_emu.features.settings.model.Setting;
|
||||||
import org.citra.citra_emu.features.settings.model.Settings;
|
import org.yuzu.yuzu_emu.features.settings.model.Settings;
|
||||||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter;
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ViewModel abstraction for an Item in the RecyclerView powering SettingsFragments.
|
* 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.yuzu.yuzu_emu.features.settings.model.IntSetting;
|
||||||
import org.citra.citra_emu.features.settings.model.Setting;
|
import org.yuzu.yuzu_emu.features.settings.model.Setting;
|
||||||
|
|
||||||
public final class SingleChoiceSetting extends SettingsItem {
|
public final class SingleChoiceSetting extends SettingsItem {
|
||||||
private int mDefaultValue;
|
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.yuzu.yuzu_emu.features.settings.model.FloatSetting;
|
||||||
import org.citra.citra_emu.features.settings.model.IntSetting;
|
import org.yuzu.yuzu_emu.features.settings.model.IntSetting;
|
||||||
import org.citra.citra_emu.features.settings.model.Setting;
|
import org.yuzu.yuzu_emu.features.settings.model.Setting;
|
||||||
import org.citra.citra_emu.utils.Log;
|
import org.yuzu.yuzu_emu.utils.Log;
|
||||||
|
|
||||||
public final class SliderSetting extends SettingsItem {
|
public final class SliderSetting extends SettingsItem {
|
||||||
private int mMin;
|
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.yuzu.yuzu_emu.features.settings.model.Setting;
|
||||||
import org.citra.citra_emu.features.settings.model.StringSetting;
|
import org.yuzu.yuzu_emu.features.settings.model.StringSetting;
|
||||||
|
|
||||||
public class StringSingleChoiceSetting extends SettingsItem {
|
public class StringSingleChoiceSetting extends SettingsItem {
|
||||||
private String mDefaultValue;
|
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 {
|
public final class SubmenuSetting extends SettingsItem {
|
||||||
private String mMenuKey;
|
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 android.content.IntentFilter;
|
||||||
|
|
||||||
import org.citra.citra_emu.features.settings.model.Settings;
|
import org.yuzu.yuzu_emu.features.settings.model.Settings;
|
||||||
import org.citra.citra_emu.utils.DirectoryStateReceiver;
|
import org.yuzu.yuzu_emu.utils.DirectoryStateReceiver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstraction for the Activity that manages SettingsFragments.
|
* 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 androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
import org.citra.citra_emu.features.settings.model.Setting;
|
import org.yuzu.yuzu_emu.features.settings.model.Setting;
|
||||||
import org.citra.citra_emu.features.settings.model.Settings;
|
import org.yuzu.yuzu_emu.features.settings.model.Settings;
|
||||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem;
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
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.content.Context;
|
||||||
import android.util.AttributeSet;
|
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.view.View;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.citra.citra_emu.R;
|
import org.yuzu.yuzu_emu.R;
|
||||||
import org.citra.citra_emu.features.settings.model.view.CheckBoxSetting;
|
import org.yuzu.yuzu_emu.features.settings.model.view.CheckBoxSetting;
|
||||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem;
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem;
|
||||||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter;
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter;
|
||||||
|
|
||||||
public final class CheckBoxSettingViewHolder extends SettingViewHolder {
|
public final class CheckBoxSettingViewHolder extends SettingViewHolder {
|
||||||
private CheckBoxSetting mItem;
|
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.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.citra.citra_emu.R;
|
import org.yuzu.yuzu_emu.R;
|
||||||
import org.citra.citra_emu.features.settings.model.view.DateTimeSetting;
|
import org.yuzu.yuzu_emu.features.settings.model.view.DateTimeSetting;
|
||||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem;
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem;
|
||||||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter;
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter;
|
||||||
import org.citra.citra_emu.utils.Log;
|
import org.yuzu.yuzu_emu.utils.Log;
|
||||||
|
|
||||||
public final class DateTimeViewHolder extends SettingViewHolder {
|
public final class DateTimeViewHolder extends SettingViewHolder {
|
||||||
private DateTimeSetting mItem;
|
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.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.citra.citra_emu.R;
|
import org.yuzu.yuzu_emu.R;
|
||||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem;
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem;
|
||||||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter;
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter;
|
||||||
|
|
||||||
public final class HeaderViewHolder extends SettingViewHolder {
|
public final class HeaderViewHolder extends SettingViewHolder {
|
||||||
private TextView mHeaderName;
|
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.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.citra.citra_emu.R;
|
import org.yuzu.yuzu_emu.R;
|
||||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem;
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem;
|
||||||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter;
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter;
|
||||||
import org.citra.citra_emu.features.settings.ui.SettingsFragmentView;
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsFragmentView;
|
||||||
import org.citra.citra_emu.ui.main.MainActivity;
|
import org.yuzu.yuzu_emu.ui.main.MainActivity;
|
||||||
|
|
||||||
public final class PremiumViewHolder extends SettingViewHolder {
|
public final class PremiumViewHolder extends SettingViewHolder {
|
||||||
private TextView mHeaderName;
|
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 android.view.View;
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem;
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem;
|
||||||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter;
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter;
|
||||||
|
|
||||||
public abstract class SettingViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
public abstract class SettingViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||||
private SettingsAdapter mAdapter;
|
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.content.res.Resources;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.citra.citra_emu.R;
|
import org.yuzu.yuzu_emu.R;
|
||||||
import org.citra.citra_emu.features.settings.model.view.PremiumSingleChoiceSetting;
|
import org.yuzu.yuzu_emu.features.settings.model.view.PremiumSingleChoiceSetting;
|
||||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem;
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem;
|
||||||
import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting;
|
import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting;
|
||||||
import org.citra.citra_emu.features.settings.model.view.StringSingleChoiceSetting;
|
import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting;
|
||||||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter;
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter;
|
||||||
|
|
||||||
public final class SingleChoiceViewHolder extends SettingViewHolder {
|
public final class SingleChoiceViewHolder extends SettingViewHolder {
|
||||||
private SettingsItem mItem;
|
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.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.citra.citra_emu.R;
|
import org.yuzu.yuzu_emu.R;
|
||||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem;
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem;
|
||||||
import org.citra.citra_emu.features.settings.model.view.SliderSetting;
|
import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting;
|
||||||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter;
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter;
|
||||||
|
|
||||||
public final class SliderViewHolder extends SettingViewHolder {
|
public final class SliderViewHolder extends SettingViewHolder {
|
||||||
private SliderSetting mItem;
|
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.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.citra.citra_emu.R;
|
import org.yuzu.yuzu_emu.R;
|
||||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem;
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem;
|
||||||
import org.citra.citra_emu.features.settings.model.view.SubmenuSetting;
|
import org.yuzu.yuzu_emu.features.settings.model.view.SubmenuSetting;
|
||||||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter;
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter;
|
||||||
|
|
||||||
public final class SubmenuViewHolder extends SettingViewHolder {
|
public final class SubmenuViewHolder extends SettingViewHolder {
|
||||||
private SubmenuSetting mItem;
|
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.content.ContentValues;
|
||||||
import android.database.Cursor;
|
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.Context;
|
||||||
import android.content.res.TypedArray;
|
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;
|
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.
|
* 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;
|
import android.database.Cursor;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.citra.citra_emu.utils;
|
package org.yuzu.yuzu_emu.utils;
|
||||||
|
|
||||||
public interface Action1<T> {
|
public interface Action1<T> {
|
||||||
void call(T 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.AsyncQueryHandler;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import org.citra.citra_emu.model.GameDatabase;
|
import org.yuzu.yuzu_emu.model.GameDatabase;
|
||||||
import org.citra.citra_emu.model.GameProvider;
|
import org.yuzu.yuzu_emu.model.GameProvider;
|
||||||
|
|
||||||
public class AddDirectoryHelper {
|
public class AddDirectoryHelper {
|
||||||
private Context mContext;
|
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.HashMap;
|
||||||
import java.util.Map;
|
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.InputDevice;
|
||||||
import android.view.KeyEvent;
|
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.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
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 {
|
public class DirectoryStateReceiver extends BroadcastReceiver {
|
||||||
Action1<DirectoryInitializationState> callback;
|
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.content.SharedPreferences;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.citra.citra_emu.CitraApplication;
|
import org.yuzu.yuzu_emu.YuzuApplication;
|
||||||
|
|
||||||
public class EmulationMenuSettings {
|
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
|
// These must match what is defined in src/core/settings.h
|
||||||
public static final int LayoutOption_Default = 0;
|
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.File;
|
||||||
import java.io.FileInputStream;
|
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.annotation.TargetApi;
|
||||||
import android.content.Context;
|
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.Bitmap;
|
||||||
import android.graphics.BitmapShader;
|
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 have changed in this diff Show More
Loading…
Reference in New Issue