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 000000000..985644ebd Binary files /dev/null and b/src/ui/android/res/drawable-xhdpi/ic_dictionary.png differ 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); }