From daed9b15f5ae067f0c03fc2bb942b3171aed9b4f Mon Sep 17 00:00:00 2001 From: Thad Hughes Date: Fri, 5 Nov 2010 12:26:13 -0700 Subject: [PATCH] go --- res/drawable/icon_old.png | Bin 0 -> 5368 bytes .../dictionary/DictionaryActivityOld.java.old | 739 ++++++++++++++++++ 2 files changed, 739 insertions(+) create mode 100644 res/drawable/icon_old.png create mode 100644 src/com/hughes/android/dictionary/DictionaryActivityOld.java.old diff --git a/res/drawable/icon_old.png b/res/drawable/icon_old.png new file mode 100644 index 0000000000000000000000000000000000000000..17ccb38b85ef726803b772bbc1ebd0e2d6e28c31 GIT binary patch literal 5368 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 W&auqBz#k3(0000P{ literal 0 HcmV?d00001 diff --git a/src/com/hughes/android/dictionary/DictionaryActivityOld.java.old b/src/com/hughes/android/dictionary/DictionaryActivityOld.java.old new file mode 100644 index 0000000..662ed15 --- /dev/null +++ b/src/com/hughes/android/dictionary/DictionaryActivityOld.java.old @@ -0,0 +1,739 @@ +package com.hughes.android.dictionary; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.RandomAccessFile; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; + +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.text.style.StyleSpan; +import android.util.Log; +import android.view.ContextMenu; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.View.OnClickListener; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.TableLayout; +import android.widget.TableRow; +import android.widget.TextView; +import android.widget.Toast; + +import com.hughes.android.dictionary.engine.Dictionary; +import com.hughes.android.dictionary.engine.Language; +import com.ibm.icu.text.Collator; + +public class DictionaryActivityOld extends ListActivity { + + // TO DO: + // * Easy reverse lookup. + // * 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(); + + EditText searchText; + Button langButton; + int lastSelectedRow = 0; // TODO: I'm evil. + + private boolean prefsMightHaveChanged = true; + + // Never null. + private File wordList = null; + private RandomAccessFile dictRaf = null; + private Dictionary dictionary = null; + private boolean saveOnlyFirstSubentry = false; + + // Visible for testing. + IndexAdapter indexAdapter = null; + private SearchOperation searchOperation = null; + + public DictionaryActivity() { + + searchExecutor.execute(new Runnable() { + public void run() { + final long startMillis = System.currentTimeMillis(); + for (final String lang : Arrays.asList("EN", "DE")) { + Language.lookup(lang).getFindCollator(); + final Collator c = Language.lookup(lang).getSortCollator(); + if (c.compare("pre-print", "preppy") >= 0) { + Log.e(LOG, c.getClass() + " is buggy, lookups may not work properly."); + } + } + Log.d(LOG, "Loading collators took:" + (System.currentTimeMillis() - startMillis)); + } + }); + + } + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.d(LOG, "onCreate:" + this); + + try { + initDictionaryAndPrefs(); + } catch (Exception e) { + return; + } + + // UI init. + + setContentView(R.layout.dictionary_activity); + searchText = (EditText) findViewById(R.id.SearchText); + langButton = (Button) findViewById(R.id.LangButton); + + 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) { + onClearSearchTextButton(clearSearchTextButton); + } + }); + 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) { + onLanguageButton(); + } + }); + + final Button upButton = (Button) findViewById(R.id.UpButton); + upButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + onUpButton(); + } + }); + final Button downButton = (Button) findViewById(R.id.DownButton); + downButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + onDownButton(); + } + }); + + // ContextMenu. + registerForContextMenu(getListView()); + + 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); + + 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"); + final long startMillis = System.currentTimeMillis(); + dictionary = new Dictionary(dictRaf); + Log.d(LOG, "Read dictionary millis: " + (System.currentTimeMillis() - startMillis)); + } catch (IOException e) { + Log.e(LOG, "Couldn't open dictionary.", e); + + this.startActivity(new asdfIntent(this, DictionaryEditActivity.class)); + finish(); + } + + final byte lang = prefs.getInt(PREF_DICT_ACTIVE_LANG, SimpleEntry.LANG1) == SimpleEntry.LANG1 ? SimpleEntry.LANG1 + : SimpleEntry.LANG2; + + indexAdapter = new IndexAdapter(dictionary.languageDatas[lang]); + setListAdapter(indexAdapter); + prefsMightHaveChanged = false; + } + + @Override + public void onResume() { + super.onResume(); + Log.d(LOG, "onResume:" + this); + + 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, indexAdapter.languageData.lang); + prefs.putString(PREF_ACTIVE_SEARCH_TEXT, searchText.getText().toString()); + prefs.commit(); + } + + @Override + public void onStop() { + super.onStop(); + Log.d(LOG, "onStop:" + this); + if (isFinishing()) { + Log.i(LOG, "isFinishing()==true, closing dictionary."); + closeCurrentDictionary(); + } + } + + private void closeCurrentDictionary() { + Log.i(LOG, "closeCurrentDictionary"); + if (dictionary == null) { + return; + } + waitForSearchEnd(); + indexAdapter = null; + setListAdapter(null); + Log.d(LOG, "setListAdapter finished."); + dictionary = null; + try { + if (dictRaf != null) { + dictRaf.close(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + dictRaf = null; + } + + public String getSelectedRowRawText(final boolean onlyFirstSubentry) { + final Row row = indexAdapter.languageData.rows.get(getSelectedRow()); + return indexAdapter.languageData.rowToString(row, onlyFirstSubentry); + } + + // ---------------------------------------------------------------- + // OptionsMenu + // ---------------------------------------------------------------- + + private MenuItem switchLanguageMenuItem = null; + + @Override + public boolean onCreateOptionsMenu(final Menu menu) { + 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) { + prefsMightHaveChanged = true; + startActivity(new Intent(DictionaryActivity.this, + PreferenceActivity.class)); + return false; + } + }); + + final MenuItem about = menu.add(getString(R.string.about)); + about.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(final MenuItem menuItem) { + 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 download = menu.add(getString(R.string.downloadDictionary)); + download.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(final MenuItem menuItem) { + prefsMightHaveChanged = true; + startDownloadDictActivity(DictionaryActivity.this); + return false; + } + }); + + return true; + } + + @Override + public boolean onPrepareOptionsMenu(final Menu menu) { + switchLanguageMenuItem.setTitle(getString(R.string.switchToLanguage, + dictionary.languageDatas[SimpleEntry + .otherLang(indexAdapter.languageData.lang)].language.symbol)); + return super.onPrepareOptionsMenu(menu); + } + + void updateLangButton() { + langButton.setText(indexAdapter.languageData.language.symbol); + } + + // ---------------------------------------------------------------- + // Event handlers. + // ---------------------------------------------------------------- + + void onLanguageButton() { + waitForSearchEnd(); + indexAdapter = new IndexAdapter( + dictionary.languageDatas[(indexAdapter.languageData == dictionary.languageDatas[0]) ? 1 + : 0]); + Log.d(LOG, "onLanguageButton, newLang=" + indexAdapter.languageData.language.symbol); + setListAdapter(indexAdapter); + updateLangButton(); + onSearchTextChange(searchText.getText().toString()); + } + + void onUpButton() { + final int destRowIndex = indexAdapter.languageData.getPrevTokenRow(getSelectedRow()); + Log.d(LOG, "onUpButton, destRowIndex=" + destRowIndex); + jumpToRow(indexAdapter, destRowIndex); + } + + void onDownButton() { + final int destRowIndex = indexAdapter.languageData.getNextTokenRow(getSelectedRow()); + Log.d(LOG, "onDownButton, destRowIndex=" + destRowIndex); + jumpToRow(indexAdapter, destRowIndex); + } + + void onAppendToWordList() { + final int row = getSelectedRow(); + if (row < 0) { + return; + } + final StringBuilder rawText = new StringBuilder(); + final String word = indexAdapter.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) { + if (!searchText.hasFocus()) { + searchText.setText("" + (char) event.getUnicodeChar()); + onSearchTextChange(searchText.getText().toString()); + searchText.requestFocus(); + } + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + protected void onListItemClick(ListView l, View v, int row, long id) { + setSelectedRow(row); + openContextMenu(getListView()); + } + + void onSearchTextChange(final String searchText) { + Log.d(LOG, "onSearchTextChange: " + searchText); + synchronized (this) { + searchOperation = new SearchOperation(indexAdapter, searchText.trim(), searchOperation); + searchExecutor.execute(searchOperation); + } + } + + private void onClearSearchTextButton(final Button clearSearchTextButton) { + clearSearchTextButton.requestFocus(); + searchText.setText(""); + searchText.requestFocus(); + Log.d(LOG, "Trying to show soft keyboard."); + final InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + manager.showSoftInput(searchText, InputMethodManager.SHOW_IMPLICIT); + } + + // ---------------------------------------------------------------- + // 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 IndexAdapter dictionaryListAdapter, + final int rowIndex) { + Log.d(LOG, "jumpToRow: " + rowIndex); + if (dictionaryListAdapter != this.indexAdapter) { + Log.w(LOG, "skipping jumpToRow for old list adapter: " + rowIndex); + return; + } + setSelection(rowIndex); + setSelectedRow(rowIndex); + getListView().setSelected(true); + } + + // 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() { + Log.d(LOG, "updateSearchText"); + final int selectedRowIndex = getSelectedRow(); + if (!searchText.hasFocus()) { + if (selectedRowIndex >= 0) { + final String word = indexAdapter.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."); + } + } + } + + 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); + } + + class IndexAdapter extends BaseAdapter { + + // Visible for testing. + final LanguageData languageData; + + IndexAdapter(final LanguageData languageData) { + this.languageData = languageData; + } + + public int getCount() { + return languageData.rows.size(); + } + + public Dictionary.Row getItem(int rowIndex) { + assert rowIndex < languageData.rows.size(); + return languageData.rows.get(rowIndex); + } + + public long getItemId(int rowIndex) { + return 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; + if (convertView instanceof TextView) { + result = (TextView) convertView; + } else { + result = new TextView(parent.getContext()); + } + if (row == null) { + return result; + } + result.setText(languageData.rowToString(row, false)); + result.setTextAppearance(parent.getContext(), + android.R.style.TextAppearance_Large); + result.setClickable(false); + return result; + } + + // Entry row(s). + final TableLayout result = new TableLayout(parent.getContext()); + + final SimpleEntry entry = new SimpleEntry(null, null);//.entries.get(row.getIndex()); + 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) { + final TextView spacer = new TextView(tableRow.getContext()); + spacer.setText(r == 0 ? "� " : " � "); + tableRow.addView(spacer); + } + tableRow.addView(column1, layoutParams); + if (r > 0) { + final TextView spacer = new TextView(tableRow.getContext()); + spacer.setText(r == 0 ? "� " : " � "); + tableRow.addView(spacer); + } + tableRow.addView(column2, layoutParams); + + column1.setWidth(1); + column2.setWidth(1); + // column1.setTextAppearance(parent.getContext(), android.R.style.Text); + + // 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 = 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(); + } + + column2.setText( + entry.getAllText(SimpleEntry.otherLang(languageData.lang))[r], + TextView.BufferType.NORMAL); + + result.addView(tableRow); + } + + return result; + } + + } // DictionaryListAdapter + + private final class SearchOperation implements Runnable { + SearchOperation previousSearchOperation; + + final IndexAdapter listAdapter; + final LanguageData languageData; + final String searchText; + final AtomicBoolean interrupted = new AtomicBoolean(false); + boolean searchFinished = false; + + SearchOperation(final IndexAdapter 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) { + Log.d(LOG, "waitForSearchEnd"); + 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()); + } + } + + public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, + int arg3) { + } + + public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { + } + } + +} \ No newline at end of file -- 2.43.0