From ddc29f12062b462f98385e49124afd9b8f9f2507 Mon Sep 17 00:00:00 2001 From: SSimco <37044560+SSimco@users.noreply.github.com> Date: Mon, 3 Jul 2023 17:35:18 +0300 Subject: [PATCH] Replace most adapters with a generic one --- .../info/cemu/Cemu/ButtonListAdapter.java | 77 ----------- .../cemu/Cemu/ButtonRecyclerViewItem.java | 51 ++++++++ .../info/cemu/Cemu/ControllerHeaderItem.java | 22 ---- .../info/cemu/Cemu/ControllerInputItem.java | 34 ----- .../cemu/Cemu/ControllerInputListener.java | 41 ------ .../Cemu/ControllerInputsDataProvider.java | 65 ++++++---- .../cemu/Cemu/ControllerInputsFragment.java | 104 +++++++-------- .../java/info/cemu/Cemu/ControllerItem.java | 8 -- .../info/cemu/Cemu/ControllerListAdapter.java | 122 ------------------ .../cemu/Cemu/GenericRecyclerViewAdapter.java | 46 +++++++ .../cemu/Cemu/HeaderRecyclerViewItem.java | 37 ++++++ .../info/cemu/Cemu/InputRecyclerViewItem.java | 61 +++++++++ .../info/cemu/Cemu/InputSettingsFragment.java | 9 +- .../java/info/cemu/Cemu/RecyclerViewItem.java | 11 ++ .../java/info/cemu/Cemu/SettingsFragment.java | 95 -------------- .../cemu/Cemu/SpinnerRecyclerViewItem.java | 65 ++++++++++ .../res/layout/fragment_controller_inputs.xml | 18 --- .../src/main/res/layout/fragment_settings.xml | 13 -- .../app/src/main/res/layout/layout_button.xml | 7 +- ...ontroller_header.xml => layout_header.xml} | 2 +- .../src/main/res/layout/layout_spinner.xml | 22 ++++ .../src/main/res/layout/settings_spinner.xml | 19 --- .../app/src/main/res/values/strings.xml | 6 + 23 files changed, 404 insertions(+), 531 deletions(-) delete mode 100644 src/android/app/src/main/java/info/cemu/Cemu/ButtonListAdapter.java create mode 100644 src/android/app/src/main/java/info/cemu/Cemu/ButtonRecyclerViewItem.java delete mode 100644 src/android/app/src/main/java/info/cemu/Cemu/ControllerHeaderItem.java delete mode 100644 src/android/app/src/main/java/info/cemu/Cemu/ControllerInputItem.java delete mode 100644 src/android/app/src/main/java/info/cemu/Cemu/ControllerInputListener.java delete mode 100644 src/android/app/src/main/java/info/cemu/Cemu/ControllerItem.java delete mode 100644 src/android/app/src/main/java/info/cemu/Cemu/ControllerListAdapter.java create mode 100644 src/android/app/src/main/java/info/cemu/Cemu/GenericRecyclerViewAdapter.java create mode 100644 src/android/app/src/main/java/info/cemu/Cemu/HeaderRecyclerViewItem.java create mode 100644 src/android/app/src/main/java/info/cemu/Cemu/InputRecyclerViewItem.java create mode 100644 src/android/app/src/main/java/info/cemu/Cemu/RecyclerViewItem.java delete mode 100644 src/android/app/src/main/java/info/cemu/Cemu/SettingsFragment.java create mode 100644 src/android/app/src/main/java/info/cemu/Cemu/SpinnerRecyclerViewItem.java delete mode 100644 src/android/app/src/main/res/layout/fragment_settings.xml rename src/android/app/src/main/res/layout/{layout_controller_header.xml => layout_header.xml} (86%) create mode 100644 src/android/app/src/main/res/layout/layout_spinner.xml delete mode 100644 src/android/app/src/main/res/layout/settings_spinner.xml diff --git a/src/android/app/src/main/java/info/cemu/Cemu/ButtonListAdapter.java b/src/android/app/src/main/java/info/cemu/Cemu/ButtonListAdapter.java deleted file mode 100644 index f72902a1..00000000 --- a/src/android/app/src/main/java/info/cemu/Cemu/ButtonListAdapter.java +++ /dev/null @@ -1,77 +0,0 @@ -package info.cemu.Cemu; - -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; - -import java.util.ArrayList; -import java.util.List; - -public class ButtonListAdapter extends RecyclerView.Adapter { - - public interface OnButtonClickListener { - void onButtonClicked(); - } - - private static class ButtonInfo { - public ButtonInfo(String text, String description, OnButtonClickListener onButtonClickListener) { - this.text = text; - this.description = description; - this.onButtonClickListener = onButtonClickListener; - } - - String text; - String description; - OnButtonClickListener onButtonClickListener; - } - - private final List buttonInfoList = new ArrayList<>(); - - public void addButtonInfo(String text, String description, OnButtonClickListener onButtonClickListener) { - buttonInfoList.add(new ButtonInfo(text, description, onButtonClickListener)); - notifyItemInserted(buttonInfoList.size()); - } - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new ButtonViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_button, parent, false)); - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - ((ButtonViewHolder) holder).bind(buttonInfoList.get(position)); - holder.itemView.setOnClickListener(view -> { - ButtonInfo buttonInfo = buttonInfoList.get(holder.getAdapterPosition()); - if (buttonInfo.onButtonClickListener != null) { - buttonInfo.onButtonClickListener.onButtonClicked(); - } - }); - } - - @Override - public int getItemCount() { - return buttonInfoList.size(); - } - - private static class ButtonViewHolder extends RecyclerView.ViewHolder { - TextView text; - TextView description; - - void bind(ButtonInfo buttonInfo) { - text.setText(buttonInfo.text); - description.setText(buttonInfo.description); - } - - public ButtonViewHolder(View itemView) { - super(itemView); - text = itemView.findViewById(R.id.button_text); - description = itemView.findViewById(R.id.button_description); - } - } - -} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/ButtonRecyclerViewItem.java b/src/android/app/src/main/java/info/cemu/Cemu/ButtonRecyclerViewItem.java new file mode 100644 index 00000000..3115c434 --- /dev/null +++ b/src/android/app/src/main/java/info/cemu/Cemu/ButtonRecyclerViewItem.java @@ -0,0 +1,51 @@ +package info.cemu.Cemu; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +public class ButtonRecyclerViewItem implements RecyclerViewItem { + public interface OnButtonClickListener { + void onButtonClick(); + } + + private static class ButtonViewHolder extends RecyclerView.ViewHolder { + TextView text; + TextView description; + + public ButtonViewHolder(View itemView) { + super(itemView); + text = itemView.findViewById(R.id.button_text); + description = itemView.findViewById(R.id.button_description); + } + } + + private final OnButtonClickListener onButtonClickListener; + private String text; + private String description; + + public ButtonRecyclerViewItem(String text, String description, OnButtonClickListener onButtonClickListener) { + this.text = text; + this.description = description; + this.onButtonClickListener = onButtonClickListener; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) { + return new ButtonViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_button, parent, false)); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, RecyclerView.Adapter adapter) { + ButtonViewHolder buttonViewHolder = (ButtonViewHolder) viewHolder; + buttonViewHolder.text.setText(text); + buttonViewHolder.description.setText(description); + buttonViewHolder.itemView.setOnClickListener(view -> { + if (onButtonClickListener != null) + onButtonClickListener.onButtonClick(); + }); + } +} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/ControllerHeaderItem.java b/src/android/app/src/main/java/info/cemu/Cemu/ControllerHeaderItem.java deleted file mode 100644 index 7b9ee893..00000000 --- a/src/android/app/src/main/java/info/cemu/Cemu/ControllerHeaderItem.java +++ /dev/null @@ -1,22 +0,0 @@ -package info.cemu.Cemu; - -public class ControllerHeaderItem implements ControllerItem { - private String header; - - public ControllerHeaderItem(String header) { - this.header = header; - } - - @Override - public int getType() { - return TYPE_HEADER; - } - - public String getHeader() { - return header; - } - - public void setHeader(String header) { - this.header = header; - } -} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputItem.java b/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputItem.java deleted file mode 100644 index 33ab3a6d..00000000 --- a/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputItem.java +++ /dev/null @@ -1,34 +0,0 @@ -package info.cemu.Cemu; - -public class ControllerInputItem implements ControllerItem { - private final int nameResourceId; - private final int id; - private String boundInput; - - public ControllerInputItem(int nameResourceId, int id, String boundInput) { - this.nameResourceId = nameResourceId; - this.id = id; - this.boundInput = boundInput; - } - - @Override - public int getType() { - return TYPE_INPUT; - } - - public int getNameResourceId() { - return nameResourceId; - } - - public int getId() { - return id; - } - - public String getBoundInput() { - return boundInput; - } - - public void setBoundInput(String boundInput) { - this.boundInput = boundInput; - } -} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputListener.java b/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputListener.java deleted file mode 100644 index 21746dfc..00000000 --- a/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputListener.java +++ /dev/null @@ -1,41 +0,0 @@ -package info.cemu.Cemu; - -import android.view.InputDevice; -import android.view.KeyEvent; -import android.view.MotionEvent; - -public class ControllerInputListener { - private static boolean isController(int sources) { - return ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK) || - ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) || - ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD); - } - - public static boolean onKeyEvent(KeyEvent keyEvent) { - InputDevice inputDevice = keyEvent.getDevice(); - if (isController(inputDevice.getSources())) { - String descriptor = inputDevice.getDescriptor(); - String name = inputDevice.getName(); - NativeLibrary.onNativeKey(descriptor == null ? name : descriptor, name, keyEvent.getKeyCode(), keyEvent.getAction() == KeyEvent.ACTION_DOWN); - return true; - } - return false; - } - - public static boolean onMotionEvent(MotionEvent motionEvent) { - int actionPointerIndex = motionEvent.getActionIndex(); - int action = motionEvent.getActionMasked(); - if (action == MotionEvent.ACTION_MOVE) { - InputDevice inputDevice = motionEvent.getDevice(); - String descriptor = inputDevice.getDescriptor(); - String name = inputDevice.getName(); - for (InputDevice.MotionRange range : inputDevice.getMotionRanges()) { - int axis = range.getAxis(); - float value = (motionEvent.getAxisValue(axis, actionPointerIndex) - range.getMin()) / range.getRange() * 2.0f - 1.0f; - NativeLibrary.onNativeAxis(descriptor == null ? name : descriptor, name, axis, value); - } - return true; - } - return false; - } -} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputsDataProvider.java b/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputsDataProvider.java index 058763c7..950f7994 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputsDataProvider.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputsDataProvider.java @@ -3,6 +3,7 @@ package info.cemu.Cemu; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public class ControllerInputsDataProvider { private int getButtonResourceIdName(int controllerType, int buttonId) { @@ -125,38 +126,58 @@ public class ControllerInputsDataProvider { throw new RuntimeException("Invalid controllerType " + controllerType); } - private void addControllerInputsGroup(List controllerInputItems, String groupName, int controllerType, int[] buttons, Map inputs) { - controllerInputItems.add(new ControllerHeaderItem(groupName)); - for (int button : buttons) { - controllerInputItems.add(new ControllerInputItem(getButtonResourceIdName(controllerType, button), button, inputs.getOrDefault(button, ""))); + public static class ControllerInput { + public int buttonResourceIdName; + public int buttonId; + public String boundInput; + + public ControllerInput(int buttonResourceIdName, int buttonId, String boundInput) { + this.boundInput = boundInput; + this.buttonId = buttonId; + this.buttonResourceIdName = buttonResourceIdName; } } - public List getControllerInputs(int controllerType, Map inputs) { - List controllerInputItems = new ArrayList<>(); + public static class ControllerInputGroup { + public int groupResourceIdName; + public List inputs; + + public ControllerInputGroup(int groupResourceIdName, List inputs) { + this.groupResourceIdName = groupResourceIdName; + this.inputs = inputs; + } + } + + private void addControllerInputsGroup(List controllerInputItems, int groupResourceIdName, int controllerType, List buttons, Map inputs) { + List controllerInputs = buttons.stream().map(buttonId -> new ControllerInput(getButtonResourceIdName(controllerType, buttonId), buttonId, inputs.getOrDefault(buttonId, ""))).collect(Collectors.toList()); + controllerInputItems.add(new ControllerInputGroup(groupResourceIdName, controllerInputs)); + } + + public List getControllerInputs(int controllerType, Map inputs) { + List controllerInputItems = new ArrayList<>(); if (controllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_VPAD) { - addControllerInputsGroup(controllerInputItems, "Buttons", controllerType, new int[]{NativeLibrary.VPAD_BUTTON_A, NativeLibrary.VPAD_BUTTON_B, NativeLibrary.VPAD_BUTTON_X, NativeLibrary.VPAD_BUTTON_Y, NativeLibrary.VPAD_BUTTON_L, NativeLibrary.VPAD_BUTTON_R, NativeLibrary.VPAD_BUTTON_ZL, NativeLibrary.VPAD_BUTTON_ZR, NativeLibrary.VPAD_BUTTON_PLUS, NativeLibrary.VPAD_BUTTON_MINUS}, inputs); - addControllerInputsGroup(controllerInputItems, "D-Pad", controllerType, new int[]{NativeLibrary.VPAD_BUTTON_UP, NativeLibrary.VPAD_BUTTON_DOWN, NativeLibrary.VPAD_BUTTON_LEFT, NativeLibrary.VPAD_BUTTON_RIGHT}, inputs); - addControllerInputsGroup(controllerInputItems, "Left Axis", controllerType, new int[]{NativeLibrary.VPAD_BUTTON_STICKL, NativeLibrary.VPAD_BUTTON_STICKL_UP, NativeLibrary.VPAD_BUTTON_STICKL_DOWN, NativeLibrary.VPAD_BUTTON_STICKL_LEFT, NativeLibrary.VPAD_BUTTON_STICKL_RIGHT}, inputs); - addControllerInputsGroup(controllerInputItems, "Right Axis", controllerType, new int[]{NativeLibrary.VPAD_BUTTON_STICKR, NativeLibrary.VPAD_BUTTON_STICKR_UP, NativeLibrary.VPAD_BUTTON_STICKR_DOWN, NativeLibrary.VPAD_BUTTON_STICKR_LEFT, NativeLibrary.VPAD_BUTTON_STICKR_RIGHT}, inputs); - addControllerInputsGroup(controllerInputItems, "Extra", controllerType, new int[]{NativeLibrary.VPAD_BUTTON_MIC, NativeLibrary.VPAD_BUTTON_SCREEN, NativeLibrary.VPAD_BUTTON_HOME}, inputs); + addControllerInputsGroup(controllerInputItems, R.string.buttons, controllerType, List.of(NativeLibrary.VPAD_BUTTON_A, NativeLibrary.VPAD_BUTTON_B, NativeLibrary.VPAD_BUTTON_X, NativeLibrary.VPAD_BUTTON_Y, NativeLibrary.VPAD_BUTTON_L, NativeLibrary.VPAD_BUTTON_R, NativeLibrary.VPAD_BUTTON_ZL, NativeLibrary.VPAD_BUTTON_ZR, NativeLibrary.VPAD_BUTTON_PLUS, NativeLibrary.VPAD_BUTTON_MINUS), inputs); + addControllerInputsGroup(controllerInputItems, R.string.d_pad, controllerType, List.of(NativeLibrary.VPAD_BUTTON_UP, NativeLibrary.VPAD_BUTTON_DOWN, NativeLibrary.VPAD_BUTTON_LEFT, NativeLibrary.VPAD_BUTTON_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.left_axis, controllerType, List.of(NativeLibrary.VPAD_BUTTON_STICKL, NativeLibrary.VPAD_BUTTON_STICKL_UP, NativeLibrary.VPAD_BUTTON_STICKL_DOWN, NativeLibrary.VPAD_BUTTON_STICKL_LEFT, NativeLibrary.VPAD_BUTTON_STICKL_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.right_axis, controllerType, List.of(NativeLibrary.VPAD_BUTTON_STICKR, NativeLibrary.VPAD_BUTTON_STICKR_UP, NativeLibrary.VPAD_BUTTON_STICKR_DOWN, NativeLibrary.VPAD_BUTTON_STICKR_LEFT, NativeLibrary.VPAD_BUTTON_STICKR_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.extra, controllerType, List.of(NativeLibrary.VPAD_BUTTON_MIC, NativeLibrary.VPAD_BUTTON_SCREEN, NativeLibrary.VPAD_BUTTON_HOME), inputs); } if (controllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_PRO) { - addControllerInputsGroup(controllerInputItems, "Buttons", controllerType, new int[]{NativeLibrary.PRO_BUTTON_A, NativeLibrary.PRO_BUTTON_B, NativeLibrary.PRO_BUTTON_X, NativeLibrary.PRO_BUTTON_Y, NativeLibrary.PRO_BUTTON_L, NativeLibrary.PRO_BUTTON_R, NativeLibrary.PRO_BUTTON_ZL, NativeLibrary.PRO_BUTTON_ZR, NativeLibrary.PRO_BUTTON_PLUS, NativeLibrary.PRO_BUTTON_MINUS, NativeLibrary.PRO_BUTTON_HOME}, inputs); - addControllerInputsGroup(controllerInputItems, "Left Axis", controllerType, new int[]{NativeLibrary.PRO_BUTTON_STICKL, NativeLibrary.PRO_BUTTON_STICKL_UP, NativeLibrary.PRO_BUTTON_STICKL_DOWN, NativeLibrary.PRO_BUTTON_STICKL_LEFT, NativeLibrary.PRO_BUTTON_STICKL_RIGHT}, inputs); - addControllerInputsGroup(controllerInputItems, "Right Axis", controllerType, new int[]{NativeLibrary.PRO_BUTTON_STICKR, NativeLibrary.PRO_BUTTON_STICKR_UP, NativeLibrary.PRO_BUTTON_STICKR_DOWN, NativeLibrary.PRO_BUTTON_STICKR_LEFT, NativeLibrary.PRO_BUTTON_STICKR_RIGHT}, inputs); - addControllerInputsGroup(controllerInputItems, "D-Pad", controllerType, new int[]{NativeLibrary.PRO_BUTTON_UP, NativeLibrary.PRO_BUTTON_DOWN, NativeLibrary.PRO_BUTTON_LEFT, NativeLibrary.PRO_BUTTON_RIGHT}, inputs); + addControllerInputsGroup(controllerInputItems, R.string.buttons, controllerType, List.of(NativeLibrary.PRO_BUTTON_A, NativeLibrary.PRO_BUTTON_B, NativeLibrary.PRO_BUTTON_X, NativeLibrary.PRO_BUTTON_Y, NativeLibrary.PRO_BUTTON_L, NativeLibrary.PRO_BUTTON_R, NativeLibrary.PRO_BUTTON_ZL, NativeLibrary.PRO_BUTTON_ZR, NativeLibrary.PRO_BUTTON_PLUS, NativeLibrary.PRO_BUTTON_MINUS, NativeLibrary.PRO_BUTTON_HOME), inputs); + addControllerInputsGroup(controllerInputItems, R.string.left_axis, controllerType, List.of(NativeLibrary.PRO_BUTTON_STICKL, NativeLibrary.PRO_BUTTON_STICKL_UP, NativeLibrary.PRO_BUTTON_STICKL_DOWN, NativeLibrary.PRO_BUTTON_STICKL_LEFT, NativeLibrary.PRO_BUTTON_STICKL_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.right_axis, controllerType, List.of(NativeLibrary.PRO_BUTTON_STICKR, NativeLibrary.PRO_BUTTON_STICKR_UP, NativeLibrary.PRO_BUTTON_STICKR_DOWN, NativeLibrary.PRO_BUTTON_STICKR_LEFT, NativeLibrary.PRO_BUTTON_STICKR_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.d_pad, controllerType, List.of(NativeLibrary.PRO_BUTTON_UP, NativeLibrary.PRO_BUTTON_DOWN, NativeLibrary.PRO_BUTTON_LEFT, NativeLibrary.PRO_BUTTON_RIGHT), inputs); } if (controllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_CLASSIC) { - addControllerInputsGroup(controllerInputItems, "Buttons", controllerType, new int[]{NativeLibrary.CLASSIC_BUTTON_A, NativeLibrary.CLASSIC_BUTTON_B, NativeLibrary.CLASSIC_BUTTON_X, NativeLibrary.CLASSIC_BUTTON_Y, NativeLibrary.CLASSIC_BUTTON_L, NativeLibrary.CLASSIC_BUTTON_R, NativeLibrary.CLASSIC_BUTTON_ZL, NativeLibrary.CLASSIC_BUTTON_ZR, NativeLibrary.CLASSIC_BUTTON_PLUS, NativeLibrary.CLASSIC_BUTTON_MINUS, NativeLibrary.CLASSIC_BUTTON_HOME}, inputs); - addControllerInputsGroup(controllerInputItems, "Left Axis", controllerType, new int[]{NativeLibrary.CLASSIC_BUTTON_STICKL_UP, NativeLibrary.CLASSIC_BUTTON_STICKL_DOWN, NativeLibrary.CLASSIC_BUTTON_STICKL_LEFT, NativeLibrary.CLASSIC_BUTTON_STICKL_RIGHT}, inputs); - addControllerInputsGroup(controllerInputItems, "Right Axis", controllerType, new int[]{NativeLibrary.CLASSIC_BUTTON_STICKR_UP, NativeLibrary.CLASSIC_BUTTON_STICKR_DOWN, NativeLibrary.CLASSIC_BUTTON_STICKR_LEFT, NativeLibrary.CLASSIC_BUTTON_STICKR_RIGHT}, inputs); - addControllerInputsGroup(controllerInputItems, "D-Pad", controllerType, new int[]{NativeLibrary.CLASSIC_BUTTON_UP, NativeLibrary.CLASSIC_BUTTON_DOWN, NativeLibrary.CLASSIC_BUTTON_LEFT, NativeLibrary.CLASSIC_BUTTON_RIGHT}, inputs); + addControllerInputsGroup(controllerInputItems, R.string.buttons, controllerType, List.of(NativeLibrary.CLASSIC_BUTTON_A, NativeLibrary.CLASSIC_BUTTON_B, NativeLibrary.CLASSIC_BUTTON_X, NativeLibrary.CLASSIC_BUTTON_Y, NativeLibrary.CLASSIC_BUTTON_L, NativeLibrary.CLASSIC_BUTTON_R, NativeLibrary.CLASSIC_BUTTON_ZL, NativeLibrary.CLASSIC_BUTTON_ZR, NativeLibrary.CLASSIC_BUTTON_PLUS, NativeLibrary.CLASSIC_BUTTON_MINUS, NativeLibrary.CLASSIC_BUTTON_HOME), inputs); + addControllerInputsGroup(controllerInputItems, R.string.left_axis, controllerType, List.of(NativeLibrary.CLASSIC_BUTTON_STICKL_UP, NativeLibrary.CLASSIC_BUTTON_STICKL_DOWN, NativeLibrary.CLASSIC_BUTTON_STICKL_LEFT, NativeLibrary.CLASSIC_BUTTON_STICKL_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.right_axis, controllerType, List.of(NativeLibrary.CLASSIC_BUTTON_STICKR_UP, NativeLibrary.CLASSIC_BUTTON_STICKR_DOWN, NativeLibrary.CLASSIC_BUTTON_STICKR_LEFT, NativeLibrary.CLASSIC_BUTTON_STICKR_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.d_pad, controllerType, List.of(NativeLibrary.CLASSIC_BUTTON_UP, NativeLibrary.CLASSIC_BUTTON_DOWN, NativeLibrary.CLASSIC_BUTTON_LEFT, NativeLibrary.CLASSIC_BUTTON_RIGHT), inputs); } if (controllerType == NativeLibrary.EMULATED_CONTROLLER_TYPE_WIIMOTE) { - addControllerInputsGroup(controllerInputItems, "Buttons", controllerType, new int[]{NativeLibrary.WIIMOTE_BUTTON_A, NativeLibrary.WIIMOTE_BUTTON_B, NativeLibrary.WIIMOTE_BUTTON_1, NativeLibrary.WIIMOTE_BUTTON_2, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_Z, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_C, NativeLibrary.WIIMOTE_BUTTON_PLUS, NativeLibrary.WIIMOTE_BUTTON_MINUS, NativeLibrary.WIIMOTE_BUTTON_HOME}, inputs); - addControllerInputsGroup(controllerInputItems, "D-Pad", controllerType, new int[]{NativeLibrary.WIIMOTE_BUTTON_UP, NativeLibrary.WIIMOTE_BUTTON_DOWN, NativeLibrary.WIIMOTE_BUTTON_LEFT, NativeLibrary.WIIMOTE_BUTTON_RIGHT}, inputs); - addControllerInputsGroup(controllerInputItems, "Nunchuck", controllerType, new int[]{NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_UP, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_DOWN, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_LEFT, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_RIGHT}, inputs); + addControllerInputsGroup(controllerInputItems, R.string.buttons, controllerType, List.of(NativeLibrary.WIIMOTE_BUTTON_A, NativeLibrary.WIIMOTE_BUTTON_B, NativeLibrary.WIIMOTE_BUTTON_1, NativeLibrary.WIIMOTE_BUTTON_2, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_Z, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_C, NativeLibrary.WIIMOTE_BUTTON_PLUS, NativeLibrary.WIIMOTE_BUTTON_MINUS, NativeLibrary.WIIMOTE_BUTTON_HOME), inputs); + addControllerInputsGroup(controllerInputItems, R.string.d_pad, controllerType, List.of(NativeLibrary.WIIMOTE_BUTTON_UP, NativeLibrary.WIIMOTE_BUTTON_DOWN, NativeLibrary.WIIMOTE_BUTTON_LEFT, NativeLibrary.WIIMOTE_BUTTON_RIGHT), inputs); + addControllerInputsGroup(controllerInputItems, R.string.nunchuck, controllerType, List.of(NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_UP, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_DOWN, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_LEFT, NativeLibrary.WIIMOTE_BUTTON_NUNCHUCK_RIGHT), inputs); } return controllerInputItems; } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputsFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputsFragment.java index 95fcfc0d..34a597ef 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputsFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/ControllerInputsFragment.java @@ -1,11 +1,9 @@ package info.cemu.Cemu; import android.os.Bundle; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.AdapterView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -14,26 +12,67 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; -import info.cemu.Cemu.databinding.FragmentControllerInputsBinding; - import java.util.HashMap; -import java.util.Objects; +import java.util.Map; + +import info.cemu.Cemu.databinding.FragmentControllerInputsBinding; public class ControllerInputsFragment extends Fragment { public static final String CONTROLLER_INDEX = "ControllerIndex"; private int controllerIndex; private int controllerType; private final InputManager inputManager = new InputManager(); - private EmulatedControllerTypeAdapter emulatedControllerTypeAdapter; - private ControllerListAdapter controllerListAdapter; + private final ControllerInputsDataProvider controllerInputsDataProvider = new ControllerInputsDataProvider(); + private final GenericRecyclerViewAdapter genericRecyclerViewAdapter = new GenericRecyclerViewAdapter(); + private final EmulatedControllerTypeAdapter emulatedControllerTypeAdapter = new EmulatedControllerTypeAdapter(); private void onTypeChanged(int controllerType) { if (this.controllerType == controllerType) return; this.controllerType = controllerType; NativeLibrary.setControllerType(controllerIndex, controllerType); + genericRecyclerViewAdapter.clearRecyclerViewItems(); + setControllerInputs(new HashMap<>()); + } + + private void setControllerInputs(Map inputs) { emulatedControllerTypeAdapter.setCurrentControllerType(controllerType); - controllerListAdapter.setEmulatedControllerListItems(controllerType, new HashMap<>()); emulatedControllerTypeAdapter.setControllerTypeCounts(NativeLibrary.getVPADControllersCount(), NativeLibrary.getWPADControllersCount()); + SpinnerRecyclerViewItem emulatedControllerSpinner = new SpinnerRecyclerViewItem(R.string.emulated_controller_label, emulatedControllerTypeAdapter, emulatedControllerTypeAdapter.getPosition(controllerType), position -> onTypeChanged(emulatedControllerTypeAdapter.getItem(position))); + genericRecyclerViewAdapter.addRecyclerViewItem(emulatedControllerSpinner); + for (var controllerInputsGroups : controllerInputsDataProvider.getControllerInputs(controllerType, inputs)) { + genericRecyclerViewAdapter.addRecyclerViewItem(new HeaderRecyclerViewItem(controllerInputsGroups.groupResourceIdName)); + for (var controllerInput : controllerInputsGroups.inputs) { + int buttonId = controllerInput.buttonId; + int buttonResourceIdName = controllerInput.buttonResourceIdName; + InputRecyclerViewItem inputRecyclerViewItem = new InputRecyclerViewItem(controllerInput.buttonResourceIdName, controllerInput.boundInput, inputItem -> { + MotionDialog inputDialog = new MotionDialog(getContext()); + inputDialog.setOnKeyListener((dialog, keyCode, keyEvent) -> { + if (inputManager.mapKeyEventToMappingId(controllerIndex, buttonId, keyEvent)) { + inputItem.setBoundInput(NativeLibrary.getControllerMapping(controllerIndex, buttonId)); + inputDialog.dismiss(); + } + return true; + }); + inputDialog.setOnMotionListener(motionEvent -> { + if (inputManager.mapMotionEventToMappingId(controllerIndex, buttonId, motionEvent)) { + inputItem.setBoundInput(NativeLibrary.getControllerMapping(controllerIndex, buttonId)); + inputDialog.dismiss(); + } + return true; + }); + inputDialog.setMessage(getString(R.string.inputBindingDialogMessage, getString(buttonResourceIdName))); + inputDialog.setButton(AlertDialog.BUTTON_NEUTRAL, getString(R.string.clear), (dialogInterface, i) -> { + NativeLibrary.clearControllerMapping(controllerIndex, buttonId); + inputItem.clearBoundInput(); + dialogInterface.dismiss(); + }); + inputDialog.setButton(AlertDialog.BUTTON_NEGATIVE, getString(R.string.cancel), (dialogInterface, i) -> dialogInterface.dismiss()); + inputDialog.setTitle(R.string.inputBindingDialogTitle); + inputDialog.show(); + }); + genericRecyclerViewAdapter.addRecyclerViewItem(inputRecyclerViewItem); + } + } } @Nullable @@ -47,54 +86,11 @@ public class ControllerInputsFragment extends Fragment { if (NativeLibrary.isControllerDisabled(controllerIndex)) controllerType = NativeLibrary.EMULATED_CONTROLLER_TYPE_DISABLED; else controllerType = NativeLibrary.getControllerType(controllerIndex); - controllerListAdapter = new ControllerListAdapter(); - emulatedControllerTypeAdapter = new EmulatedControllerTypeAdapter(); - emulatedControllerTypeAdapter.setCurrentControllerType(controllerType); - emulatedControllerTypeAdapter.setControllerTypeCounts(NativeLibrary.getVPADControllersCount(), NativeLibrary.getWPADControllersCount()); + + setControllerInputs(NativeLibrary.getControllerMappings(controllerIndex)); FragmentControllerInputsBinding binding = FragmentControllerInputsBinding.inflate(inflater, container, false); - - binding.emulatedControllerSpinner.setAdapter(emulatedControllerTypeAdapter); - binding.emulatedControllerSpinner.setSelection(emulatedControllerTypeAdapter.getPosition(controllerType)); - binding.emulatedControllerSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView adapterView, View view, int position, long l) { - onTypeChanged(emulatedControllerTypeAdapter.getItem(position)); - } - - @Override - public void onNothingSelected(AdapterView adapterView) { - } - }); - - controllerListAdapter.setEmulatedControllerListItems(controllerType, NativeLibrary.getControllerMappings(controllerIndex)); - controllerListAdapter.setOnInputClickListener((nameId, id, position) -> { - MotionDialog inputDialog = new MotionDialog(getContext()); - inputDialog.setOnKeyListener((dialog, keyCode, keyEvent) -> { - if (inputManager.mapKeyEventToMappingId(controllerIndex, id, keyEvent)) { - controllerListAdapter.setBoundInput(position, NativeLibrary.getControllerMapping(controllerIndex, id)); - inputDialog.dismiss(); - } - return true; - }); - inputDialog.setOnMotionListener(motionEvent -> { - if (inputManager.mapMotionEventToMappingId(controllerIndex, id, motionEvent)) { - controllerListAdapter.setBoundInput(position, NativeLibrary.getControllerMapping(controllerIndex, id)); - inputDialog.dismiss(); - } - return true; - }); - inputDialog.setMessage(getString(R.string.inputBindingDialogMessage, getString(nameId))); - inputDialog.setButton(AlertDialog.BUTTON_NEUTRAL, getString(R.string.clear), (dialogInterface, i) -> { - NativeLibrary.clearControllerMapping(controllerIndex, id); - controllerListAdapter.clearBoundInput(position); - dialogInterface.dismiss(); - }); - inputDialog.setButton(AlertDialog.BUTTON_NEGATIVE, getString(R.string.cancel), (dialogInterface, i) -> dialogInterface.dismiss()); - inputDialog.setTitle(R.string.inputBindingDialogTitle); - inputDialog.show(); - }); - binding.controllerInputsRecyclerView.setAdapter(controllerListAdapter); + binding.controllerInputsRecyclerView.setAdapter(genericRecyclerViewAdapter); return binding.getRoot(); } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/ControllerItem.java b/src/android/app/src/main/java/info/cemu/Cemu/ControllerItem.java deleted file mode 100644 index 89879e43..00000000 --- a/src/android/app/src/main/java/info/cemu/Cemu/ControllerItem.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.cemu.Cemu; - -public interface ControllerItem { - int TYPE_HEADER = 0; - int TYPE_INPUT = 1; - - int getType(); -} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/ControllerListAdapter.java b/src/android/app/src/main/java/info/cemu/Cemu/ControllerListAdapter.java deleted file mode 100644 index 10ebe1ab..00000000 --- a/src/android/app/src/main/java/info/cemu/Cemu/ControllerListAdapter.java +++ /dev/null @@ -1,122 +0,0 @@ -package info.cemu.Cemu; - -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class ControllerListAdapter extends RecyclerView.Adapter { - private List controllerItemList = new ArrayList<>(); - private final ControllerInputsDataProvider controllerInputs = new ControllerInputsDataProvider(); - private OnInputClickListener onInputClickListener; - - - public void setEmulatedControllerListItems(int controllerType, Map inputsMapping) { - controllerItemList = controllerInputs.getControllerInputs(controllerType, inputsMapping); - notifyDataSetChanged(); - } - - public void clearBoundInput(int position) { - ControllerItem listItem = controllerItemList.get(position); - if (listItem.getType() == ControllerItem.TYPE_INPUT) { - ControllerInputItem controllerInputItem = (ControllerInputItem) listItem; - controllerInputItem.setBoundInput(""); - controllerItemList.set(position, controllerInputItem); - notifyItemChanged(position); - } - } - - public interface OnInputClickListener { - void onInputClicked(int nameId, int id, int position); - } - - void setOnInputClickListener(OnInputClickListener onInputClickListener) { - this.onInputClickListener = onInputClickListener; - } - - @Override - public int getItemViewType(int position) { - return controllerItemList.get(position).getType(); - } - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - if (viewType == ControllerItem.TYPE_HEADER) { - View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_controller_header, parent, false); - return new HeaderViewHolder(view); - } else if (viewType == ControllerItem.TYPE_INPUT) { - View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_controller_input, parent, false); - return new InputViewHolder(view); - } - throw new RuntimeException("Invalid viewType: " + viewType); - } - - public void setBoundInput(int inputItemPosition, String boundInput) { - ControllerItem listItem = controllerItemList.get(inputItemPosition); - if (listItem.getType() == ControllerItem.TYPE_INPUT) { - ControllerInputItem controllerInputItem = (ControllerInputItem) listItem; - controllerInputItem.setBoundInput(boundInput); - controllerItemList.set(inputItemPosition, controllerInputItem); - notifyItemChanged(inputItemPosition); - } - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - if (holder instanceof HeaderViewHolder) { - ((HeaderViewHolder) holder).bind((ControllerHeaderItem) controllerItemList.get(position)); - } else if (holder instanceof InputViewHolder inputViewHolder) { - ControllerInputItem inputListItem = (ControllerInputItem) controllerItemList.get(position); - holder.itemView.setOnClickListener(v -> { - if (onInputClickListener != null) { - onInputClickListener.onInputClicked(inputListItem.getNameResourceId(), inputListItem.getId(), holder.getAdapterPosition()); - } - }); - inputViewHolder.bind(inputListItem); - } - } - - @Override - public int getItemCount() { - return controllerItemList.size(); - } - - public static class InputViewHolder extends RecyclerView.ViewHolder { - TextView inputName; - TextView boundInput; - - void bind(ControllerInputItem inputListItem) { - inputName.setText(inputListItem.getNameResourceId()); - boundInput.setText(inputListItem.getBoundInput()); - } - - public InputViewHolder(View itemView) { - super(itemView); - inputName = itemView.findViewById(R.id.controller_input_name); - boundInput = itemView.findViewById(R.id.controller_button_name); - } - } - - public static class HeaderViewHolder extends RecyclerView.ViewHolder { - TextView header; - - void bind(ControllerHeaderItem headerListItem) { - header.setText(headerListItem.getHeader()); - } - - public HeaderViewHolder(View itemView) { - super(itemView); - header = itemView.findViewById(R.id.textview_controller_header); - } - } - -} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/GenericRecyclerViewAdapter.java b/src/android/app/src/main/java/info/cemu/Cemu/GenericRecyclerViewAdapter.java new file mode 100644 index 00000000..5f51331c --- /dev/null +++ b/src/android/app/src/main/java/info/cemu/Cemu/GenericRecyclerViewAdapter.java @@ -0,0 +1,46 @@ +package info.cemu.Cemu; + +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.List; + +public class GenericRecyclerViewAdapter extends RecyclerView.Adapter { + + private final List recyclerViewItems = new ArrayList<>(); + + public void addRecyclerViewItem(RecyclerViewItem recyclerViewItem) { + recyclerViewItems.add(recyclerViewItem); + notifyItemInserted(recyclerViewItems.size() - 1); + } + + public void clearRecyclerViewItems() { + int itemsCount = recyclerViewItems.size(); + recyclerViewItems.clear(); + notifyItemRangeRemoved(0, itemsCount); + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) { + return recyclerViewItems.get(position).onCreateViewHolder(parent); + } + + @Override + public int getItemViewType(int position) { + return position; + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + recyclerViewItems.get(position).onBindViewHolder(holder, this); + } + + @Override + public int getItemCount() { + return recyclerViewItems.size(); + } +} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/HeaderRecyclerViewItem.java b/src/android/app/src/main/java/info/cemu/Cemu/HeaderRecyclerViewItem.java new file mode 100644 index 00000000..95f5c610 --- /dev/null +++ b/src/android/app/src/main/java/info/cemu/Cemu/HeaderRecyclerViewItem.java @@ -0,0 +1,37 @@ +package info.cemu.Cemu; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +public class HeaderRecyclerViewItem implements RecyclerViewItem { + + private static class HeaderViewHolder extends RecyclerView.ViewHolder { + TextView header; + + public HeaderViewHolder(View itemView) { + super(itemView); + header = itemView.findViewById(R.id.textview_header); + } + } + + private final int headerResourceIdText; + + public HeaderRecyclerViewItem(int headerResourceIdText) { + this.headerResourceIdText = headerResourceIdText; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) { + return new HeaderViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_header, parent, false)); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, RecyclerView.Adapter adapter) { + HeaderViewHolder headerViewHolder = (HeaderViewHolder) viewHolder; + headerViewHolder.header.setText(headerResourceIdText); + } +} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/InputRecyclerViewItem.java b/src/android/app/src/main/java/info/cemu/Cemu/InputRecyclerViewItem.java new file mode 100644 index 00000000..e026330a --- /dev/null +++ b/src/android/app/src/main/java/info/cemu/Cemu/InputRecyclerViewItem.java @@ -0,0 +1,61 @@ +package info.cemu.Cemu; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +public class InputRecyclerViewItem implements RecyclerViewItem { + public interface OnInputClickListener { + void onInputClick(InputRecyclerViewItem inputRecyclerViewItem); + } + + private static class InputViewHolder extends RecyclerView.ViewHolder { + TextView inputName; + TextView boundInput; + + public InputViewHolder(View itemView) { + super(itemView); + inputName = itemView.findViewById(R.id.controller_input_name); + boundInput = itemView.findViewById(R.id.controller_button_name); + } + } + + private final int inputNameResourceId; + private String boundInput; + private final OnInputClickListener onInputClickListener; + private RecyclerView.Adapter recyclerViewAdapter; + private InputViewHolder inputViewHolder; + + public InputRecyclerViewItem(int inputNameResourceId, String boundInput, OnInputClickListener onInputClickListener) { + this.inputNameResourceId = inputNameResourceId; + this.boundInput = boundInput; + this.onInputClickListener = onInputClickListener; + + } + + public void clearBoundInput() { + setBoundInput(""); + } + + public void setBoundInput(String boundInput) { + this.boundInput = boundInput; + recyclerViewAdapter.notifyItemChanged(inputViewHolder.getAdapterPosition()); + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) { + return new InputViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_controller_input, parent, false)); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, RecyclerView.Adapter adapter) { + inputViewHolder = (InputViewHolder) viewHolder; + recyclerViewAdapter = adapter; + inputViewHolder.itemView.setOnClickListener(view -> onInputClickListener.onInputClick(this)); + inputViewHolder.inputName.setText(inputNameResourceId); + inputViewHolder.boundInput.setText(boundInput); + } +} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/InputSettingsFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/InputSettingsFragment.java index 2d5746ed..77e43e23 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/InputSettingsFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/InputSettingsFragment.java @@ -20,18 +20,21 @@ public class InputSettingsFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { FragmentInputSettingsBinding binding = FragmentInputSettingsBinding.inflate(inflater, container, false); - ButtonListAdapter buttonListAdapter = new ButtonListAdapter(); + GenericRecyclerViewAdapter genericRecyclerViewAdapter = new GenericRecyclerViewAdapter(); for (int index = 0; index < NativeLibrary.MAX_CONTROLLERS; index++) { int controllerIndex = index; String controllerType = getString(NativeLibrary.controllerTypeToResourceNameId(NativeLibrary.getControllerType(controllerIndex))); - buttonListAdapter.addButtonInfo(getString(R.string.controller_numbered, controllerIndex + 1), getString(R.string.emulated_controller_with_type, controllerType), + ButtonRecyclerViewItem buttonRecyclerViewItem = new ButtonRecyclerViewItem( + getString(R.string.controller_numbered, controllerIndex + 1), + getString(R.string.emulated_controller_with_type, controllerType), () -> { Bundle bundle = new Bundle(); bundle.putInt(ControllerInputsFragment.CONTROLLER_INDEX, controllerIndex); NavHostFragment.findNavController(InputSettingsFragment.this).navigate(R.id.action_inputSettingsFragment_to_controllerInputsFragment, bundle); }); + genericRecyclerViewAdapter.addRecyclerViewItem(buttonRecyclerViewItem); } - binding.inputSettingsRecyclerView.setAdapter(buttonListAdapter); + binding.inputSettingsRecyclerView.setAdapter(genericRecyclerViewAdapter); return binding.getRoot(); } } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/RecyclerViewItem.java b/src/android/app/src/main/java/info/cemu/Cemu/RecyclerViewItem.java new file mode 100644 index 00000000..a2fa95c3 --- /dev/null +++ b/src/android/app/src/main/java/info/cemu/Cemu/RecyclerViewItem.java @@ -0,0 +1,11 @@ +package info.cemu.Cemu; + +import android.view.ViewGroup; + +import androidx.recyclerview.widget.RecyclerView; + +public interface RecyclerViewItem { + RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent); + + void onBindViewHolder(RecyclerView.ViewHolder viewHolder, RecyclerView.Adapter adapter); +} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/SettingsFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/SettingsFragment.java deleted file mode 100644 index 578eea7f..00000000 --- a/src/android/app/src/main/java/info/cemu/Cemu/SettingsFragment.java +++ /dev/null @@ -1,95 +0,0 @@ -package info.cemu.Cemu; - -import android.os.Bundle; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; - -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.LinearLayout; -import android.widget.SpinnerAdapter; - -import java.util.ArrayList; -import java.util.List; - -import info.cemu.Cemu.databinding.FragmentSettingsBinding; - -import info.cemu.Cemu.databinding.SettingsCheckboxBinding; -import info.cemu.Cemu.databinding.SettingsHeaderBinding; -import info.cemu.Cemu.databinding.SettingsCheckboxBinding; -import info.cemu.Cemu.databinding.SettingsSpinnerBinding; - -public class SettingsFragment extends Fragment { - protected FragmentSettingsBinding binding; - - public SettingsFragment() { - } - -// public abstract int getSettingsNameId(); - - protected interface OnCheckBoxStateListener { - void onStateChanged(boolean checked); - } - - protected interface OnItemSelectedPositionListener { - void onItemSelected(int position); - } - - protected void addCheckBox(String title, String description, boolean initialValue, OnCheckBoxStateListener checkBoxStateListener) { - View checkboxLayout = getLayoutInflater().inflate(R.layout.settings_spinner, null); - binding.settingsLayout.addView(checkboxLayout); - SettingsCheckboxBinding checkboxBinding = SettingsCheckboxBinding.bind(checkboxLayout); - checkboxBinding.textviewCheckboxName.setText(title); - checkboxBinding.checkbox.setChecked(initialValue); - checkboxBinding.textviewCheckboxDescription.setText(description); - checkboxLayout.setOnClickListener(v -> { - boolean isChecked = !checkboxBinding.checkbox.isChecked(); - checkboxBinding.checkbox.setChecked(isChecked); - checkBoxStateListener.onStateChanged(isChecked); - }); - } - -// protected void addSeparator() { -// View divider = getLayoutInflater().inflate(R.layout.divider_layout, null); -// binding.settingsLayout.addView(divider); -// } - - protected void addHeader(String title) { - View headerLayout = getLayoutInflater().inflate(R.layout.settings_header, null); - binding.settingsLayout.addView(headerLayout); - SettingsHeaderBinding headerBinding = SettingsHeaderBinding.bind(headerLayout); - headerBinding.settingsTextviewHeaderName.setText(title); - } - - protected void addSpinner(String title, List items, int initialPosition, OnItemSelectedPositionListener itemSelectedPositionListener) { - View spinnerLayout = getLayoutInflater().inflate(R.layout.settings_spinner, null); - binding.settingsLayout.addView(spinnerLayout); - SettingsSpinnerBinding spinnerBinding = SettingsSpinnerBinding.bind(spinnerLayout); - spinnerBinding.textviewSpinnerName.setText(title); - spinnerLayout.setOnClickListener(v -> spinnerBinding.spinner.performClick()); - ArrayAdapter adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_item, items); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spinnerBinding.spinner.setAdapter(adapter); - spinnerBinding.spinner.setSelection(initialPosition); - spinnerBinding.spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - itemSelectedPositionListener.onItemSelected(position); - } - - @Override - public void onNothingSelected(AdapterView parent) { - } - }); - } - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentSettingsBinding.inflate(inflater, container, false); - return binding.getRoot(); - } -} \ No newline at end of file diff --git a/src/android/app/src/main/java/info/cemu/Cemu/SpinnerRecyclerViewItem.java b/src/android/app/src/main/java/info/cemu/Cemu/SpinnerRecyclerViewItem.java new file mode 100644 index 00000000..5fd7178e --- /dev/null +++ b/src/android/app/src/main/java/info/cemu/Cemu/SpinnerRecyclerViewItem.java @@ -0,0 +1,65 @@ +package info.cemu.Cemu; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.Spinner; +import android.widget.SpinnerAdapter; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +public class SpinnerRecyclerViewItem implements RecyclerViewItem { + public interface OnItemSelectedListener { + void onItemSelected(int position); + } + + private static class SpinnerViewHolder extends RecyclerView.ViewHolder { + TextView text; + Spinner spinner; + + public SpinnerViewHolder(View itemView) { + super(itemView); + text = itemView.findViewById(R.id.spinner_label); + spinner = itemView.findViewById(R.id.spinner); + } + } + + private final SpinnerAdapter spinnerAdapter; + private final int spinnerLabelResourceId; + private final int initialSelection; + private final OnItemSelectedListener onItemSelectedListener; + + public SpinnerRecyclerViewItem(int spinnerLabelResourceId, SpinnerAdapter spinnerAdapter, int initialSelection, OnItemSelectedListener onItemSelectedListener) { + this.spinnerLabelResourceId = spinnerLabelResourceId; + this.spinnerAdapter = spinnerAdapter; + this.initialSelection = initialSelection; + this.onItemSelectedListener = onItemSelectedListener; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) { + return new SpinnerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_spinner, parent, false)); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, RecyclerView.Adapter adapter) { + SpinnerViewHolder spinnerViewHolder = (SpinnerViewHolder) viewHolder; + spinnerViewHolder.text.setText(spinnerLabelResourceId); + spinnerViewHolder.spinner.setAdapter(spinnerAdapter); + spinnerViewHolder.spinner.setSelection(initialSelection); + spinnerViewHolder.spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, int position, long l) { + if (onItemSelectedListener != null) + onItemSelectedListener.onItemSelected(position); + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + + } + }); + } +} diff --git a/src/android/app/src/main/res/layout/fragment_controller_inputs.xml b/src/android/app/src/main/res/layout/fragment_controller_inputs.xml index 26028267..121f790a 100644 --- a/src/android/app/src/main/res/layout/fragment_controller_inputs.xml +++ b/src/android/app/src/main/res/layout/fragment_controller_inputs.xml @@ -8,24 +8,6 @@ android:padding="16dp" tools:context=".ControllerInputsFragment"> - - - - - - - - - - - diff --git a/src/android/app/src/main/res/layout/layout_button.xml b/src/android/app/src/main/res/layout/layout_button.xml index 4ef6dbfd..d60ac3cb 100644 --- a/src/android/app/src/main/res/layout/layout_button.xml +++ b/src/android/app/src/main/res/layout/layout_button.xml @@ -1,5 +1,6 @@ + android:textAppearance="?attr/textAppearanceHeadline6" + tools:ignore="HardcodedText" /> + android:textColor="?android:attr/textColorSecondary" + tools:ignore="HardcodedText" /> diff --git a/src/android/app/src/main/res/layout/layout_controller_header.xml b/src/android/app/src/main/res/layout/layout_header.xml similarity index 86% rename from src/android/app/src/main/res/layout/layout_controller_header.xml rename to src/android/app/src/main/res/layout/layout_header.xml index 6a2809b2..81b16820 100644 --- a/src/android/app/src/main/res/layout/layout_controller_header.xml +++ b/src/android/app/src/main/res/layout/layout_header.xml @@ -1,5 +1,5 @@ + + + + + + diff --git a/src/android/app/src/main/res/layout/settings_spinner.xml b/src/android/app/src/main/res/layout/settings_spinner.xml deleted file mode 100644 index 86954226..00000000 --- a/src/android/app/src/main/res/layout/settings_spinner.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index bd652bfa..619d76d9 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -59,4 +59,10 @@ Exit Confirmation Yes No + Buttons + D-Pad + Left Axis + Right Axis + Extra + Nunchuck \ No newline at end of file