package com.hughes.android.dictionary;
import java.io.File;
-import java.io.FileOutputStream;
+import java.io.FileWriter;
import java.io.IOException;
-import java.io.OutputStream;
+import java.io.PrintWriter;
import java.io.RandomAccessFile;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
-import android.app.AlertDialog;
import android.app.ListActivity;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
+import android.text.ClipboardManager;
import android.text.Editable;
import android.text.Spannable;
import android.text.TextWatcher;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
-import android.widget.AdapterView.OnItemLongClickListener;
-import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.Toast;
import com.hughes.android.dictionary.Dictionary.IndexEntry;
import com.hughes.android.dictionary.Dictionary.LanguageData;
public class DictionaryActivity extends ListActivity {
- static final Intent aboutIntent = new Intent().setClassName(AboutActivity.class.getPackage().getName(), AboutActivity.class.getCanonicalName());
- static final Intent preferencesIntent = new Intent().setClassName(PreferenceActivity.class.getPackage().getName(), PreferenceActivity.class.getCanonicalName());
-
- private final Handler uiHandler = new Handler();
+ // TODO:
+ // * Download latest dicts.
+ // * http://ftp.tu-chemnitz.de/pub/Local/urz/ding/de-en-devel/
+ // * http://www1.dict.cc/translation_file_request.php?l=e
+ // * Compress all the strings everywhere, put compression table in file.
+ // Done:
+ // * Only one way to way for current search to end. (won't do).
+
+ static final String LOG = "QuickDic";
+ static final String PREF_DICT_ACTIVE_LANG = "DICT_DIR_PREF";
+ static final String PREF_ACTIVE_SEARCH_TEXT = "ACTIVE_WORD_PREF";
+
+ // package for test.
+ final Handler uiHandler = new Handler();
private final Executor searchExecutor = Executors.newSingleThreadExecutor();
- private final DictionaryListAdapter dictionaryListAdapter = new DictionaryListAdapter();
- // Never null.
- private File wordList = new File("/sdcard/wordList.txt");
+ EditText searchText;
+ Button langButton;
+ int lastSelectedRow = 0; // TODO: I'm evil.
- // Can be null.
- private File dictFile = null;
+ private boolean prefsMightHaveChanged = true;
+
+ // Never null.
+ private File wordList;
private RandomAccessFile dictRaf = null;
private Dictionary dictionary = null;
- private LanguageData activeLangaugeData = null;
+ private boolean saveOnlyFirstSubentry = false;
+ // Visible for testing.
+ LanguageListAdapter languageList = null;
private SearchOperation searchOperation = null;
- private int selectedRowIndex = -1;
- private int selectedTokenRowIndex = -1;
-
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
- Log.d("THAD", "onCreate");
super.onCreate(savedInstanceState);
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- closeCurrentDictionary();
+ Log.d(LOG, "onCreate:" + this);
- final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
- wordList = new File(settings.getString(getResources().getString(R.string.wordListFile), wordList.getAbsolutePath()));
- dictFile = new File(settings.getString(getResources().getString(R.string.dictFile), "/sdcard/de-en.dict"));
- Log.d("THAD", "wordList=" + wordList);
- Log.d("THAD", "dictFile=" + dictFile);
-
- if (!dictFile.canRead()) {
- return;
+ if (Language.EN.sortCollator.compare("pre-print", "preppy") >= 0) {
+ Log
+ .e(LOG,
+ Language.EN.sortCollator.getClass() + " is buggy, lookups may not work properly.");
}
-
+
try {
- dictRaf = new RandomAccessFile(dictFile, "r");
- dictionary = new Dictionary(dictRaf);
- activeLangaugeData = dictionary.languageDatas[Entry.LANG1];
+ initDictionaryAndPrefs();
} catch (Exception e) {
- throw new RuntimeException(e);
+ return;
}
- setContentView(R.layout.main);
-
- getSearchText().addTextChangedListener(new DictionaryTextWatcher());
-
- setListAdapter(dictionaryListAdapter);
+ // UI init.
- // Language button.
+ setContentView(R.layout.main);
+ searchText = (EditText) findViewById(R.id.SearchText);
+ langButton = (Button) findViewById(R.id.LangButton);
+
+ Log.d(LOG, "adding text changed listener");
+ searchText.addTextChangedListener(new SearchTextWatcher());
+
+ getListView().setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> arg0, View arg1, int row,
+ long arg3) {
+ setSelectedRow(row);
+ }
+ public void onNothingSelected(AdapterView<?> arg0) {
+ }
+ });
+
+ getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
+ public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int row,
+ long arg3) {
+ setSelectedRow(row);
+ return false;
+ }
+ });
+
+ final Button clearSearchTextButton = (Button) findViewById(R.id.ClearSearchTextButton);
+ clearSearchTextButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ clearSearchTextButton.requestFocus();
+ searchText.setText("");
+ searchText.requestFocus();
+ }
+ });
+ clearSearchTextButton.setVisibility(PreferenceManager.getDefaultSharedPreferences(this).getBoolean(
+ getString(R.string.showClearSearchTextButtonKey), true) ? View.VISIBLE
+ : View.GONE);
+
final Button langButton = (Button) findViewById(R.id.LangButton);
langButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
- switchLanguage();
- }});
- updateLangButton();
-
+ onLanguageButton();
+ }
+ });
+
final Button upButton = (Button) findViewById(R.id.UpButton);
upButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
- final int destRowIndex;
- final Row tokenRow = activeLangaugeData.rows.get(selectedTokenRowIndex);
- assert tokenRow.isToken();
- final int prevTokenIndex = tokenRow.getIndex() - 1;
- if (selectedRowIndex == selectedTokenRowIndex && selectedRowIndex > 0) {
- destRowIndex = activeLangaugeData.sortedIndex.get(prevTokenIndex).startRow;
- } else {
- destRowIndex = selectedTokenRowIndex;
- }
- jumpToRow(destRowIndex);
- }});
+ onUpButton();
+ }
+ });
final Button downButton = (Button) findViewById(R.id.DownButton);
downButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
- final Row tokenRow = activeLangaugeData.rows.get(selectedTokenRowIndex);
- assert tokenRow.isToken();
- final int nextTokenIndex = tokenRow.getIndex() + 1;
- final int destRowIndex;
- if (nextTokenIndex < activeLangaugeData.sortedIndex.size()) {
- destRowIndex = activeLangaugeData.sortedIndex.get(nextTokenIndex).startRow;
- } else {
- destRowIndex = activeLangaugeData.rows.size() - 1;
- }
- jumpToRow(destRowIndex);
- }});
+ onDownButton();
+ }
+ });
// ContextMenu.
registerForContextMenu(getListView());
- // ItemSelectedListener.
- getListView().setOnItemSelectedListener(new OnItemSelectedListener() {
- public void onItemSelected(AdapterView<?> arg0, View arg1, int rowIndex,
- long arg3) {
- Log.d("THAD", "onItemSelected: " + rowIndex);
- selectedRowIndex = rowIndex;
- selectedTokenRowIndex = activeLangaugeData.getIndexEntryForRow(rowIndex).startRow;
- updateSearchText();
- }
+ updateLangButton();
+ }
+
+ private void initDictionaryAndPrefs() throws Exception {
+ if (!prefsMightHaveChanged) {
+ return;
+ }
+ closeCurrentDictionary();
+
+ final SharedPreferences prefs = PreferenceManager
+ .getDefaultSharedPreferences(this);
+ wordList = new File(prefs.getString(getString(R.string.wordListFileKey),
+ getString(R.string.wordListFileDefault)));
+ Log.d(LOG, "wordList=" + wordList);
+
+ saveOnlyFirstSubentry = prefs.getBoolean(getString(R.string.saveOnlyFirstSubentryKey), false);
- public void onNothingSelected(AdapterView<?> arg0) {
- }});
+ final File dictFile = new File(prefs.getString(getString(R.string.dictFileKey),
+ getString(R.string.dictFileDefault)));
+ Log.d(LOG, "dictFile=" + dictFile);
+
+ try {
+ if (!dictFile.canRead()) {
+ throw new IOException("Unable to read dictionary file.");
+ }
+
+ dictRaf = new RandomAccessFile(dictFile, "r");
+ dictionary = new Dictionary(dictRaf);
+ } catch (IOException e) {
+ Log.e(LOG, "Couldn't open dictionary.", e);
+ this.startActivity(new Intent(this, NoDictionaryActivity.class));
+ finish();
+ throw new Exception(e);
+ }
+
+ final byte lang = prefs.getInt(PREF_DICT_ACTIVE_LANG, Entry.LANG1) == Entry.LANG1 ? Entry.LANG1
+ : Entry.LANG2;
+ languageList = new LanguageListAdapter(dictionary.languageDatas[lang]);
+ setListAdapter(languageList);
+ prefsMightHaveChanged = false;
+ }
- // LongClickListener.
- getListView().setOnItemLongClickListener((new OnItemLongClickListener() {
- public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int rowIndex,
- long arg3) {
- selectedRowIndex = rowIndex;
- return false;
- }
- }));
+ @Override
+ public void onResume() {
+ super.onResume();
+ Log.d(LOG, "onResume:" + this);
- onSearchTextChange("");
+ try {
+ initDictionaryAndPrefs();
+ } catch (Exception e) {
+ return;
+ }
+
+ final SharedPreferences prefs = PreferenceManager
+ .getDefaultSharedPreferences(this);
+ final String searchTextString = prefs
+ .getString(PREF_ACTIVE_SEARCH_TEXT, "");
+ searchText.setText(searchTextString);
+ getListView().requestFocus();
+ onSearchTextChange(searchTextString);
}
-
-
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ Log.d(LOG, "onPause:" + this);
+ final Editor prefs = PreferenceManager.getDefaultSharedPreferences(this)
+ .edit();
+ prefs.putInt(PREF_DICT_ACTIVE_LANG, languageList.languageData.lang);
+ prefs.putString(PREF_ACTIVE_SEARCH_TEXT, searchText.getText().toString());
+ prefs.commit();
+ }
+
@Override
public void onStop() {
super.onStop();
- closeCurrentDictionary();
+ Log.d(LOG, "onStop:" + this);
+ if (isFinishing()) {
+ Log.i(LOG, "isFinishing()==true, closing dictionary.");
+ closeCurrentDictionary();
+ }
}
private void closeCurrentDictionary() {
+ Log.i(LOG, "closeCurrentDictionary");
+ waitForSearchEnd();
+ languageList = null;
+ setListAdapter(null);
dictionary = null;
- activeLangaugeData = null;
try {
if (dictRaf != null) {
dictRaf.close();
}
dictRaf = null;
}
-
- public String getSelectedRowText() {
- return activeLangaugeData.rowToString(activeLangaugeData.rows.get(selectedRowIndex));
- }
-
- public EditText getSearchText() {
- return (EditText) findViewById(R.id.SearchText);
+
+ public String getSelectedRowRawText(final boolean onlyFirstSubentry) {
+ final Row row = languageList.languageData.rows.get(getSelectedRow());
+ return languageList.languageData.rowToString(row, onlyFirstSubentry);
}
-
+
// ----------------------------------------------------------------
// OptionsMenu
// ----------------------------------------------------------------
private MenuItem switchLanguageMenuItem = null;
-
+
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
- switchLanguageMenuItem = menu.add("Switch to language.");
- switchLanguageMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener(){
+ switchLanguageMenuItem = menu.add(getString(R.string.switchToLanguage));
+ switchLanguageMenuItem
+ .setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ public boolean onMenuItemClick(final MenuItem menuItem) {
+ onLanguageButton();
+ return false;
+ }
+ });
+
+ final MenuItem preferences = menu.add(getString(R.string.preferences));
+ preferences.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(final MenuItem menuItem) {
- switchLanguage();
+ prefsMightHaveChanged = true;
+ startActivity(new Intent(DictionaryActivity.this,
+ PreferenceActivity.class));
return false;
- }});
+ }
+ });
- final MenuItem preferences = menu.add("Preferences...");
- preferences.setOnMenuItemClickListener(new OnMenuItemClickListener(){
+ final MenuItem about = menu.add(getString(R.string.about));
+ about.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(final MenuItem menuItem) {
- startActivity(preferencesIntent);
+ final Intent intent = new Intent().setClassName(AboutActivity.class
+ .getPackage().getName(), AboutActivity.class.getCanonicalName());
+ final String currentDictInfo;
+ if (dictionary == null) {
+ currentDictInfo = getString(R.string.noDictLoaded);
+ } else {
+ final LanguageData lang0 = dictionary.languageDatas[0];
+ final LanguageData lang1 = dictionary.languageDatas[1];
+ currentDictInfo = getString(R.string.aboutText, dictionary.dictionaryInfo, dictionary.entries.size(),
+ lang0.language.symbol, lang0.sortedIndex.size(), lang0.rows.size(),
+ lang1.language.symbol, lang1.sortedIndex.size(), lang1.rows.size());
+ }
+ intent.putExtra(AboutActivity.CURRENT_DICT_INFO, currentDictInfo
+ .toString());
+ startActivity(intent);
return false;
- }});
+ }
+ });
- final MenuItem about = menu.add("About...");
- about.setOnMenuItemClickListener(new OnMenuItemClickListener(){
+ final MenuItem download = menu.add(getString(R.string.downloadDictionary));
+ download.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(final MenuItem menuItem) {
- startActivity(aboutIntent);
+ prefsMightHaveChanged = true;
+ startDownloadDictActivity(DictionaryActivity.this);
return false;
- }});
+ }
+ });
return true;
}
-
+
@Override
public boolean onPrepareOptionsMenu(final Menu menu) {
- if (dictionary != null) {
- switchLanguageMenuItem.setTitle(String.format("Switch to %s", dictionary.languageDatas[Entry.otherLang(activeLangaugeData.lang)].language.symbol));
- }
- switchLanguageMenuItem.setEnabled(dictionary != null);
+ switchLanguageMenuItem.setTitle(getString(R.string.switchToLanguage,
+ dictionary.languageDatas[Entry
+ .otherLang(languageList.languageData.lang)].language.symbol));
return super.onPrepareOptionsMenu(menu);
}
-
- void switchLanguage() {
- activeLangaugeData = dictionary.languageDatas[(activeLangaugeData == dictionary.languageDatas[0]) ? 1 : 0];
- selectedRowIndex = 0;
- selectedTokenRowIndex = 0;
- updateLangButton();
- dictionaryListAdapter.notifyDataSetChanged();
- onSearchTextChange(getSearchText().getText().toString());
- }
void updateLangButton() {
- final Button langButton = (Button) findViewById(R.id.LangButton);
- langButton.setText(activeLangaugeData.language.symbol);
+ langButton.setText(languageList.languageData.language.symbol);
}
-
+
// ----------------------------------------------------------------
- // ContextMenu
+ // Event handlers.
// ----------------------------------------------------------------
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
- if (selectedRowIndex == -1) {
+ void onLanguageButton() {
+ waitForSearchEnd();
+ languageList = new LanguageListAdapter(
+ dictionary.languageDatas[(languageList.languageData == dictionary.languageDatas[0]) ? 1
+ : 0]);
+ Log.d(LOG, "onLanguageButton, newLang=" + languageList.languageData.language.symbol);
+ setListAdapter(languageList);
+ updateLangButton();
+ onSearchTextChange(searchText.getText().toString());
+ }
+
+ void onUpButton() {
+ final int destRowIndex = languageList.languageData.getPrevTokenRow(getSelectedRow());
+ Log.d(LOG, "onUpButton, destRowIndex=" + destRowIndex);
+ jumpToRow(languageList, destRowIndex);
+ }
+
+ void onDownButton() {
+ final int destRowIndex = languageList.languageData.getNextTokenRow(getSelectedRow());
+ Log.d(LOG, "onDownButton, destRowIndex=" + destRowIndex);
+ jumpToRow(languageList, destRowIndex);
+ }
+
+ void onAppendToWordList() {
+ final int row = getSelectedRow();
+ if (row < 0) {
return;
}
- final MenuItem addToWordlist = menu.add("Add to wordlist: " + wordList.getName());
- addToWordlist.setOnMenuItemClickListener(new OnMenuItemClickListener() {
- public boolean onMenuItemClick(MenuItem item) {
- final String rawText = getSelectedRowText();
- Log.d("THAD", "Writing : " + rawText);
- try {
- final OutputStream out = new FileOutputStream(wordList, true);
- out.write((rawText + "\n").getBytes());
- out.close();
- } catch (IOException e) {
- final AlertDialog alert = new AlertDialog.Builder(DictionaryActivity.this).create();
- alert.setMessage("Failed to append to file: " + wordList.getAbsolutePath());
- alert.show();
- }
- return false;
- }
- });
+ final StringBuilder rawText = new StringBuilder();
+ final String word = languageList.languageData.getIndexEntryForRow(row).word;
+ rawText.append(
+ new SimpleDateFormat("yyyy.MM.dd HH:mm:ss").format(new Date()))
+ .append("\t");
+ rawText.append(word).append("\t");
+ rawText.append(getSelectedRowRawText(saveOnlyFirstSubentry));
+ Log.d(LOG, "Writing : " + rawText);
+ try {
+ wordList.getParentFile().mkdirs();
+ final PrintWriter out = new PrintWriter(
+ new FileWriter(wordList, true));
+ out.println(rawText.toString());
+ out.close();
+ } catch (IOException e) {
+ Log.e(LOG, "Unable to append to " + wordList.getAbsolutePath(), e);
+ Toast.makeText(this, getString(R.string.failedAddingToWordList, wordList.getAbsolutePath()), Toast.LENGTH_LONG);
+ }
+ return;
}
-
+
+ void onCopy() {
+ final int row = getSelectedRow();
+ if (row < 0) {
+ return;
+ }
+ Log.d(LOG, "Copy." + DictionaryActivity.this.getSelectedRow());
+ final StringBuilder result = new StringBuilder();
+ result.append(getSelectedRowRawText(false));
+ final ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+ clipboardManager.setText(result.toString());
+ Log.d(LOG, "Copied: " + result);
+ }
+
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getUnicodeChar() != 0) {
- final EditText searchText = getSearchText();
if (!searchText.hasFocus()) {
- searchText.setText("" + (char)event.getUnicodeChar());
+ searchText.setText("" + (char) event.getUnicodeChar());
onSearchTextChange(searchText.getText().toString());
searchText.requestFocus();
}
@Override
protected void onListItemClick(ListView l, View v, int row, long id) {
- selectedRowIndex = row;
- Log.d("THAD", "Clicked: " + getSelectedRowText());
+ setSelectedRow(row);
openContextMenu(getListView());
}
void onSearchTextChange(final String searchText) {
- Log.d("THAD", "onSearchTextChange: " + searchText);
- if (searchOperation != null) {
- searchOperation.interrupted.set(true);
+ Log.d(LOG, "onSearchTextChange: " + searchText);
+ synchronized (this) {
+ searchOperation = new SearchOperation(languageList, searchText, searchOperation);
+ searchExecutor.execute(searchOperation);
+ }
+ }
+
+
+
+ // ----------------------------------------------------------------
+ // ContextMenu
+ // ----------------------------------------------------------------
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v,
+ ContextMenuInfo menuInfo) {
+ final int row = getSelectedRow();
+ if (row < 0) {
+ return;
+ }
+
+ final MenuItem addToWordlist = menu.add(getString(R.string.addToWordList, wordList.getName()));
+ addToWordlist.setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ onAppendToWordList();
+ return false;
+ }
+ });
+
+ final MenuItem copy = menu.add(android.R.string.copy);
+ copy.setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ onCopy();
+ return false;
+ }
+ });
+
+ }
+
+ private void jumpToRow(final LanguageListAdapter dictionaryListAdapter,
+ final int rowIndex) {
+ Log.d(LOG, "jumpToRow: " + rowIndex);
+ if (dictionaryListAdapter != this.languageList) {
+ Log.w(LOG, "skipping jumpToRow for old list adapter: " + rowIndex);
+ return;
}
- searchOperation = new SearchOperation(searchText);
- searchExecutor.execute(searchOperation);
+ setSelection(rowIndex);
+ setSelectedRow(rowIndex);
+ getListView().setSelected(true);
}
- private void jumpToRow(final int rowIndex) {
- Log.d("THAD", "jumpToRow: " + rowIndex);
- selectedRowIndex = rowIndex;
- selectedTokenRowIndex = activeLangaugeData.getIndexEntryForRow(rowIndex).startRow;
- getListView().setSelection(rowIndex);
- getListView().setSelected(true); // TODO: is this doing anything?
+ // TODO: delete me somehow.
+ private int getSelectedRow() {
+ return lastSelectedRow;
+ }
+ private void setSelectedRow(final int row) {
+ lastSelectedRow = row;
+ Log.d(LOG, "Selected: " + getSelectedRowRawText(true));
updateSearchText();
}
private void updateSearchText() {
- final EditText searchText = getSearchText();
+ Log.d(LOG, "updateSearchText");
+ final int selectedRowIndex = getSelectedRow();
if (!searchText.hasFocus()) {
- // TODO: Not so nice:
- final String word = activeLangaugeData.getIndexEntryForRow(selectedRowIndex).word;
- if (!word.equals(searchText.getText().toString())) {
- Log.d("THAD", "updateSearchText: setText: " + word);
- searchText.setText(word);
+ if (selectedRowIndex >= 0) {
+ final String word = languageList.languageData
+ .getIndexEntryForRow(selectedRowIndex).word;
+ if (!word.equals(searchText.getText().toString())) {
+ Log.d(LOG, "updateSearchText: setText: " + word);
+ searchText.setText(word);
+ }
+ } else {
+ Log.w(LOG, "updateSearchText: nothing selected.");
}
}
}
- private final class SearchOperation implements Runnable {
- final String searchText;
- final AtomicBoolean interrupted = new AtomicBoolean(false);
+ static void startDownloadDictActivity(final Context context) {
+ final Intent intent = new Intent(context, DownloadActivity.class);
+ final SharedPreferences prefs = PreferenceManager
+ .getDefaultSharedPreferences(context);
+ final String dictFetchUrl = prefs.getString(context
+ .getString(R.string.dictFetchUrlKey), context
+ .getString(R.string.dictFetchUrlDefault));
+ final String dictFileName = prefs.getString(context
+ .getString(R.string.dictFileKey), context
+ .getString(R.string.dictFileDefault));
+ intent.putExtra(DownloadActivity.SOURCE, dictFetchUrl);
+ intent.putExtra(DownloadActivity.DEST, dictFileName);
+ context.startActivity(intent);
+ }
- public SearchOperation(final String searchText) {
- this.searchText = searchText;
- }
+ class LanguageListAdapter extends BaseAdapter {
- public void run() {
- Log.d("THAD", "SearchOperation: " + searchText);
- final int indexLocation = activeLangaugeData.lookup(searchText, interrupted);
- if (interrupted.get()) {
- return;
- }
- final IndexEntry indexEntry = activeLangaugeData.sortedIndex
- .get(indexLocation);
- uiHandler.post(new Runnable() {
- public void run() {
- jumpToRow(indexEntry.startRow);
- }
- });
- }
- }
+ // Visible for testing.
+ final LanguageData languageData;
- private class DictionaryListAdapter extends BaseAdapter {
+ LanguageListAdapter(final LanguageData languageData) {
+ this.languageData = languageData;
+ }
public int getCount() {
- return dictionary != null ? activeLangaugeData.rows.size() : 0;
+ return languageData.rows.size();
}
public Dictionary.Row getItem(int rowIndex) {
- assert rowIndex < activeLangaugeData.rows.size();
- return activeLangaugeData.rows.get(rowIndex);
+ assert rowIndex < languageData.rows.size();
+ return languageData.rows.get(rowIndex);
}
public long getItemId(int rowIndex) {
public View getView(final int rowIndex, final View convertView,
final ViewGroup parent) {
final Row row = getItem(rowIndex);
-
+
// Token row.
if (row.isToken()) {
TextView result = null;
} else {
result = new TextView(parent.getContext());
}
- result.setText(activeLangaugeData.rowToString(row));
+ if (row == null) {
+ return result;
+ }
+ result.setText(languageData.rowToString(row, false));
result.setTextAppearance(parent.getContext(),
android.R.style.TextAppearance_Large);
result.setClickable(false);
final int rowCount = entry.getRowCount();
for (int r = 0; r < rowCount; ++r) {
final TableRow tableRow = new TableRow(result.getContext());
-
+
TextView column1 = new TextView(tableRow.getContext());
TextView column2 = new TextView(tableRow.getContext());
final TableRow.LayoutParams layoutParams = new TableRow.LayoutParams();
layoutParams.weight = 0.5f;
-
- if (r>0){
+
+ if (r > 0) {
final TextView spacer = new TextView(tableRow.getContext());
spacer.setText(r == 0 ? "\95 " : " \95 ");
tableRow.addView(spacer);
}
tableRow.addView(column1, layoutParams);
- if (r>0){
+ if (r > 0) {
final TextView spacer = new TextView(tableRow.getContext());
spacer.setText(r == 0 ? "\95 " : " \95 ");
tableRow.addView(spacer);
}
tableRow.addView(column2, layoutParams);
-
+
column1.setWidth(1);
column2.setWidth(1);
// column1.setTextAppearance(parent.getContext(), android.R.style.Text);
-
- // TODO: highlight query word in entries.
- final String col1Text = entry.getAllText(activeLangaugeData.lang)[r];
+
+ // TODO: color words by gender
+ final String col1Text = entry.getAllText(languageData.lang)[r];
column1.setText(col1Text, TextView.BufferType.SPANNABLE);
final Spannable col1Spannable = (Spannable) column1.getText();
int startPos = 0;
- final String token = activeLangaugeData.getIndexEntryForRow(rowIndex).word;
+ final String token = languageData.getIndexEntryForRow(rowIndex).word;
while ((startPos = col1Text.indexOf(token, startPos)) != -1) {
- col1Spannable.setSpan(new StyleSpan(Typeface.BOLD), startPos, startPos + token.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
- startPos += token.length();
+ col1Spannable.setSpan(new StyleSpan(Typeface.BOLD), startPos,
+ startPos + token.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
+ startPos += token.length();
}
-
- column2.setText(entry.getAllText(Entry.otherLang(activeLangaugeData.lang))[r], TextView.BufferType.NORMAL);
-
+
+ column2.setText(
+ entry.getAllText(Entry.otherLang(languageData.lang))[r],
+ TextView.BufferType.NORMAL);
+
result.addView(tableRow);
}
-
+
return result;
}
- } // DictionaryListAdapter
- private class DictionaryTextWatcher implements TextWatcher {
- public void afterTextChanged(Editable searchText) {
- if (getSearchText().hasFocus()) {
- onSearchTextChange(searchText.toString());
+ } // DictionaryListAdapter
+
+ private final class SearchOperation implements Runnable {
+ SearchOperation previousSearchOperation;
+
+ final LanguageListAdapter listAdapter;
+ final LanguageData languageData;
+ final String searchText;
+ final AtomicBoolean interrupted = new AtomicBoolean(false);
+ boolean searchFinished = false;
+
+ SearchOperation(final LanguageListAdapter listAdapter,
+ final String searchText, final SearchOperation previousSearchOperation) {
+ this.listAdapter = listAdapter;
+ this.languageData = listAdapter.languageData;
+ this.searchText = searchText;
+ this.previousSearchOperation = previousSearchOperation;
+ }
+
+ public void run() {
+ if (previousSearchOperation != null) {
+ previousSearchOperation.stopAndWait();
+ }
+ previousSearchOperation = null;
+
+ Log.d(LOG, "SearchOperation: " + searchText);
+ final int indexLocation = languageData.lookup(searchText, interrupted);
+ if (!interrupted.get()) {
+ final IndexEntry indexEntry = languageData.sortedIndex.get(indexLocation);
+
+ Log.d(LOG, "SearchOperation completed: " + indexEntry.toString());
+ uiHandler.post(new Runnable() {
+ public void run() {
+ // Check is just a performance operation.
+ if (!interrupted.get()) {
+ // This is safe, because it checks that the listAdapter hasn't changed.
+ jumpToRow(listAdapter, indexEntry.startRow);
+ }
+ synchronized (DictionaryActivity.this) {
+ searchOperation = null;
+ DictionaryActivity.this.notifyAll();
+ }
+ }
+ });
+ }
+ synchronized (this) {
+ searchFinished = true;
+ this.notifyAll();
+ }
+ }
+
+ private void stopAndWait() {
+ interrupted.set(true);
+ synchronized (this) {
+ while (!searchFinished) {
+ Log.d(LOG, "stopAndWait: " + searchText);
+ try {
+ this.wait();
+ } catch (InterruptedException e) {
+ Log.e(LOG, "Interrupted", e);
+ }
+ }
+ }
+ }
+ } // SearchOperation
+
+ void waitForSearchEnd() {
+ synchronized (this) {
+ while (searchOperation != null) {
+ try {
+ this.wait();
+ } catch (InterruptedException e) {
+ Log.e(LOG, "Interrupted.", e);
+ }
+ }
+ }
+ }
+
+ private class SearchTextWatcher implements TextWatcher {
+ public void afterTextChanged(final Editable searchTextEditable) {
+ Log.d(LOG, "Search text changed: " + searchText.getText().toString());
+ if (searchText.hasFocus()) {
+ // If they were typing to cause the change, update the UI.
+ onSearchTextChange(searchText.getText().toString());
}
}