From 5f5c95e7dab040ead159c155e03e9ac3342a50f1 Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Wed, 1 Mar 2023 13:37:21 -0500 Subject: [PATCH] Android: Convert CheatDetailsFragment to Kotlin --- .../cheats/ui/CheatDetailsFragment.java | 178 ------------------ .../cheats/ui/CheatDetailsFragment.kt | 170 +++++++++++++++++ 2 files changed, 170 insertions(+), 178 deletions(-) delete mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatDetailsFragment.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatDetailsFragment.kt diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatDetailsFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatDetailsFragment.java deleted file mode 100644 index 9e118e3932..0000000000 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatDetailsFragment.java +++ /dev/null @@ -1,178 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.dolphinemu.dolphinemu.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 com.google.android.material.dialog.MaterialAlertDialogBuilder; - -import org.dolphinemu.dolphinemu.R; -import org.dolphinemu.dolphinemu.databinding.FragmentCheatDetailsBinding; -import org.dolphinemu.dolphinemu.features.cheats.model.Cheat; -import org.dolphinemu.dolphinemu.features.cheats.model.CheatsViewModel; - -public class CheatDetailsFragment extends Fragment -{ - private CheatsViewModel mViewModel; - private Cheat mCheat; - - private FragmentCheatDetailsBinding mBinding; - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) - { - mBinding = FragmentCheatDetailsBinding.inflate(inflater, container, false); - return mBinding.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) - { - CheatsActivity activity = (CheatsActivity) requireActivity(); - mViewModel = new ViewModelProvider(activity).get(CheatsViewModel.class); - - mViewModel.getSelectedCheat().observe(getViewLifecycleOwner(), this::onSelectedCheatUpdated); - mViewModel.getIsEditing().observe(getViewLifecycleOwner(), this::onIsEditingUpdated); - - mBinding.buttonDelete.setOnClickListener(this::onDeleteClicked); - mBinding.buttonEdit.setOnClickListener(this::onEditClicked); - mBinding.buttonCancel.setOnClickListener(this::onCancelClicked); - mBinding.buttonOk.setOnClickListener(this::onOkClicked); - - CheatsActivity.setOnFocusChangeListenerRecursively(view, - (v, hasFocus) -> activity.onDetailsViewFocusChange(hasFocus)); - } - - @Override - public void onDestroyView() - { - super.onDestroyView(); - mBinding = null; - } - - private void clearEditErrors() - { - mBinding.editName.setError(null); - mBinding.editCode.setError(null); - } - - private void onDeleteClicked(View view) - { - new MaterialAlertDialogBuilder(requireContext()) - .setMessage(getString(R.string.cheats_delete_confirmation, mCheat.getName())) - .setPositiveButton(R.string.yes, (dialog, i) -> mViewModel.deleteSelectedCheat()) - .setNegativeButton(R.string.no, null) - .show(); - } - - private void onEditClicked(View view) - { - mViewModel.setIsEditing(true); - mBinding.buttonOk.requestFocus(); - } - - private void onCancelClicked(View view) - { - mViewModel.setIsEditing(false); - onSelectedCheatUpdated(mCheat); - mBinding.buttonDelete.requestFocus(); - } - - private void onOkClicked(View view) - { - clearEditErrors(); - - int result = mCheat.trySet(mBinding.editNameInput.getText().toString(), - mBinding.editCreatorInput.getText().toString(), - mBinding.editNotesInput.getText().toString(), - mBinding.editCodeInput.getText().toString()); - - switch (result) - { - case Cheat.TRY_SET_SUCCESS: - if (mViewModel.getIsAdding().getValue()) - { - mViewModel.finishAddingCheat(); - onSelectedCheatUpdated(mCheat); - } - else - { - mViewModel.notifySelectedCheatChanged(); - mViewModel.setIsEditing(false); - } - mBinding.buttonEdit.requestFocus(); - break; - case Cheat.TRY_SET_FAIL_NO_NAME: - mBinding.editName.setError(getString(R.string.cheats_error_no_name)); - mBinding.scrollView.smoothScrollTo(0, mBinding.editNameInput.getTop()); - break; - case Cheat.TRY_SET_FAIL_NO_CODE_LINES: - mBinding.editCode.setError(getString(R.string.cheats_error_no_code_lines)); - mBinding.scrollView.smoothScrollTo(0, mBinding.editCodeInput.getBottom()); - break; - case Cheat.TRY_SET_FAIL_CODE_MIXED_ENCRYPTION: - mBinding.editCode.setError(getString(R.string.cheats_error_mixed_encryption)); - mBinding.scrollView.smoothScrollTo(0, mBinding.editCodeInput.getBottom()); - break; - default: - mBinding.editCode.setError(getString(R.string.cheats_error_on_line, result)); - mBinding.scrollView.smoothScrollTo(0, mBinding.editCodeInput.getBottom()); - break; - } - } - - private void onSelectedCheatUpdated(@Nullable Cheat cheat) - { - clearEditErrors(); - - mBinding.root.setVisibility(cheat == null ? View.GONE : View.VISIBLE); - - int creatorVisibility = cheat != null && cheat.supportsCreator() ? View.VISIBLE : View.GONE; - int notesVisibility = cheat != null && cheat.supportsNotes() ? View.VISIBLE : View.GONE; - int codeVisibility = cheat != null && cheat.supportsCode() ? View.VISIBLE : View.GONE; - mBinding.editCreator.setVisibility(creatorVisibility); - mBinding.editNotes.setVisibility(notesVisibility); - mBinding.editCode.setVisibility(codeVisibility); - - boolean userDefined = cheat != null && cheat.getUserDefined(); - mBinding.buttonDelete.setEnabled(userDefined); - mBinding.buttonEdit.setEnabled(userDefined); - - // 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 - boolean isEditing = mViewModel.getIsEditing().getValue(); - - if (!isEditing && cheat != null) - { - mBinding.editNameInput.setText(cheat.getName()); - mBinding.editCreatorInput.setText(cheat.getCreator()); - mBinding.editNotesInput.setText(cheat.getNotes()); - mBinding.editCodeInput.setText(cheat.getCode()); - } - - mCheat = cheat; - } - - private void onIsEditingUpdated(boolean isEditing) - { - mBinding.editNameInput.setEnabled(isEditing); - mBinding.editCreatorInput.setEnabled(isEditing); - mBinding.editNotesInput.setEnabled(isEditing); - mBinding.editCodeInput.setEnabled(isEditing); - - mBinding.buttonDelete.setVisibility(isEditing ? View.GONE : View.VISIBLE); - mBinding.buttonEdit.setVisibility(isEditing ? View.GONE : View.VISIBLE); - mBinding.buttonCancel.setVisibility(isEditing ? View.VISIBLE : View.GONE); - mBinding.buttonOk.setVisibility(isEditing ? View.VISIBLE : View.GONE); - } -} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatDetailsFragment.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatDetailsFragment.kt new file mode 100644 index 0000000000..1d473ef6e0 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatDetailsFragment.kt @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.cheats.ui + +import android.content.DialogInterface +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelProvider +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import org.dolphinemu.dolphinemu.R +import org.dolphinemu.dolphinemu.databinding.FragmentCheatDetailsBinding +import org.dolphinemu.dolphinemu.features.cheats.model.Cheat +import org.dolphinemu.dolphinemu.features.cheats.model.CheatsViewModel + +class CheatDetailsFragment : Fragment() { + private lateinit var viewModel: CheatsViewModel + private var cheat: Cheat? = null + + private var _binding: FragmentCheatDetailsBinding? = null + private val binding get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentCheatDetailsBinding.inflate(inflater, container, false) + return binding.getRoot() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + val activity = requireActivity() as CheatsActivity + viewModel = ViewModelProvider(activity)[CheatsViewModel::class.java] + + viewModel.selectedCheat.observe(viewLifecycleOwner) { cheat: Cheat? -> + onSelectedCheatUpdated( + cheat + ) + } + viewModel.isEditing.observe(viewLifecycleOwner) { isEditing: Boolean -> + onIsEditingUpdated( + isEditing + ) + } + + binding.buttonDelete.setOnClickListener { onDeleteClicked() } + binding.buttonEdit.setOnClickListener { onEditClicked() } + binding.buttonCancel.setOnClickListener { onCancelClicked() } + binding.buttonOk.setOnClickListener { onOkClicked() } + + CheatsActivity.setOnFocusChangeListenerRecursively( + view + ) { _: View?, hasFocus: Boolean -> activity.onDetailsViewFocusChange(hasFocus) } + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + private fun clearEditErrors() { + binding.editName.error = null + binding.editCode.error = null + } + + private fun onDeleteClicked() { + MaterialAlertDialogBuilder(requireContext()) + .setMessage(getString(R.string.cheats_delete_confirmation, cheat!!.getName())) + .setPositiveButton(R.string.yes) { _: DialogInterface?, i: Int -> viewModel.deleteSelectedCheat() } + .setNegativeButton(R.string.no, null) + .show() + } + + private fun onEditClicked() { + viewModel.setIsEditing(true) + binding.buttonOk.requestFocus() + } + + private fun onCancelClicked() { + viewModel.setIsEditing(false) + onSelectedCheatUpdated(cheat) + binding.buttonDelete.requestFocus() + } + + private fun onOkClicked() { + clearEditErrors() + + val result = cheat!!.setCheat( + binding.editNameInput.text.toString(), + binding.editCreatorInput.text.toString(), + binding.editNotesInput.text.toString(), + binding.editCodeInput.text.toString() + ) + + when (result) { + Cheat.TRY_SET_SUCCESS -> { + if (viewModel.isAdding.value!!) { + viewModel.finishAddingCheat() + onSelectedCheatUpdated(cheat) + } else { + viewModel.notifySelectedCheatChanged() + viewModel.setIsEditing(false) + } + binding.buttonEdit.requestFocus() + } + Cheat.TRY_SET_FAIL_NO_NAME -> { + binding.editName.error = getString(R.string.cheats_error_no_name) + binding.scrollView.smoothScrollTo(0, binding.editNameInput.top) + } + Cheat.TRY_SET_FAIL_NO_CODE_LINES -> { + binding.editCode.error = getString(R.string.cheats_error_no_code_lines) + binding.scrollView.smoothScrollTo(0, binding.editCodeInput.bottom) + } + Cheat.TRY_SET_FAIL_CODE_MIXED_ENCRYPTION -> { + binding.editCode.error = getString(R.string.cheats_error_mixed_encryption) + binding.scrollView.smoothScrollTo(0, binding.editCodeInput.bottom) + } + else -> { + binding.editCode.error = getString(R.string.cheats_error_on_line, result) + binding.scrollView.smoothScrollTo(0, binding.editCodeInput.bottom) + } + } + } + + private fun onSelectedCheatUpdated(cheat: Cheat?) { + clearEditErrors() + + binding.root.visibility = if (cheat == null) View.GONE else View.VISIBLE + + val creatorVisibility = + if (cheat != null && cheat.supportsCreator()) View.VISIBLE else View.GONE + val notesVisibility = + if (cheat != null && cheat.supportsNotes()) View.VISIBLE else View.GONE + val codeVisibility = if (cheat != null && cheat.supportsCode()) View.VISIBLE else View.GONE + binding.editCreator.visibility = creatorVisibility + binding.editNotes.visibility = notesVisibility + binding.editCode.visibility = codeVisibility + + val userDefined = cheat != null && cheat.getUserDefined() + binding.buttonDelete.isEnabled = userDefined + binding.buttonEdit.isEnabled = userDefined + + // 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 + val isEditing = viewModel.isEditing.value!! + + if (!isEditing && cheat != null) { + binding.editNameInput.setText(cheat.getName()) + binding.editCreatorInput.setText(cheat.getCreator()) + binding.editNotesInput.setText(cheat.getNotes()) + binding.editCodeInput.setText(cheat.getCode()) + } + this.cheat = cheat + } + + private fun onIsEditingUpdated(isEditing: Boolean) { + binding.editNameInput.isEnabled = isEditing + binding.editCreatorInput.isEnabled = isEditing + binding.editNotesInput.isEnabled = isEditing + binding.editCodeInput.isEnabled = isEditing + + binding.buttonDelete.visibility = if (isEditing) View.GONE else View.VISIBLE + binding.buttonEdit.visibility = if (isEditing) View.GONE else View.VISIBLE + binding.buttonCancel.visibility = if (isEditing) View.VISIBLE else View.GONE + binding.buttonOk.visibility = if (isEditing) View.VISIBLE else View.GONE + } +}