0
0
mirror of https://github.com/ankidroid/Anki-Android.git synced 2024-09-20 12:02:16 +02:00

[Kotlin Migration] BasicTextFieldController

This commit is contained in:
Akshay 2022-01-08 18:55:04 +05:30 committed by Mike Hardy
parent 2725de8ac4
commit 5677a459b6
2 changed files with 191 additions and 254 deletions

View File

@ -43,7 +43,7 @@ permission notice:
// Example of class name: "/com/ichi2/anki/UIUtils.kt"
// Ensure that it starts with '/' (slash)
def source = Source.MAIN
def className = "/com/ichi2/anki/multimediacard/fields/BasicTextFieldController.kt"
def className = ""
enum Source {
MAIN("/src/main/java"),

View File

@ -17,370 +17,307 @@
* this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************/
package com.ichi2.anki.multimediacard.fields;
package com.ichi2.anki.multimediacard.fields
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.view.Gravity;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import com.ichi2.anki.R;
import com.ichi2.anki.UIUtils;
import com.ichi2.anki.multimediacard.activity.LoadPronounciationActivity;
import com.ichi2.anki.multimediacard.activity.PickStringDialogFragment;
import com.ichi2.anki.multimediacard.activity.TranslationActivity;
import com.ichi2.compat.CompatHelper;
import com.ichi2.ui.FixedEditText;
import com.ichi2.ui.FixedTextView;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import timber.log.Timber;
import android.app.Activity
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.PackageManager
import android.view.Gravity
import android.widget.Button
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.TextView
import com.ichi2.anki.R
import com.ichi2.anki.UIUtils.showThemedToast
import com.ichi2.anki.multimediacard.activity.LoadPronounciationActivity
import com.ichi2.anki.multimediacard.activity.PickStringDialogFragment
import com.ichi2.anki.multimediacard.activity.TranslationActivity
import com.ichi2.compat.CompatHelper
import com.ichi2.ui.FixedEditText
import com.ichi2.ui.FixedTextView
import com.ichi2.utils.KotlinCleanup
import timber.log.Timber
import java.io.File
import java.util.*
/**
* One of the most powerful controllers - creates UI and works with the field of textual type.
* <p>
* Controllers work with the edit field activity and create UI on it to edit a field.
*/
public class BasicTextFieldController extends FieldControllerBase implements IFieldController,
DialogInterface.OnClickListener {
// Additional activities are started to perform translation/pronunciation search and
// so on, here are their request codes, to differentiate, when they return.
private static final int REQUEST_CODE_TRANSLATE_GLOSBE = 101;
private static final int REQUEST_CODE_PRONOUNCIATION = 102;
private static final int REQUEST_CODE_TRANSLATE_COLORDICT = 103;
private EditText mEditText;
@KotlinCleanup("lateinit")
class BasicTextFieldController : FieldControllerBase(), IFieldController, DialogInterface.OnClickListener {
private var mEditText: EditText? = null
// This is used to copy from another field value to this field
private ArrayList<String> mPossibleClones;
@Override
public void createUI(Context context, LinearLayout layout) {
mEditText = new FixedEditText(mActivity);
mEditText.setMinLines(3);
mEditText.setText(mField.getText());
layout.addView(mEditText, LayoutParams.MATCH_PARENT);
LinearLayout layoutTools = new LinearLayout(mActivity);
layoutTools.setOrientation(LinearLayout.HORIZONTAL);
layout.addView(layoutTools);
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1);
createCloneButton(layoutTools, p);
createClearButton(layoutTools, p);
private var mPossibleClones: ArrayList<String>? = null
override fun createUI(context: Context?, layout: LinearLayout?) {
mEditText = FixedEditText(mActivity)
mEditText!!.minLines = 3
mEditText!!.setText(mField.text)
layout!!.addView(mEditText, LinearLayout.LayoutParams.MATCH_PARENT)
val layoutTools = LinearLayout(mActivity)
layoutTools.orientation = LinearLayout.HORIZONTAL
layout.addView(layoutTools)
val p = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1F)
createCloneButton(layoutTools, p)
createClearButton(layoutTools, p)
// search label
TextView searchLabel = new FixedTextView(mActivity);
searchLabel.setText(R.string.multimedia_editor_text_field_editing_search_label);
layout.addView(searchLabel);
val searchLabel: TextView = FixedTextView(mActivity)
searchLabel.setText(R.string.multimedia_editor_text_field_editing_search_label)
layout.addView(searchLabel)
// search buttons
LinearLayout layoutTools2 = new LinearLayout(mActivity);
layoutTools2.setOrientation(LinearLayout.HORIZONTAL);
layout.addView(layoutTools2);
createTranslateButton(layoutTools2, p);
createPronounceButton(layoutTools2, p);
val layoutTools2 = LinearLayout(mActivity)
layoutTools2.orientation = LinearLayout.HORIZONTAL
layout.addView(layoutTools2)
createTranslateButton(layoutTools2, p)
createPronounceButton(layoutTools2, p)
}
private String gtxt(int id) {
return mActivity.getText(id).toString();
private fun gtxt(id: Int): String {
return mActivity.getText(id).toString()
}
private void createClearButton(LinearLayout layoutTools, LayoutParams p) {
Button clearButton = new Button(mActivity);
clearButton.setText(gtxt(R.string.multimedia_editor_text_field_editing_clear));
layoutTools.addView(clearButton, p);
clearButton.setOnClickListener(v -> mEditText.setText(""));
private fun createClearButton(layoutTools: LinearLayout, p: LinearLayout.LayoutParams) {
val clearButton = Button(mActivity)
clearButton.text = gtxt(R.string.multimedia_editor_text_field_editing_clear)
layoutTools.addView(clearButton, p)
clearButton.setOnClickListener { mEditText!!.setText("") }
}
/**
* @param layoutTools to create the button
* @param p Button to load pronunciation from Beolingus
*/
private void createPronounceButton(LinearLayout layoutTools, LayoutParams p) {
Button btnPronounce = new Button(mActivity);
btnPronounce.setText(gtxt(R.string.multimedia_editor_text_field_editing_say));
btnPronounce.setOnClickListener(v -> {
String source = mEditText.getText().toString();
if (source.length() == 0) {
showToast(gtxt(R.string.multimedia_editor_text_field_editing_no_text));
return;
private fun createPronounceButton(layoutTools: LinearLayout, p: LinearLayout.LayoutParams) {
val btnPronounce = Button(mActivity)
btnPronounce.text = gtxt(R.string.multimedia_editor_text_field_editing_say)
btnPronounce.setOnClickListener {
val source = mEditText!!.text.toString()
if (source.isEmpty()) {
showToast(gtxt(R.string.multimedia_editor_text_field_editing_no_text))
return@setOnClickListener
}
Intent intent = new Intent(mActivity, LoadPronounciationActivity.class);
intent.putExtra(LoadPronounciationActivity.EXTRA_SOURCE, source);
mActivity.startActivityForResultWithoutAnimation(intent, REQUEST_CODE_PRONOUNCIATION);
});
layoutTools.addView(btnPronounce, p);
val intent = Intent(mActivity, LoadPronounciationActivity::class.java)
intent.putExtra(LoadPronounciationActivity.EXTRA_SOURCE, source)
mActivity.startActivityForResultWithoutAnimation(intent, REQUEST_CODE_PRONOUNCIATION)
}
layoutTools.addView(btnPronounce, p)
}
// Here is all the functionality to provide translations
private void createTranslateButton(LinearLayout layoutTool, LayoutParams ps) {
Button btnTranslate = new Button(mActivity);
btnTranslate.setText(gtxt(R.string.multimedia_editor_text_field_editing_translate));
btnTranslate.setOnClickListener(v -> {
String source = mEditText.getText().toString();
private fun createTranslateButton(layoutTool: LinearLayout, ps: LinearLayout.LayoutParams) {
val btnTranslate = Button(mActivity)
btnTranslate.text = gtxt(R.string.multimedia_editor_text_field_editing_translate)
btnTranslate.setOnClickListener {
val source = mEditText!!.text.toString()
// Checks and warnings
if (source.length() == 0) {
showToast(gtxt(R.string.multimedia_editor_text_field_editing_no_text));
return;
if (source.isEmpty()) {
showToast(gtxt(R.string.multimedia_editor_text_field_editing_no_text))
return@setOnClickListener
}
if (source.contains(" ")) {
showToast(gtxt(R.string.multimedia_editor_text_field_editing_many_words));
showToast(gtxt(R.string.multimedia_editor_text_field_editing_many_words))
}
// Pick from two translation sources
PickStringDialogFragment fragment = new PickStringDialogFragment();
final ArrayList<String> translationSources = new ArrayList<>(2);
translationSources.add("Glosbe.com");
val fragment = PickStringDialogFragment()
val translationSources = ArrayList<String>(2)
translationSources.add("Glosbe.com")
// Chromebooks do not support dependent apps yet.
if (!CompatHelper.isChromebook()) {
translationSources.add("ColorDict");
translationSources.add("ColorDict")
}
fragment.setChoices(translationSources);
fragment.setOnclickListener((dialog, which) -> {
String translationSource = translationSources.get(which);
if ("Glosbe.com".equals(translationSource)) {
startTranslationWithGlosbe();
} else if ("ColorDict".equals(translationSource)) {
startTranslationWithColorDict();
fragment.setChoices(translationSources)
fragment.setOnclickListener { _: DialogInterface?, which: Int ->
val translationSource = translationSources[which]
if ("Glosbe.com" == translationSource) {
startTranslationWithGlosbe()
} else if ("ColorDict" == translationSource) {
startTranslationWithColorDict()
}
});
fragment.setTitle(gtxt(R.string.multimedia_editor_trans_pick_translation_source));
fragment.show(mActivity.getSupportFragmentManager(), "pick.translation.source");
});
layoutTool.addView(btnTranslate, ps);
}
fragment.setTitle(gtxt(R.string.multimedia_editor_trans_pick_translation_source))
fragment.show(mActivity.supportFragmentManager, "pick.translation.source")
}
layoutTool.addView(btnTranslate, ps)
// flow continues in Start Translation with...
}
/**
* @param layoutTools This creates a button, which will call a dialog, allowing to pick from another note's fields
* one, and use it's value in the current one.
* @param p layout params
*/
private void createCloneButton(LinearLayout layoutTools, LayoutParams p) {
private fun createCloneButton(layoutTools: LinearLayout, p: LinearLayout.LayoutParams) {
// Makes sense only for two and more fields
if (mNote.getNumberOfFields() > 1) {
if (mNote.numberOfFields > 1) {
// Should be more than one text not empty fields for clone to make
// sense
mPossibleClones = new ArrayList<>(mNote.getNumberOfFields());
int numTextFields = 0;
for (int i = 0; i < mNote.getNumberOfFields(); ++i) {
mPossibleClones = ArrayList(mNote.numberOfFields)
var numTextFields = 0
for (i in 0 until mNote.numberOfFields) {
// Sort out non text and empty fields
IField curField = mNote.getField(i);
if (curField == null) {
continue;
val curField = mNote.getField(i) ?: continue
if (curField.type !== EFieldType.TEXT) {
continue
}
if (curField.getType() != EFieldType.TEXT) {
continue;
if (curField.text == null) {
continue
}
if (curField.getText() == null) {
continue;
}
if (curField.getText().length() == 0) {
continue;
if (curField.text.isNullOrEmpty()) {
continue
}
// as well as the same field
if (curField.getText().contentEquals(mField.getText())) {
continue;
if (curField.text?.contentEquals(mField.text) == true) {
continue
}
// collect clone sources
mPossibleClones.add(curField.getText());
++numTextFields;
mPossibleClones!!.add(curField.text)
++numTextFields
}
// Nothing to clone from
if (numTextFields < 1) {
return;
return
}
val btnOtherField = Button(mActivity)
btnOtherField.text = gtxt(R.string.multimedia_editor_text_field_editing_clone)
layoutTools.addView(btnOtherField, p)
val controller = this
btnOtherField.setOnClickListener {
val fragment = PickStringDialogFragment()
fragment.setChoices(mPossibleClones)
fragment.setOnclickListener(controller)
fragment.setTitle(gtxt(R.string.multimedia_editor_text_field_editing_clone_source))
fragment.show(mActivity.supportFragmentManager, "pick.clone")
}
Button btnOtherField = new Button(mActivity);
btnOtherField.setText(gtxt(R.string.multimedia_editor_text_field_editing_clone));
layoutTools.addView(btnOtherField, p);
final BasicTextFieldController controller = this;
btnOtherField.setOnClickListener(v -> {
PickStringDialogFragment fragment = new PickStringDialogFragment();
fragment.setChoices(mPossibleClones);
fragment.setOnclickListener(controller);
fragment.setTitle(gtxt(R.string.multimedia_editor_text_field_editing_clone_source));
fragment.show(mActivity.getSupportFragmentManager(), "pick.clone");
// flow continues in the onClick function
});
}
}
/*
* (non-Javadoc)
* @see com.ichi2.anki.IFieldController#onActivityResult(int, int, android.content.Intent) When activity started
* from here returns, the MultimediaEditFieldActivity passes control here back. And the results from the started before
* activity are received.
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_CODE_TRANSLATE_GLOSBE && resultCode == Activity.RESULT_OK) {
// Translation returned.
try {
String translation = data.getExtras().get(TranslationActivity.EXTRA_TRANSLATION).toString();
mEditText.setText(translation);
} catch (Exception e) {
Timber.w(e);
showToast(gtxt(R.string.multimedia_editor_something_wrong));
val translation = data!!.extras!![TranslationActivity.EXTRA_TRANSLATION].toString()
mEditText!!.setText(translation)
} catch (e: Exception) {
Timber.w(e)
showToast(gtxt(R.string.multimedia_editor_something_wrong))
}
} else if (requestCode == REQUEST_CODE_PRONOUNCIATION && resultCode == Activity.RESULT_OK) {
try {
String pronuncPath = data.getExtras().get(LoadPronounciationActivity.EXTRA_PRONUNCIATION_FILE_PATH)
.toString();
File f = new File(pronuncPath);
val pronuncPath = data!!.extras!![LoadPronounciationActivity.EXTRA_PRONUNCIATION_FILE_PATH]
.toString()
val f = File(pronuncPath)
if (!f.exists()) {
showToast(gtxt(R.string.multimedia_editor_pron_pronunciation_failed));
showToast(gtxt(R.string.multimedia_editor_pron_pronunciation_failed))
}
AudioField af = new AudioRecordingField();
af.setAudioPath(pronuncPath);
val af: AudioField = AudioRecordingField()
af.audioPath = pronuncPath
// This is done to delete the file later.
af.setHasTemporaryMedia(true);
mActivity.handleFieldChanged(af);
} catch (Exception e) {
Timber.w(e);
showToast(gtxt(R.string.multimedia_editor_pron_pronunciation_failed));
af.setHasTemporaryMedia(true)
mActivity.handleFieldChanged(af)
} catch (e: Exception) {
Timber.w(e)
showToast(gtxt(R.string.multimedia_editor_pron_pronunciation_failed))
}
} else if (requestCode == REQUEST_CODE_TRANSLATE_COLORDICT && resultCode == Activity.RESULT_OK) {
// String subject = data.getStringExtra(Intent.EXTRA_SUBJECT);
String text = data.getStringExtra(Intent.EXTRA_TEXT);
mEditText.setText(text);
val text = data!!.getStringExtra(Intent.EXTRA_TEXT)
mEditText!!.setText(text)
}
}
@Override
public void onFocusLost() {
override fun onFocusLost() {
// do nothing
}
/**
* @param context context with the PackageManager
* @param intent intent for state data
* @return Needed to check, if the Color Dict is installed
*/
private static boolean isIntentAvailable(Context context, Intent intent) {
final PackageManager packageManager = context.getPackageManager();
List<?> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
return !list.isEmpty();
}
// When Done button is clicked
@Override
public void onDone() {
mField.setText(mEditText.getText().toString());
override fun onDone() {
mField.text = mEditText!!.text.toString()
}
// This is when the dialog for clone ends
@Override
public void onClick(DialogInterface dialog, int which) {
mEditText.setText(mPossibleClones.get(which));
override fun onClick(dialog: DialogInterface, which: Int) {
mEditText!!.setText(mPossibleClones!![which])
}
/**
* @param text A short cut to show a toast
*/
private void showToast(CharSequence text) {
UIUtils.showThemedToast(mActivity, text, true);
private fun showToast(text: CharSequence) {
showThemedToast(mActivity, text, true)
}
// Only now not all APIs are used, may be later, they will be.
@SuppressWarnings("unused")
private void startTranslationWithColorDict() {
final String PICK_RESULT_ACTION = "colordict.intent.action.PICK_RESULT";
final String SEARCH_ACTION = "colordict.intent.action.SEARCH";
final String EXTRA_QUERY = "EXTRA_QUERY";
final String EXTRA_FULLSCREEN = "EXTRA_FULLSCREEN";
final String EXTRA_HEIGHT = "EXTRA_HEIGHT";
final String EXTRA_WIDTH = "EXTRA_WIDTH";
final String EXTRA_GRAVITY = "EXTRA_GRAVITY";
final String EXTRA_MARGIN_LEFT = "EXTRA_MARGIN_LEFT";
final String EXTRA_MARGIN_TOP = "EXTRA_MARGIN_TOP";
final String EXTRA_MARGIN_BOTTOM = "EXTRA_MARGIN_BOTTOM";
final String EXTRA_MARGIN_RIGHT = "EXTRA_MARGIN_RIGHT";
Intent intent = new Intent(PICK_RESULT_ACTION);
intent.putExtra(EXTRA_QUERY, mEditText.getText().toString()); // Search
// Query
intent.putExtra(EXTRA_FULLSCREEN, false); //
@Suppress("Unused_Variable")
private fun startTranslationWithColorDict() {
val PICK_RESULT_ACTION = "colordict.intent.action.PICK_RESULT"
val SEARCH_ACTION = "colordict.intent.action.SEARCH"
val EXTRA_QUERY = "EXTRA_QUERY"
val EXTRA_FULLSCREEN = "EXTRA_FULLSCREEN"
val EXTRA_HEIGHT = "EXTRA_HEIGHT"
val EXTRA_WIDTH = "EXTRA_WIDTH"
val EXTRA_GRAVITY = "EXTRA_GRAVITY"
val EXTRA_MARGIN_LEFT = "EXTRA_MARGIN_LEFT"
val EXTRA_MARGIN_TOP = "EXTRA_MARGIN_TOP"
val EXTRA_MARGIN_BOTTOM = "EXTRA_MARGIN_BOTTOM"
val EXTRA_MARGIN_RIGHT = "EXTRA_MARGIN_RIGHT"
val intent = Intent(PICK_RESULT_ACTION)
intent.putExtra(EXTRA_QUERY, mEditText!!.text.toString()) // Search
// Query
intent.putExtra(EXTRA_FULLSCREEN, false) //
// intent.putExtra(EXTRA_HEIGHT, 400); //400pixel, if you don't specify,
// fill_parent"
intent.putExtra(EXTRA_GRAVITY, Gravity.BOTTOM);
intent.putExtra(EXTRA_GRAVITY, Gravity.BOTTOM)
// intent.putExtra(EXTRA_MARGIN_LEFT, 100);
if (!isIntentAvailable(mActivity, intent)) {
showToast(gtxt(R.string.multimedia_editor_trans_install_color_dict));
return;
showToast(gtxt(R.string.multimedia_editor_trans_install_color_dict))
return
}
mActivity.startActivityForResultWithoutAnimation(intent, REQUEST_CODE_TRANSLATE_COLORDICT);
mActivity.startActivityForResultWithoutAnimation(intent, REQUEST_CODE_TRANSLATE_COLORDICT)
}
private void startTranslationWithGlosbe() {
String source = mEditText.getText().toString();
Intent intent = new Intent(mActivity, TranslationActivity.class);
intent.putExtra(TranslationActivity.EXTRA_SOURCE, source);
mActivity.startActivityForResultWithoutAnimation(intent, REQUEST_CODE_TRANSLATE_GLOSBE);
private fun startTranslationWithGlosbe() {
val source = mEditText!!.text.toString()
val intent = Intent(mActivity, TranslationActivity::class.java)
intent.putExtra(TranslationActivity.EXTRA_SOURCE, source)
mActivity.startActivityForResultWithoutAnimation(intent, REQUEST_CODE_TRANSLATE_GLOSBE)
}
@Override
public void onDestroy() {
override fun onDestroy() {
// TODO Auto-generated method stub
}
companion object {
// Additional activities are started to perform translation/pronunciation search and
// so on, here are their request codes, to differentiate, when they return.
private const val REQUEST_CODE_TRANSLATE_GLOSBE = 101
private const val REQUEST_CODE_PRONOUNCIATION = 102
private const val REQUEST_CODE_TRANSLATE_COLORDICT = 103
/**
* @param context context with the PackageManager
* @param intent intent for state data
* @return Needed to check, if the Color Dict is installed
*/
private fun isIntentAvailable(context: Context, intent: Intent): Boolean {
val packageManager = context.packageManager
val list: List<*> = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
return list.isNotEmpty()
}
}
}