From fe4483582016a071d9d25e3dfbbeb1c1afc9e25f Mon Sep 17 00:00:00 2001 From: "kr.angelov" Date: Thu, 10 Oct 2013 15:39:52 +0000 Subject: [PATCH] an improvised dictionary mode in the Android translator --- src/ui/android/AndroidManifest.xml | 3 +- .../res/drawable-xhdpi/ic_dictionary.png | Bin 0 -> 3591 bytes .../res/layout/activity_lexical_entry.xml | 24 +++++++ .../res/layout/first_person_utterance.xml | 38 +++++++---- .../ui/android/ConversationView.java | 49 +++++++++++--- .../ui/android/GFTranslator.java | 16 +++++ .../ui/android/Language.java | 15 ++++- .../ui/android/LanguageSelector.java | 4 ++ .../ui/android/LexicalEntryActivity.java | 60 ++++++++++++++++++ .../ui/android/MainActivity.java | 33 +++++++--- .../ui/android/Translator.java | 19 ++++-- 11 files changed, 223 insertions(+), 38 deletions(-) create mode 100644 src/ui/android/res/drawable-xhdpi/ic_dictionary.png create mode 100644 src/ui/android/res/layout/activity_lexical_entry.xml create mode 100644 src/ui/android/src/org/grammaticalframework/ui/android/GFTranslator.java create mode 100644 src/ui/android/src/org/grammaticalframework/ui/android/LexicalEntryActivity.java diff --git a/src/ui/android/AndroidManifest.xml b/src/ui/android/AndroidManifest.xml index 9728b71aa..d9f983e65 100644 --- a/src/ui/android/AndroidManifest.xml +++ b/src/ui/android/AndroidManifest.xml @@ -14,7 +14,7 @@ android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" - android:theme="@style/AppTheme" > + android:theme="@style/AppTheme" android:name="GFTranslator"> @@ -24,6 +24,7 @@ + diff --git a/src/ui/android/res/drawable-xhdpi/ic_dictionary.png b/src/ui/android/res/drawable-xhdpi/ic_dictionary.png new file mode 100644 index 0000000000000000000000000000000000000000..985644ebd18dc6d62a42c2d9834fadb59fd809e2 GIT binary patch literal 3591 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 literal 0 HcmV?d00001 diff --git a/src/ui/android/res/layout/activity_lexical_entry.xml b/src/ui/android/res/layout/activity_lexical_entry.xml new file mode 100644 index 000000000..75be89885 --- /dev/null +++ b/src/ui/android/res/layout/activity_lexical_entry.xml @@ -0,0 +1,24 @@ + + + + + + + + \ No newline at end of file diff --git a/src/ui/android/res/layout/first_person_utterance.xml b/src/ui/android/res/layout/first_person_utterance.xml index 55779ae8f..ce0abf875 100644 --- a/src/ui/android/res/layout/first_person_utterance.xml +++ b/src/ui/android/res/layout/first_person_utterance.xml @@ -1,11 +1,27 @@ - + + + + + + + + \ No newline at end of file diff --git a/src/ui/android/src/org/grammaticalframework/ui/android/ConversationView.java b/src/ui/android/src/org/grammaticalframework/ui/android/ConversationView.java index 3923d13a0..75d34f886 100644 --- a/src/ui/android/src/org/grammaticalframework/ui/android/ConversationView.java +++ b/src/ui/android/src/org/grammaticalframework/ui/android/ConversationView.java @@ -3,7 +3,9 @@ package org.grammaticalframework.ui.android; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; +import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.ScrollView; import android.widget.TextView; @@ -12,6 +14,8 @@ public class ConversationView extends ScrollView { private LayoutInflater mInflater; private ViewGroup mContent; + + private OnWordSelectedListener mListener; public ConversationView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); @@ -33,15 +37,21 @@ public class ConversationView extends ScrollView { } public void addFirstPersonUtterance(CharSequence text) { - addUtterance(R.layout.first_person_utterance, text); + View view = + mInflater.inflate(R.layout.first_person_utterance, mContent, false); + TextView textview = (TextView) view.findViewById(R.id.text); + textview.setText(text); + mContent.addView(view); + post(new Runnable() { + public void run() { + fullScroll(FOCUS_DOWN); + } + }); } public void addSecondPersonUtterance(CharSequence text) { - addUtterance(R.layout.second_person_utterance, text); - } - - private void addUtterance(int res, CharSequence text) { - TextView view = (TextView) mInflater.inflate(res, mContent, false); + TextView view = (TextView) + mInflater.inflate(R.layout.second_person_utterance, mContent, false); view.setText(text); mContent.addView(view); post(new Runnable() { @@ -51,12 +61,33 @@ public class ConversationView extends ScrollView { }); } - public void updateLastUtterance(CharSequence text) { + public void updateLastUtterance(CharSequence text, Object lexicon) { int count = mContent.getChildCount(); if (count > 0) { - TextView view = (TextView) mContent.getChildAt(count - 1); - view.setText(text); + View view = mContent.getChildAt(count - 1); + TextView textview = (TextView) view.findViewById(R.id.text); + textview.setText(text); + + if (lexicon != null && mListener != null) { + ImageView showWordButton = (ImageView) view.findViewById(R.id.show_word); + showWordButton.setVisibility(VISIBLE); + + final Object lexicon2 = lexicon; + showWordButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mListener.onWordSelected(lexicon2); + } + }); + } } } + public void setOnWordSelectedListener(OnWordSelectedListener listener) { + mListener = listener; + } + + public interface OnWordSelectedListener { + public void onWordSelected(Object lexicon); + } } diff --git a/src/ui/android/src/org/grammaticalframework/ui/android/GFTranslator.java b/src/ui/android/src/org/grammaticalframework/ui/android/GFTranslator.java new file mode 100644 index 000000000..ee4cbc092 --- /dev/null +++ b/src/ui/android/src/org/grammaticalframework/ui/android/GFTranslator.java @@ -0,0 +1,16 @@ +package org.grammaticalframework.ui.android; + +import android.app.Application; + +public class GFTranslator extends Application { + private Translator mTranslator; + + @Override + public void onCreate() { + mTranslator = new Translator(this); + } + + public Translator getTranslator() { + return mTranslator; + } +} diff --git a/src/ui/android/src/org/grammaticalframework/ui/android/Language.java b/src/ui/android/src/org/grammaticalframework/ui/android/Language.java index 8adc74609..cd16974ab 100644 --- a/src/ui/android/src/org/grammaticalframework/ui/android/Language.java +++ b/src/ui/android/src/org/grammaticalframework/ui/android/Language.java @@ -1,7 +1,11 @@ package org.grammaticalframework.ui.android; -public class Language { - private final String mLangCode; +import java.io.Serializable; + +public class Language implements Serializable { + private static final long serialVersionUID = 1L; + + private final String mLangCode; private final String mLangName; private final String mConcrete; @@ -27,5 +31,10 @@ public class Language { public String toString() { return getLangName(); } - + + @Override + public boolean equals(Object o) { + Language other = (Language) o; + return mLangCode.equals(other.mLangCode); + } } \ No newline at end of file diff --git a/src/ui/android/src/org/grammaticalframework/ui/android/LanguageSelector.java b/src/ui/android/src/org/grammaticalframework/ui/android/LanguageSelector.java index d3148cda4..de628b2b5 100644 --- a/src/ui/android/src/org/grammaticalframework/ui/android/LanguageSelector.java +++ b/src/ui/android/src/org/grammaticalframework/ui/android/LanguageSelector.java @@ -30,6 +30,10 @@ public class LanguageSelector extends Spinner { setSelection(((LanguagesAdapter) getAdapter()).getPosition(selected)); } + public Language getSelectedLanguage() { + return (Language) getSelectedItem(); + } + public void setOnLanguageSelectedListener(final OnLanguageSelectedListener listener) { setOnItemSelectedListener(new OnItemSelectedListener() { @Override diff --git a/src/ui/android/src/org/grammaticalframework/ui/android/LexicalEntryActivity.java b/src/ui/android/src/org/grammaticalframework/ui/android/LexicalEntryActivity.java new file mode 100644 index 000000000..d6f935113 --- /dev/null +++ b/src/ui/android/src/org/grammaticalframework/ui/android/LexicalEntryActivity.java @@ -0,0 +1,60 @@ +package org.grammaticalframework.ui.android; + +import java.util.ArrayList; +import java.util.List; + +import android.app.ListActivity; +import android.os.Bundle; +import android.widget.ArrayAdapter; + +import org.grammaticalframework.pgf.*; +import org.grammaticalframework.ui.android.LanguageSelector.OnLanguageSelectedListener; + +public class LexicalEntryActivity extends ListActivity { + + private Translator mTranslator; + private LanguageSelector mShowLanguageView; + + /** Called when the activity is first created. */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_lexical_entry); + + mTranslator = ((GFTranslator) getApplicationContext()).getTranslator(); + + mShowLanguageView = (LanguageSelector) findViewById(R.id.show_language); + mShowLanguageView.setLanguages(mTranslator.getAvailableSourceLanguages()); + mShowLanguageView.setSelectedLanguage(mTranslator.getTargetLanguage()); + mShowLanguageView.setOnLanguageSelectedListener(new OnLanguageSelectedListener() { + @Override + public void onLanguageSelected(Language language) { + mTranslator.setTargetLanguage(language); + updateTranslations(); + } + }); + + updateTranslations(); + } + + private void updateTranslations() { + @SuppressWarnings("unchecked") + List list = (List) + getIntent().getExtras().getSerializable("analyses"); + + List data = new ArrayList(); + for (MorphoAnalysis a : list) { + Expr e = Expr.readExpr(a.getLemma()); + String phrase = mTranslator.linearize(e); + + if (!data.contains(phrase)) { + data.add(phrase); + } + } + + ArrayAdapter adapter = new ArrayAdapter(this, + android.R.layout.simple_list_item_1, + data); + setListAdapter(adapter); + } +} diff --git a/src/ui/android/src/org/grammaticalframework/ui/android/MainActivity.java b/src/ui/android/src/org/grammaticalframework/ui/android/MainActivity.java index 1e5f8c06e..91823946b 100644 --- a/src/ui/android/src/org/grammaticalframework/ui/android/MainActivity.java +++ b/src/ui/android/src/org/grammaticalframework/ui/android/MainActivity.java @@ -1,7 +1,11 @@ package org.grammaticalframework.ui.android; +import java.io.Serializable; +import java.util.List; + import android.app.Activity; +import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.speech.SpeechRecognizer; @@ -12,6 +16,8 @@ import android.widget.ImageView; import org.grammaticalframework.ui.android.ASR.State; import org.grammaticalframework.ui.android.LanguageSelector.OnLanguageSelectedListener; +import org.grammaticalframework.ui.android.ConversationView.OnWordSelectedListener; +import org.grammaticalframework.pgf.MorphoAnalysis; public class MainActivity extends Activity { @@ -34,9 +40,7 @@ public class MainActivity extends Activity { private TTS mTts; - // mTranslator is static to ensure that the grammar - // is loaded only once even if the activity has been recreated. - private static Translator mTranslator; + private Translator mTranslator; @Override protected void onCreate(Bundle savedInstanceState) { @@ -48,7 +52,7 @@ public class MainActivity extends Activity { mSourceLanguageView = (LanguageSelector) findViewById(R.id.source_language); mTargetLanguageView = (LanguageSelector) findViewById(R.id.target_language); mSwitchLanguagesButton = (ImageView) findViewById(R.id.switch_languages); - + mStartStopButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -61,15 +65,22 @@ public class MainActivity extends Activity { }); mStartStopButton.setEnabled(SpeechRecognizer.isRecognitionAvailable(this)); + + mConversationView.setOnWordSelectedListener(new OnWordSelectedListener() { + @Override + public void onWordSelected(Object lexicon) { + Intent myIntent = new Intent(MainActivity.this, LexicalEntryActivity.class); + myIntent.putExtra("analyses", (Serializable) lexicon); + MainActivity.this.startActivity(myIntent); + } + }); mAsr = new ASR(this); mAsr.setListener(new SpeechInputListener()); mTts = new TTS(this); - if (mTranslator == null) { - mTranslator = new Translator(this); - } + mTranslator = ((GFTranslator) getApplicationContext()).getTranslator(); mSourceLanguageView.setLanguages(mTranslator.getAvailableSourceLanguages()); mSourceLanguageView.setSelectedLanguage(mTranslator.getSourceLanguage()); @@ -148,11 +159,15 @@ public class MainActivity extends Activity { } private void handlePartialSpeechInput(String input) { - mConversationView.updateLastUtterance(input); + mConversationView.updateLastUtterance(input, null); } private void handleSpeechInput(final String input) { - mConversationView.updateLastUtterance(input); + List list = mTranslator.lookupMorpho(input); + if (list.size() == 0) + list = null; + + mConversationView.updateLastUtterance(input, list); new AsyncTask() { @Override protected String doInBackground(Void... params) { diff --git a/src/ui/android/src/org/grammaticalframework/ui/android/Translator.java b/src/ui/android/src/org/grammaticalframework/ui/android/Translator.java index c65237fdb..50f5bb33d 100644 --- a/src/ui/android/src/org/grammaticalframework/ui/android/Translator.java +++ b/src/ui/android/src/org/grammaticalframework/ui/android/Translator.java @@ -5,6 +5,7 @@ import android.util.Log; import org.grammaticalframework.pgf.Concr; import org.grammaticalframework.pgf.Expr; +import org.grammaticalframework.pgf.MorphoAnalysis; import org.grammaticalframework.pgf.PGF; import org.grammaticalframework.pgf.ParseError; @@ -19,14 +20,13 @@ public class Translator { private static final String TAG = "Translator"; // TODO: allow changing - private String mGrammar = "ResourceDemo.pgf"; + private String mGrammar = "ParseEngAbs.pgf"; // TODO: build dynamically? private Language[] mLanguages = { - new Language("en-US", "English", "ResourceDemoEng"), - new Language("de-DE", "German", "ResourceDemoGer"), - new Language("es-ES", "Spanish", "ResourceDemoSpa"), - new Language("fr-FR", "French", "ResourceDemoFre"), + new Language("en-US", "English", "ParseEng"), + new Language("bg-BG", "Bulgarian", "ParseBul"), + new Language("cmn-Hans-CN", "Chinese", "ParseChi") }; private Language mSourceLanguage; @@ -96,6 +96,15 @@ public class Translator { } } + public String linearize(Expr e) { + Concr targetLang = getConcr(getTargetLanguage().getConcrete()); + return targetLang.linearize(e); + } + + public List lookupMorpho(String sentence) { + return getConcr(getSourceLanguage().getConcrete()).lookupMorpho(sentence); + } + private Concr getConcr(String name) { return getGrammar().getLanguages().get(name); }