]> gitweb.fperrin.net Git - Dictionary.git/commitdiff
go
authorThad Hughes <thad.hughes@gmail.com>
Fri, 5 Nov 2010 19:25:08 +0000 (12:25 -0700)
committerThad Hughes <thad.hughes@gmail.com>
Fri, 5 Nov 2010 19:25:08 +0000 (12:25 -0700)
18 files changed:
americanFlag.jpg [deleted file]
flags.xcf [deleted file]
germanFlag.jpg [deleted file]
res/drawable/icon.png
res/layout/about_activity.xml
res/layout/edit_activity.xml
res/values/strings.xml
src/com/hughes/android/dictionary/C.java
src/com/hughes/android/dictionary/DictionaryActivity.java
src/com/hughes/android/dictionary/DictionaryConfig.java
src/com/hughes/android/dictionary/DictionaryEditActivity.java
src/com/hughes/android/dictionary/DictionaryListActivity.java
src/com/hughes/android/dictionary/engine/Dictionary.java
src/com/hughes/android/dictionary/engine/Index.java
src/com/hughes/android/dictionary/engine/PairEntry.java
src/com/hughes/android/dictionary/engine/RowBase.java
src/com/hughes/android/dictionary/engine/TextEntry.java
src/com/hughes/android/dictionary/engine/TokenRow.java

diff --git a/americanFlag.jpg b/americanFlag.jpg
deleted file mode 100755 (executable)
index 8d85b25..0000000
Binary files a/americanFlag.jpg and /dev/null differ
diff --git a/flags.xcf b/flags.xcf
deleted file mode 100755 (executable)
index b322c28..0000000
Binary files a/flags.xcf and /dev/null differ
diff --git a/germanFlag.jpg b/germanFlag.jpg
deleted file mode 100755 (executable)
index b796c87..0000000
Binary files a/germanFlag.jpg and /dev/null differ
index 17ccb38b85ef726803b772bbc1ebd0e2d6e28c31..99ae67fb4184fb3ddc360e666822add617675cbc 100644 (file)
Binary files a/res/drawable/icon.png and b/res/drawable/icon.png differ
index bf7759cf7104649a316a5b9f4360e6e5b37b7e1e..47b8d62c66cfd2c29aa686f2386d01734e78f4da 100755 (executable)
                android:clickable="true" 
                android:layout_gravity="left"
                android:paddingBottom="10dip"/>
+  
+    <TextView 
+    android:id="@+id/webPage"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content" 
+    android:text="@string/webPage"/>
+
+  <TextView 
+    android:id="@+id/webPageUrl" 
+    android:text="@string/webPageUrl"
+    android:autoLink="web"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content" 
+    android:clickable="true" 
+    android:layout_gravity="left"
+    android:paddingBottom="10dip"/>
+  
 
 </LinearLayout>
 
index d2d6e0683d69c91e9f4fc370f398874652969e7a..8c4282401699973df6913db0499931e3a5b80175 100755 (executable)
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" />
 
-  <!-- Local file. --> 
-  <TextView 
-    android:id="@+id/wordListFileTitle" 
-    android:text="@string/wordListFile"
-    android:layout_width="wrap_content" 
-    android:layout_height="wrap_content"
-    android:paddingTop="5dip" />
-  <EditText 
-    android:id="@+id/wordListFile" 
-    android:layout_width="fill_parent" 
-    android:layout_height="wrap_content" />
-
   <!-- Download URL. --> 
   <TextView 
     android:id="@+id/downloadUrlTitle" 
index ea95fb865b998c4ea098509a513797d942baafb6..4f69aab5253e0b7910d0fa7122d07de47735b613 100644 (file)
@@ -5,6 +5,7 @@
        <string name="about_text">QuickDic\nby Thad Hughes</string>
  
   <!-- DictionaryListActivity -->
+  <string name="dictionaryList">Dictionary list</string>
   <string name="selectADictionary"><![CDATA[Select a dictionary.
 \nLong-press to edit the dictionary. Press "menu" to add a new dictionary.]]></string>
   <string name="addDictionary">Add dictionary</string>
   <string name="deleteDictionary">Delete dictionary</string>
   <string name="moveUp">Move up</string>
   <string name="newDictionary">New Dictionary</string>
+
+  <string name="thanksForUpdating"><![CDATA[
+<html>
+<body>
+  Thanks for updating QuickDic.
+  <p> New features:
+  <ul>
+    <li> Easily work with multiple dictionaries.
+    <li> Wiktionary-based dictionaries for French, Italian, German, Spanish, Swedish.
+    <li> Create your own dictionaries.  Look in Menu...About for details.
+  </ul>
+  <p>The new version requires you to re-download any dictionaries you want.<br/>
+</body>
+</html>
+]]>
+  </string>
  
   <!-- DictionaryEditActivity -->
+  <string name="dictionaryEdit">Edit dictionary config</string>
   <string name="dictionaryName">Dictionary name</string>
   <string name="downloadUrl">Dictionary download URL</string>
   <string name="dictionaryInfo">Dictionary info:</string>
@@ -24,6 +42,7 @@
   <string name="numPairEntries">Entries: %d</string>
   <string name="numTokens">Tokens: %d</string>
   <string name="numRows">Rows: %d</string>
+
  
        <!-- Main -->
        <string name="searchText">Search Text</string>
@@ -39,7 +58,9 @@
        <string name="thadHughes">Thad Hughes</string>
        <string name="contactMe">If you\'re using QuickDic, I\'d love to hear from you.  Please send comments, suggestions, bug reports, or just a quick hello to:</string>
        <string name="myEmail">thad.hughes\+quickdic@gmail.com</string>
-       
+  <string name="webPage">For more information, including how to make your own QuickDic dictionaries, see:</string>
+  <string name="webPageUrl">http://sites.google.com/site/quickdic/home</string>
        <!-- Download. -->
        <string name="downloading">Downloading, %d of %d bytes.</string>
        <string name="downloadFinished">Download finished, %d bytes downloaded.</string>
@@ -54,7 +75,7 @@
        <string name="wordListFileKey">wordListFile</string>
        <string name="wordListFileTitle">Word list file</string>
        <string name="wordListFileSummary">The local file where the word list will be appended.</string>
-       <string name="wordListFileDefault">/sdcard/wordList.txt</string>
+       <string name="wordListFileDefault">/sdcard/quickDic/wordList.txt</string>
 
   <string name="saveOnlyFirstSubentryKey">saveOnlyFirstSubentry</string>
   <string name="saveOnlyFirstSubentryTitle">Save only first sub-entry</string>
   <string name="showClearSearchTextButtonTitle">Show \'clear search text\' button</string>
   <string name="showClearSearchTextButtonSummary">Show the button to clear the search text. You can also just move focus away from search text and start typing.</string>
   
-       <string name="dictFileKey">dictFile</string>
-       <string name="dictFileTitle">Dictionary file</string>
-       <string name="dictFileSummary">The local filename where the dictionary is stored (and downloaded to).</string>
-       <string name="dictFileDefault">/sdcard/de-en.dict</string>
-
-       <string name="dictFetchUrlKey">dictFetchUrl</string>
-       <string name="dictFetchUrlTitle">Dictionary fetch URL</string>
-       <string name="dictFetchUrlSummary">URL to use to download the dictionary from the Internet.</string>
-       <string name="dictFetchUrlDefault">http://www.stanford.edu/~egirard/dict/de-en.dict</string>
-
   <string name="vibrateOnFailedSearchKey">vibrateOnFailedSearch</string>
   <string name="vibrateOnFailedSearchTitle">Vibrate on failed search.</string>
   <string name="vibrateOnFailedSearchSummary">Vibrate the phone when invalid search text is entered.</string>
index 21fbfed36b3e9bbe176da0785cf948790cdd6a6a..ce929a1a644fabe52f7c985af66be4f98b98bbec 100644 (file)
@@ -8,5 +8,7 @@ public class C {
   static final String INDEX_INDEX = "indexIndex";
   static final String SEARCH_TOKEN = "searchToken";
 
+  public static final String INTRO_MESSAGE_SHOWN = "introMessageShown";
+
 
 }
index c8850ffafb4627421d2cf9357f6344cfcdfa1b23..afca2b59e7aa84fa69094fe6386ba59d03e9b148 100644 (file)
@@ -1,7 +1,12 @@
 package com.hughes.android.dictionary;\r
 \r
 import java.io.File;\r
+import java.io.FileWriter;\r
+import java.io.IOException;\r
+import java.io.PrintWriter;\r
 import java.io.RandomAccessFile;\r
+import java.text.SimpleDateFormat;\r
+import java.util.Date;\r
 import java.util.concurrent.Executor;\r
 import java.util.concurrent.Executors;\r
 import java.util.concurrent.atomic.AtomicBoolean;\r
@@ -15,22 +20,33 @@ import android.os.Bundle;
 import android.os.Handler;\r
 import android.os.Vibrator;\r
 import android.preference.PreferenceManager;\r
+import android.text.ClipboardManager;\r
 import android.text.Editable;\r
 import android.text.Spannable;\r
 import android.text.TextWatcher;\r
 import android.text.style.StyleSpan;\r
 import android.util.Log;\r
+import android.view.ContextMenu;\r
+import android.view.KeyEvent;\r
+import android.view.Menu;\r
+import android.view.MenuItem;\r
 import android.view.View;\r
 import android.view.ViewGroup;\r
+import android.view.ContextMenu.ContextMenuInfo;\r
+import android.view.MenuItem.OnMenuItemClickListener;\r
 import android.view.View.OnClickListener;\r
 import android.view.inputmethod.InputMethodManager;\r
+import android.widget.AdapterView;\r
 import android.widget.BaseAdapter;\r
 import android.widget.Button;\r
 import android.widget.EditText;\r
 import android.widget.ListAdapter;\r
+import android.widget.ListView;\r
 import android.widget.TableLayout;\r
 import android.widget.TableRow;\r
 import android.widget.TextView;\r
+import android.widget.Toast;\r
+import android.widget.AdapterView.AdapterContextMenuInfo;\r
 \r
 import com.hughes.android.dictionary.engine.Dictionary;\r
 import com.hughes.android.dictionary.engine.Index;\r
@@ -45,6 +61,7 @@ public class DictionaryActivity extends ListActivity {
   \r
   static final int VIBRATE_MILLIS = 100;\r
 \r
+  int dictIndex = 0;\r
   RandomAccessFile dictRaf = null;\r
   Dictionary dictionary = null;\r
   int indexIndex = 0;\r
@@ -70,35 +87,49 @@ public class DictionaryActivity extends ListActivity {
   public DictionaryActivity() {\r
   }\r
   \r
-  public static Intent getIntent(final int dictIndex, final int indexIndex, final String searchToken) {\r
+  public static Intent getIntent(final Context context, final int dictIndex, final int indexIndex, final String searchToken) {\r
+    setDictionaryPrefs(context, dictIndex, indexIndex, searchToken);\r
+    \r
     final Intent intent = new Intent();\r
     intent.setClassName(DictionaryActivity.class.getPackage().getName(), DictionaryActivity.class.getName());\r
-    intent.putExtra(C.DICT_INDEX, dictIndex);\r
-    intent.putExtra(C.INDEX_INDEX, indexIndex);\r
-    intent.putExtra(C.SEARCH_TOKEN, searchToken);\r
     return intent;\r
   }\r
 \r
+  public static void setDictionaryPrefs(final Context context,\r
+      final int dictIndex, final int indexIndex, final String searchToken) {\r
+    final SharedPreferences.Editor prefs = PreferenceManager.getDefaultSharedPreferences(context).edit();\r
+    prefs.putInt(C.DICT_INDEX, dictIndex);\r
+    prefs.putInt(C.INDEX_INDEX, indexIndex);\r
+    prefs.putString(C.SEARCH_TOKEN, searchToken);\r
+    prefs.commit();\r
+  }\r
+\r
+  public static void clearDictionaryPrefs(final Context context) {\r
+    final SharedPreferences.Editor prefs = PreferenceManager.getDefaultSharedPreferences(context).edit();\r
+    prefs.remove(C.DICT_INDEX);\r
+    prefs.remove(C.INDEX_INDEX);\r
+    prefs.remove(C.SEARCH_TOKEN);\r
+    prefs.commit();\r
+  }\r
+\r
   @Override\r
   public void onCreate(Bundle savedInstanceState) {\r
     super.onCreate(savedInstanceState);\r
     \r
     final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);\r
     \r
-    PersistentObjectCache.init(this);\r
-    QuickDicConfig quickDicConfig = PersistentObjectCache.init(\r
-        this).read(C.DICTIONARY_CONFIGS, QuickDicConfig.class);\r
-    \r
-    final Intent intent = getIntent();\r
-    \r
-    final int dictIndex = intent.getIntExtra(C.DICT_INDEX, 0);\r
     try {\r
+      PersistentObjectCache.init(this);\r
+      QuickDicConfig quickDicConfig = PersistentObjectCache.init(\r
+          this).read(C.DICTIONARY_CONFIGS, QuickDicConfig.class);\r
+      dictIndex = prefs.getInt(C.DICT_INDEX, 0) ;\r
       final DictionaryConfig dictionaryConfig = quickDicConfig.dictionaryConfigs.get(dictIndex);\r
       dictRaf = new RandomAccessFile(dictionaryConfig.localFile, "r");\r
       dictionary = new Dictionary(dictRaf); \r
     } catch (Exception e) {\r
       Log.e(LOG, "Unable to load dictionary.", e);\r
-      DictionaryEditActivity.getIntent(dictIndex);\r
+      Toast.makeText(this, getString(R.string.invalidDictionary, "", e.getMessage()), Toast.LENGTH_LONG);\r
+      startActivity(DictionaryEditActivity.getIntent(dictIndex));\r
       finish();\r
       return;\r
     }\r
@@ -121,7 +152,7 @@ public class DictionaryActivity extends ListActivity {
       }\r
     });\r
     \r
-    indexIndex = intent.getIntExtra(C.INDEX_INDEX, 0) % dictionary.indices.size();\r
+    indexIndex = prefs.getInt(C.INDEX_INDEX, 0) % dictionary.indices.size();\r
     index = dictionary.indices.get(indexIndex);\r
     setListAdapter(new IndexAdapter(index));\r
     \r
@@ -129,8 +160,10 @@ public class DictionaryActivity extends ListActivity {
     searchText = (EditText) findViewById(R.id.SearchText);\r
     langButton = (Button) findViewById(R.id.LangButton);\r
     \r
+    searchText.requestFocus();\r
     searchText.addTextChangedListener(new SearchTextWatcher());\r
-    \r
+    searchText.setText(prefs.getString(C.SEARCH_TOKEN, ""));\r
+    Log.d(LOG, "Trying to restore searchText=" + searchText.getText());\r
     \r
     final Button clearSearchTextButton = (Button) findViewById(R.id.ClearSearchTextButton);\r
     clearSearchTextButton.setOnClickListener(new OnClickListener() {\r
@@ -148,6 +181,7 @@ public class DictionaryActivity extends ListActivity {
         onLanguageButton();\r
       }\r
     });\r
+    updateLangButton();\r
     \r
     final Button upButton = (Button) findViewById(R.id.UpButton);\r
     upButton.setOnClickListener(new OnClickListener() {\r
@@ -162,15 +196,56 @@ public class DictionaryActivity extends ListActivity {
       }\r
     });\r
 \r
+   getListView().setOnItemSelectedListener(new ListView.OnItemSelectedListener() {\r
+      @Override\r
+      public void onItemSelected(AdapterView<?> adapterView, View arg1, final int position,\r
+          long id) {\r
+        if (!searchText.isFocused()) {\r
+          // TODO: don't do this if multi words are entered.\r
+          final RowBase row = (RowBase) getListAdapter().getItem(position);\r
+          final TokenRow tokenRow = row.getTokenRow(true);\r
+          searchText.setText(tokenRow.getToken());\r
+        }\r
+      }\r
+\r
+      @Override\r
+      public void onNothingSelected(AdapterView<?> arg0) {\r
+      }\r
+    });\r
+\r
     // ContextMenu.\r
     registerForContextMenu(getListView());\r
-    \r
+\r
+    // Prefs.\r
+    wordList = new File(prefs.getString(getString(R.string.wordListFileKey),\r
+        getString(R.string.wordListFileDefault)));\r
+    saveOnlyFirstSubentry = prefs.getBoolean(getString(R.string.saveOnlyFirstSubentryKey), false);\r
     if (prefs.getBoolean(getString(R.string.vibrateOnFailedSearchKey), true)) {\r
       vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);\r
     }\r
+    Log.d(LOG, "wordList=" + wordList + ", saveOnlyFirstSubentry=" + saveOnlyFirstSubentry);\r
+  }\r
+  \r
+  \r
+  @Override\r
+  protected void onResume() {\r
+    super.onResume();\r
+  }\r
 \r
-    updateLangButton();\r
+  @Override\r
+  protected void onPause() {\r
+    super.onPause();\r
+  }\r
 \r
+  @Override\r
+  protected void onDestroy() {\r
+    super.onDestroy();\r
+    setDictionaryPrefs(this, dictIndex, indexIndex, searchText.getText().toString());\r
+    try {\r
+      dictRaf.close();\r
+    } catch (IOException e) {\r
+      Log.e(LOG, "Failed to close dictionary", e);\r
+    }\r
   }\r
 \r
   // --------------------------------------------------------------------------\r
@@ -221,25 +296,150 @@ public class DictionaryActivity extends ListActivity {
       destIndexEntry = Math.min(tokenRow.referenceIndex + 1, index.sortedIndexEntries.size());\r
     }\r
     \r
-    Log.d(LOG, "onUpDownButton, destIndexEntry=" + destIndexEntry);\r
-    jumpToRow(index.sortedIndexEntries.get(destIndexEntry).startRow);\r
+    final Index.IndexEntry dest = index.sortedIndexEntries.get(destIndexEntry);\r
+    searchText.setText(dest.token);\r
+    Log.d(LOG, "onUpDownButton, destIndexEntry=" + dest.token);\r
+    //jumpToRow(index.sortedIndexEntries.get(destIndexEntry).startRow);\r
   }\r
 \r
   // --------------------------------------------------------------------------\r
-  // Menu\r
+  // Options Menu\r
   // --------------------------------------------------------------------------\r
+  \r
+  @Override\r
+  public boolean onCreateOptionsMenu(final Menu menu) {\r
+    \r
+    {\r
+    final MenuItem preferences = menu.add(getString(R.string.preferences));\r
+    preferences.setOnMenuItemClickListener(new OnMenuItemClickListener() {\r
+      public boolean onMenuItemClick(final MenuItem menuItem) {\r
+        startActivity(new Intent(DictionaryActivity.this,\r
+            PreferenceActivity.class));\r
+        return false;\r
+      }\r
+    });\r
+    }\r
+\r
+    {\r
+    final MenuItem dictionaryList = menu.add(getString(R.string.dictionaryList));\r
+    dictionaryList.setOnMenuItemClickListener(new OnMenuItemClickListener() {\r
+      public boolean onMenuItemClick(final MenuItem menuItem) {\r
+        startActivity(DictionaryListActivity.getIntent(DictionaryActivity.this));\r
+        startActivity(DictionaryListActivity.getIntent(DictionaryActivity.this));\r
+        return false;\r
+      }\r
+    });\r
+    }\r
+\r
+    {\r
+      final MenuItem dictionaryList = menu.add(getString(R.string.editDictionary));\r
+      dictionaryList.setOnMenuItemClickListener(new OnMenuItemClickListener() {\r
+        public boolean onMenuItemClick(final MenuItem menuItem) {\r
+          final Intent intent = DictionaryEditActivity.getIntent(dictIndex);\r
+          startActivity(intent);\r
+          return false;\r
+        }\r
+      });\r
+      }\r
+\r
+    return true;\r
+  }\r
+\r
+\r
+  // --------------------------------------------------------------------------\r
+  // Context Menu + clicks\r
+  // --------------------------------------------------------------------------\r
+\r
+  @Override\r
+  public void onCreateContextMenu(ContextMenu menu, View v,\r
+      ContextMenuInfo menuInfo) {\r
+    AdapterContextMenuInfo adapterContextMenuInfo = (AdapterContextMenuInfo) menuInfo;\r
+    final RowBase row = (RowBase) getListAdapter().getItem(adapterContextMenuInfo.position);\r
+\r
+    final MenuItem addToWordlist = menu.add(getString(R.string.addToWordList, wordList.getName()));\r
+    addToWordlist.setOnMenuItemClickListener(new OnMenuItemClickListener() {\r
+      public boolean onMenuItemClick(MenuItem item) {\r
+        onAppendToWordList(row);\r
+        return false;\r
+      }\r
+    });\r
+\r
+    final MenuItem copy = menu.add(android.R.string.copy);\r
+    copy.setOnMenuItemClickListener(new OnMenuItemClickListener() {\r
+      public boolean onMenuItemClick(MenuItem item) {\r
+        onCopy(row);\r
+        return false;\r
+      }\r
+    });\r
+\r
+  }\r
+  \r
+  @Override\r
+  protected void onListItemClick(ListView l, View v, int row, long id) {\r
+    openContextMenu(v);\r
+  }\r
+  \r
+  void onAppendToWordList(final RowBase row) {\r
+    final StringBuilder rawText = new StringBuilder();\r
+    rawText.append(\r
+        new SimpleDateFormat("yyyy.MM.dd HH:mm:ss").format(new Date()))\r
+        .append("\t");\r
+    rawText.append(index.longName).append("\t");\r
+    rawText.append(row.getTokenRow(true).getToken()).append("\t");\r
+    rawText.append(row.getRawText(saveOnlyFirstSubentry));\r
+    Log.d(LOG, "Writing : " + rawText);\r
+    try {\r
+      wordList.getParentFile().mkdirs();\r
+      final PrintWriter out = new PrintWriter(\r
+          new FileWriter(wordList, true));\r
+      out.println(rawText.toString());\r
+      out.close();\r
+    } catch (IOException e) {\r
+      Log.e(LOG, "Unable to append to " + wordList.getAbsolutePath(), e);\r
+      Toast.makeText(this, getString(R.string.failedAddingToWordList, wordList.getAbsolutePath()), Toast.LENGTH_LONG);\r
+    }\r
+    return;\r
+  }\r
+\r
+  void onCopy(final RowBase row) {\r
+    Log.d(LOG, "Copy, row=" + row);\r
+    final StringBuilder result = new StringBuilder();\r
+    result.append(row.getRawText(false));\r
+    final ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);\r
+    clipboardManager.setText(result.toString());\r
+    Log.d(LOG, "Copied: " + result);\r
+  }\r
+\r
+  @Override\r
+  public boolean onKeyDown(final int keyCode, final KeyEvent event) {\r
+    if (event.getUnicodeChar() != 0) {\r
+      if (!searchText.hasFocus()) {\r
+        searchText.setText("" + (char) event.getUnicodeChar());\r
+        onSearchTextChange(searchText.getText().toString());\r
+        searchText.requestFocus();\r
+      }\r
+      return true;\r
+    }\r
+    return super.onKeyDown(keyCode, event);\r
+  }\r
+\r
 \r
   // --------------------------------------------------------------------------\r
   // SearchOperation\r
   // --------------------------------------------------------------------------\r
 \r
   private void searchFinished(final SearchOperation searchOperation) {\r
+    if (searchOperation.interrupted.get()) {\r
+      Log.d(LOG, "Search operation was interrupted: " + searchOperation);\r
+      return;\r
+    }\r
     if (searchOperation != this.currentSearchOperation) {\r
+      Log.d(LOG, "Stale searchOperation finished: " + searchOperation);\r
       return;\r
     }\r
     \r
     final Index.SearchResult searchResult = searchOperation.searchResult;\r
-    Log.d(LOG, "searchFinished, " + searchResult.longestPrefixString + ", success=" + searchResult.success);\r
+    Log.d(LOG, "searchFinished: " + searchOperation + ", searchResult=" + searchResult);\r
 \r
     jumpToRow(searchResult.longestPrefix.startRow);\r
     \r
@@ -272,6 +472,10 @@ public class DictionaryActivity extends ListActivity {
       this.searchText = searchText.trim();\r
       this.index = index;\r
     }\r
+    \r
+    public String toString() {\r
+      return String.format("SearchOperation(%s,%s)", searchText, interrupted.toString());\r
+    }\r
 \r
     @Override\r
     public void run() {\r
@@ -310,13 +514,13 @@ public class DictionaryActivity extends ListActivity {
     }\r
 \r
     @Override\r
-    public Object getItem(int position) {\r
+    public RowBase getItem(int position) {\r
       return index.rows.get(position);\r
     }\r
 \r
     @Override\r
     public long getItemId(int position) {\r
-      return position;\r
+      return getItem(position).index();\r
     }\r
 \r
     @Override\r
@@ -394,19 +598,23 @@ public class DictionaryActivity extends ListActivity {
   // SearchText\r
   // --------------------------------------------------------------------------\r
 \r
-  void onSearchTextChange(final String searchText) {\r
-    Log.d(LOG, "onSearchTextChange: " + searchText);\r
+  void onSearchTextChange(final String text) {\r
+    if (!searchText.isFocused()) {\r
+      return;\r
+    }\r
+    Log.d(LOG, "onSearchTextChange: " + text);    \r
     if (currentSearchOperation != null) {\r
+      Log.d(LOG, "Interrupting currentSearchOperation.");\r
       currentSearchOperation.interrupted.set(true);\r
     }\r
-    currentSearchOperation = new SearchOperation(searchText, index);\r
+    currentSearchOperation = new SearchOperation(text, index);\r
     searchExecutor.execute(currentSearchOperation);\r
   }\r
   \r
   private class SearchTextWatcher implements TextWatcher {\r
     public void afterTextChanged(final Editable searchTextEditable) {\r
-      Log.d(LOG, "Search text changed: " + searchText.getText());\r
       if (searchText.hasFocus()) {\r
+        Log.d(LOG, "Search text changed with focus: " + searchText.getText());\r
         // If they were typing to cause the change, update the UI.\r
         onSearchTextChange(searchText.getText().toString());\r
       }\r
index 1c2458b7ad700a5bce282878723b0854bd01b531..3ef63332938de09493836946ec44214336ea28b2 100644 (file)
@@ -8,7 +8,6 @@ public class DictionaryConfig implements Serializable {
 
   String name = "";
   String localFile = "/sdcard/quickDic/";
-  String wordList = "/sdcard/quickDic/";
   String downloadUrl = "http://";
   
   int openIndex = 0;
@@ -19,7 +18,6 @@ public class DictionaryConfig implements Serializable {
     result.name = "DE<->EN";
     result.downloadUrl = "http://www.stanford.edu/~egirard/dict/de-en.2.dict";
     result.localFile = "/sdcard/quickDic/de-en.dict";
-    result.wordList = "/sdcard/quickDict/wordlist_de-en.txt";
     return result;
   }
   
index 1e3615607d7ca27105f04d6cc0c2f96bbc948c4b..cc21132c504d1d75a413cb662564b66c5ccdce90 100644 (file)
@@ -10,6 +10,7 @@ import android.content.Intent;
 import android.os.Bundle;
 import android.text.Editable;
 import android.text.TextWatcher;
+import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MenuItem.OnMenuItemClickListener;
@@ -22,13 +23,15 @@ import com.hughes.android.util.PersistentObjectCache;
 
 public class DictionaryEditActivity extends Activity {
 
+  static final String LOG = "QuickDic";
+
   QuickDicConfig quickDicConfig;
   private DictionaryConfig dictionaryConfig;
 
-  
   public static Intent getIntent(final int dictIndex) {
     final Intent intent = new Intent();
-    intent.setClassName(DictionaryEditActivity.class.getPackage().getName(), DictionaryEditActivity.class.getName());
+    intent.setClassName(DictionaryEditActivity.class.getPackage().getName(),
+        DictionaryEditActivity.class.getName());
     intent.putExtra(C.DICT_INDEX, dictIndex);
     return intent;
   }
@@ -39,92 +42,118 @@ public class DictionaryEditActivity extends Activity {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.edit_activity);
 
-    PersistentObjectCache.init(this);
-    quickDicConfig = PersistentObjectCache.init(
-        this).read(C.DICTIONARY_CONFIGS, QuickDicConfig.class);
-
     final Intent intent = getIntent();
-    dictionaryConfig = quickDicConfig.dictionaryConfigs.get(intent.getIntExtra(C.DICT_INDEX, 0));
 
-    // Write stuff from object into fields.
-    
-    ((EditText) findViewById(R.id.dictionaryName)).setText(dictionaryConfig.name);
-    ((EditText) findViewById(R.id.localFile)).setText(dictionaryConfig.localFile);
-    ((EditText) findViewById(R.id.wordListFile)).setText(dictionaryConfig.wordList);
-    ((EditText) findViewById(R.id.downloadUrl)).setText(dictionaryConfig.downloadUrl);
+    PersistentObjectCache.init(this);
+    try {
+      quickDicConfig = PersistentObjectCache.init(this).read(
+          C.DICTIONARY_CONFIGS, QuickDicConfig.class);
+      dictionaryConfig = quickDicConfig.dictionaryConfigs.get(intent
+          .getIntExtra(C.DICT_INDEX, 0));
+    } catch (Exception e) {
+      Log.e(LOG, "Failed to read QuickDicConfig.", e);
+      quickDicConfig = new QuickDicConfig();
+      dictionaryConfig = quickDicConfig.dictionaryConfigs.get(0);
+    }
     
+    // Write stuff from object into fields.
+
+    ((EditText) findViewById(R.id.dictionaryName))
+        .setText(dictionaryConfig.name);
+    ((EditText) findViewById(R.id.localFile))
+        .setText(dictionaryConfig.localFile);
+    ((EditText) findViewById(R.id.downloadUrl))
+        .setText(dictionaryConfig.downloadUrl);
+
     updateDictInfo();
-    ((EditText) findViewById(R.id.localFile)).addTextChangedListener(new TextWatcher() {
-      @Override
-      public void onTextChanged(CharSequence s, int start, int before, int count) {
-      }
-      
-      @Override
-      public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-      }
-      
-      @Override
-      public void afterTextChanged(Editable s) {
-        updateDictInfo();
-      }
-    });
-    
+    ((EditText) findViewById(R.id.localFile))
+        .addTextChangedListener(new TextWatcher() {
+          @Override
+          public void onTextChanged(CharSequence s, int start, int before,
+              int count) {
+          }
+
+          @Override
+          public void beforeTextChanged(CharSequence s, int start, int count,
+              int after) {
+          }
+
+          @Override
+          public void afterTextChanged(Editable s) {
+            updateDictInfo();
+          }
+        });
+
   }
 
   @Override
   protected void onPause() {
     super.onPause();
-    
+
     // Read stuff from fields into object.
-    dictionaryConfig.name = ((EditText) findViewById(R.id.dictionaryName)).getText().toString();
-    dictionaryConfig.localFile = ((EditText) findViewById(R.id.localFile)).getText().toString();
-    dictionaryConfig.wordList = ((EditText) findViewById(R.id.wordListFile)).getText().toString();
-    dictionaryConfig.downloadUrl = ((EditText) findViewById(R.id.downloadUrl)).getText().toString();
-    
-    PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, quickDicConfig);
+    dictionaryConfig.name = ((EditText) findViewById(R.id.dictionaryName))
+        .getText().toString();
+    dictionaryConfig.localFile = ((EditText) findViewById(R.id.localFile))
+        .getText().toString();
+    dictionaryConfig.downloadUrl = ((EditText) findViewById(R.id.downloadUrl))
+        .getText().toString();
+
+    PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS,
+        quickDicConfig);
   }
-  
+
   public boolean onCreateOptionsMenu(final Menu menu) {
-    final MenuItem newDictionaryMenuItem = menu.add(R.string.downloadDictionary);
-    newDictionaryMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
+    final MenuItem newDictionaryMenuItem = menu
+        .add(R.string.downloadDictionary);
+    newDictionaryMenuItem
+        .setOnMenuItemClickListener(new OnMenuItemClickListener() {
           public boolean onMenuItemClick(final MenuItem menuItem) {
-            startDownloadDictActivity(DictionaryEditActivity.this, dictionaryConfig);
+            startDownloadDictActivity(DictionaryEditActivity.this,
+                dictionaryConfig);
             return false;
           }
         });
-    
+
     return true;
   }
-  
+
   void updateDictInfo() {
     final TextView dictInfo = (TextView) findViewById(R.id.dictionaryInfo);
-    final String localFile = ((EditText) findViewById(R.id.localFile)).getText().toString();
-    
+    final String localFile = ((EditText) findViewById(R.id.localFile))
+        .getText().toString();
+
     if (!new File(localFile).canRead()) {
       dictInfo.setText(getString(R.string.fileNotFound, localFile));
       return;
     }
-    
+
     try {
       final RandomAccessFile raf = new RandomAccessFile(localFile, "r");
       final Dictionary dict = new Dictionary(raf);
       final StringBuilder builder = new StringBuilder();
       builder.append(dict.dictInfo).append("\n");
-      builder.append(getString(R.string.numPairEntries, dict.pairEntries.size())).append("\n");
+      builder.append(
+          getString(R.string.numPairEntries, dict.pairEntries.size())).append(
+          "\n");
       for (final Index index : dict.indices) {
         builder.append("\n");
         builder.append(index.longName).append("\n");
-        builder.append("  ").append(getString(R.string.numTokens, index.sortedIndexEntries.size())).append("\n");
-        builder.append("  ").append(getString(R.string.numRows, index.rows.size())).append("\n");
+        builder.append("  ").append(
+            getString(R.string.numTokens, index.sortedIndexEntries.size()))
+            .append("\n");
+        builder.append("  ").append(
+            getString(R.string.numRows, index.rows.size())).append("\n");
       }
       raf.close();
       dictInfo.setText(builder.toString());
     } catch (IOException e) {
-      dictInfo.setText(getString(R.string.invalidDictionary, localFile, e.toString()));
+      dictInfo.setText(getString(R.string.invalidDictionary, localFile, e
+          .toString()));
     }
   }
 
-  static void startDownloadDictActivity(final Context context, final DictionaryConfig dictionaryConfig) {
+  static void startDownloadDictActivity(final Context context,
+      final DictionaryConfig dictionaryConfig) {
     final Intent intent = new Intent(context, DownloadActivity.class);
     intent.putExtra(DownloadActivity.SOURCE, dictionaryConfig.downloadUrl);
     intent.putExtra(DownloadActivity.DEST, dictionaryConfig.localFile);
index 26f7075563ddb7c57b1ade9ecf720bcc1085bc4c..29ec4b88f94475bfd8095f9c9ac44dd847deb676 100644 (file)
@@ -1,8 +1,13 @@
 package com.hughes.android.dictionary;
 
+import android.app.AlertDialog;
 import android.app.ListActivity;
+import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.SharedPreferences;
 import android.os.Bundle;
+import android.preference.PreferenceManager;
 import android.util.Log;
 import android.view.ContextMenu;
 import android.view.Menu;
@@ -11,6 +16,7 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.MenuItem.OnMenuItemClickListener;
+import android.webkit.WebView;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.TableLayout;
@@ -34,15 +40,6 @@ public class DictionaryListActivity extends ListActivity {
     // UI init.
     setContentView(R.layout.list_activity);
 
-    /*
-    getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
-      public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int row,
-          long arg3) {
-        return false;
-      }
-    });
-    */
-
     getListView().setOnItemClickListener(new OnItemClickListener() {
       @Override
       public void onItemClick(AdapterView<?> arg0, View arg1, int index,
@@ -53,17 +50,41 @@ public class DictionaryListActivity extends ListActivity {
 
     // ContextMenu.
     registerForContextMenu(getListView());
-    
+
+    final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+    final int introMessageId = 0;
+    if (prefs.getInt(C.INTRO_MESSAGE_SHOWN, 0) < introMessageId) {
+      final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+      builder.setCancelable(false);
+      final WebView webView = new WebView(getApplicationContext());
+      webView.loadData(getString(R.string.thanksForUpdating), "text/html", "utf-8");
+      builder.setView(webView);
+      builder.setNegativeButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+          public void onClick(DialogInterface dialog, int id) {
+               dialog.cancel();
+          }
+      });
+      final AlertDialog alert = builder.create();
+      alert.show();
+      prefs.edit().putInt(C.INTRO_MESSAGE_SHOWN, introMessageId).commit();
+    }
   }
   
   private void onClick(int dictIndex) {
-    final Intent intent = DictionaryActivity.getIntent(dictIndex, 0, "");
+    final Intent intent = DictionaryActivity.getIntent(this, dictIndex, 0, "");
     startActivity(intent);
   }
   
   @Override
   protected void onResume() {
     super.onResume();
+    
+    final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+    if (prefs.contains(C.DICT_INDEX) && prefs.contains(C.INDEX_INDEX)) {
+      startActivity(DictionaryActivity.getIntent(this, prefs.getInt(C.DICT_INDEX, 0), prefs.getInt(C.INDEX_INDEX, 0), prefs.getString(C.SEARCH_TOKEN, "")));
+      finish();
+      return;
+    }
 
     quickDicConfig = PersistentObjectCache.init(this).read(C.DICTIONARY_CONFIGS, QuickDicConfig.class);
     if (quickDicConfig == null) {
@@ -72,6 +93,7 @@ public class DictionaryListActivity extends ListActivity {
     }
 
     setListAdapter(new Adapter());
+    
   }
 
   public boolean onCreateOptionsMenu(final Menu menu) {
@@ -168,5 +190,12 @@ public class DictionaryListActivity extends ListActivity {
     
   }
 
+  public static Intent getIntent(final Context context) {
+    DictionaryActivity.clearDictionaryPrefs(context);
+    final Intent intent = new Intent();
+    intent.setClassName(DictionaryListActivity.class.getPackage().getName(),
+        DictionaryListActivity.class.getName());
+    return intent;
+  }
 
 }
index cbe76fb716adcc359522bf80620c251307cd7ba0..f85af818209fae3ac86d23d084bc1ebf777a61fb 100644 (file)
@@ -20,6 +20,7 @@ public class Dictionary implements RAFSerializable<Dictionary> {
   
   // persisted
   final int dictFileVersion;
+  final long creationMillis;
   public final String dictInfo;
   public final List<PairEntry> pairEntries;
   public final List<TextEntry> textEntries;
@@ -28,6 +29,7 @@ public class Dictionary implements RAFSerializable<Dictionary> {
   
   public Dictionary(final String dictInfo) {
     this.dictFileVersion = 0;
+    this.creationMillis = System.currentTimeMillis();
     this.dictInfo = dictInfo;
     pairEntries = new ArrayList<PairEntry>();
     textEntries = new ArrayList<TextEntry>();
@@ -40,6 +42,7 @@ public class Dictionary implements RAFSerializable<Dictionary> {
     if (dictFileVersion != 0) {
       throw new IOException("Invalid dictionary version: " + dictFileVersion);
     }
+    creationMillis = raf.readLong();
     dictInfo = raf.readUTF();
     sources = CachingList.createFullyCached(RAFList.create(raf, EntrySource.SERIALIZER, raf.getFilePointer()));
     pairEntries = CachingList.create(RAFList.create(raf, PairEntry.SERIALIZER, raf.getFilePointer()), CACHE_SIZE);
@@ -54,6 +57,7 @@ public class Dictionary implements RAFSerializable<Dictionary> {
   @Override
   public void write(RandomAccessFile raf) throws IOException {
     raf.writeInt(dictFileVersion);
+    raf.writeLong(creationMillis);
     raf.writeUTF(dictInfo);
     RAFList.write(raf, sources, EntrySource.SERIALIZER);
     RAFList.write(raf, pairEntries, PairEntry.SERIALIZER);
index e15c1b74502cd8cc6d100f035e3ba55544ee843b..2d3d42f98e7b48804a021e69574e2b57a9cca710 100644 (file)
@@ -85,6 +85,7 @@ public final class Index implements RAFSerializable<Index> {
   public static final class IndexEntry implements RAFSerializable<Index.IndexEntry> {
     public final String token;
     public final int startRow;
+    public final int numRows;
     
     static final RAFSerializer<IndexEntry> SERIALIZER = new RAFSerializer<IndexEntry> () {
       @Override
@@ -96,25 +97,28 @@ public final class Index implements RAFSerializable<Index> {
         t.write(raf);
       }};
       
-    public IndexEntry(final String token, final int startRow) {
+    public IndexEntry(final String token, final int startRow, final int numRows) {
       assert token.equals(token.trim());
       assert token.length() > 0;
       this.token = token;
       this.startRow = startRow;
+      this.numRows = numRows;
     }
     
     public IndexEntry(final RandomAccessFile raf) throws IOException {
       token = raf.readUTF();
       startRow = raf.readInt();
+      numRows = raf.readInt();
     }
     
     public void write(RandomAccessFile raf) throws IOException {
       raf.writeUTF(token);
       raf.writeInt(startRow);
+      raf.writeInt(numRows);
     }
 
     public String toString() {
-      return token + "@" + startRow;
+      return String.format("%s@%d(%d)", token, startRow, numRows);
     }
   }
   
@@ -164,6 +168,11 @@ public final class Index implements RAFSerializable<Index> {
       this.longestPrefixString = longestPrefixString;
       this.success = success;
     }
+    
+    @Override
+    public String toString() {
+      return String.format("inerstionPoint=%s,longestPrefix=%s,longestPrefixString=%s,success=%b", insertionPoint.toString(), longestPrefix.toString(), longestPrefixString, success);
+    }
   }
   
   public SearchResult findLongestSubstring(String token, final AtomicBoolean interrupted) {
index 4f7c6a56f280fa55c47d0d7999d694c8f381ed51..7d30310bb9572bc3ac9072a4d2034524b7dafd4b 100644 (file)
@@ -22,6 +22,11 @@ public class PairEntry extends Entry implements RAFSerializable<PairEntry> {
     public String toString() {
       return lang1 + " :: " + lang2;
     }
+
+    public String toStringTab() {
+      return lang1 + "\t" + lang2;
+    }
+
   }
   
   public final Pair[] pairs;
@@ -83,6 +88,29 @@ public class PairEntry extends Entry implements RAFSerializable<PairEntry> {
         out.println();
       }
     }
+
+    @Override
+    public String getRawText(boolean compact) {
+      final PairEntry pairEntry = getEntry();
+      if (compact) {
+        return pairEntry.pairs[0].toStringTab();
+      }
+      final StringBuilder builder = new StringBuilder();
+      for (int i = 0; i < pairEntry.pairs.length; ++i) {
+        if (i > 0) {
+          builder.append(" | ");
+        }
+        builder.append(pairEntry.pairs[i].lang1);
+      }
+      builder.append("\t");
+      for (int i = 0; i < pairEntry.pairs.length; ++i) {
+        if (i > 0) {
+          builder.append(" | ");
+        }
+        builder.append(pairEntry.pairs[i].lang2);
+      }
+      return builder.toString();
+    }
   }
 
 
index 64500585e4b9716c78a300346bbac4b5a1ba849e..5491b4e0f9a99026446d8bac53e2db233c74a55d 100644 (file)
@@ -64,7 +64,9 @@ public abstract class RowBase extends IndexedObject {
   }
 
   public abstract void print(PrintStream out);
-  
+
+  public abstract String getRawText(final boolean compact);
+
   // RowBase must manage "disk-based" polymorphism.  All other polymorphism is
   // dealt with in the normal manner.
   static class Serializer implements RAFListSerializer<RowBase> {
index 4aba121122fe0ea90e44903af7d793700d217c66..dd7109234c380268dcefe519677b1a662a60374d 100644 (file)
@@ -47,6 +47,11 @@ public class TextEntry extends Entry implements RAFSerializable<TextEntry> {
     public void print(PrintStream out) {
       out.println("  " + getEntry().text);
     }
+
+    @Override
+    public String getRawText(boolean compact) {
+      return getEntry().text;
+    }
   }
 
 
index 3cfce02caac5a8692081ca8b0dab2e398bb2c8c3..e40d124b5e7800b3d80722bfea4ae076c939169c 100644 (file)
@@ -37,5 +37,10 @@ public class TokenRow extends RowBase {
     out.println(getToken());
   }
 
+  @Override
+  public String getRawText(boolean compact) {
+    return getToken();
+  }
+
 
 }