]> gitweb.fperrin.net Git - Dictionary.git/commitdiff
addingList
authorthadh <thadh@THADH-MTV.ad.corp.google.com>
Mon, 23 Feb 2009 08:30:14 +0000 (00:30 -0800)
committerthadh <thadh@THADH-MTV.ad.corp.google.com>
Mon, 23 Feb 2009 08:30:14 +0000 (00:30 -0800)
AndroidManifest.xml
src/com/hughes/android/dictionary/Dictionary.java
src/com/hughes/android/dictionary/Entry.java
src/com/hughes/android/dictionary/Index.java

index 640d31de4f88f086b3dc1040a7dec43d6c871fcc..577a753b19b425a6efa7f6a23d7088a928584212 100755 (executable)
@@ -4,7 +4,7 @@
       android:versionCode="1"
       android:versionName="1.0.0">
     <application android:icon="@drawable/icon" android:label="@string/app_name">
-        <activity android:name=".Dictionary"
+        <activity android:name=".DictionaryActivity"
                   android:label="@string/app_name">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
index 1e01bc974b7e93a09c807ddbfd0ea167acd065a2..ec0d0f683adba9dfb1e79aaa8b911895d11b6be4 100755 (executable)
-package com.hughes.android.dictionary;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-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.os.Bundle;
-import android.os.Handler;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.Log;
-import android.view.ContextMenu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.MenuItem.OnMenuItemClickListener;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.EditText;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.AdapterView.OnItemLongClickListener;
-
-import com.hughes.util.FileUtil;
-
-public class Dictionary extends ListActivity {
-
-  public static final String INDEX_FORMAT = "%s_index_%d";
-  private File dictionaryFile = new File("/sdcard/dict-de-en.txt");
-  private File wordList = new File("/sdcard/wordList.txt");
-
-  private RandomAccessFile dictionaryRaf;
-  private final Index[] indexes = new Index[2];
-  private final byte lang = Entry.LANG1;
-
-  final Handler uiHandler = new Handler();
-
-  private final Object mutex = new Object();
-  private Executor searchExecutor = Executors.newSingleThreadExecutor();
-  private SearchOperation searchOperation = null;
-  private List<Entry> entries = Collections.emptyList();
-  private DictionaryListAdapter dictionaryListAdapter = new DictionaryListAdapter();
-  private int selectedItem = -1;
-
-  /** Called when the activity is first created. */
-  @Override
-  public void onCreate(Bundle savedInstanceState) {
-    Log.d("THAD", "onCreate");
-    super.onCreate(savedInstanceState);
-    setContentView(R.layout.main);
-
-    EditText searchText = (EditText) findViewById(R.id.SearchText);
-    searchText.addTextChangedListener(new DictionaryTextWatcher());
-
-    setListAdapter(dictionaryListAdapter);
-
-    try {
-      loadIndex();
-    } catch (Exception e) {
-      throw new RuntimeException(e);
-    }
-    onSearchTextChange("");
-
-    registerForContextMenu(getListView());
-    getListView().setOnItemLongClickListener((new OnItemLongClickListener() {
-      public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,
-          long arg3) {
-        selectedItem = arg2;
-        return false;
-      }
-    }));
-  }
-
-  private void loadIndex() throws IOException, ClassNotFoundException {
-    Log.d("THAD", "enter loadIndex");
-    indexes[0] = new Index(String.format(INDEX_FORMAT, dictionaryFile
-        .getAbsolutePath(), Entry.LANG1));
-    dictionaryRaf = new RandomAccessFile(dictionaryFile, "r");
-    Log.d("THAD", "exit loadIndex");
-  }
-
-  @Override
-  public void onCreateContextMenu(ContextMenu menu, View v,
-      ContextMenuInfo menuInfo) {
-    if (selectedItem == -1) {
-      return;
-    }
-    final MenuItem addToWordlist = menu.add("Add to wordlist.");
-    addToWordlist.setOnMenuItemClickListener(new OnMenuItemClickListener() {
-      public boolean onMenuItemClick(MenuItem item) {
-        final String rawText = entries.get(selectedItem).getRawText();
-        Log.d("THAD", "Writing : "
-                + rawText);
-        try {
-          final OutputStream out = new FileOutputStream(wordList, true);
-          out.write((rawText + "\n").getBytes());
-          out.close();
-        } catch (IOException e) {
-          throw new RuntimeException(e);
-        }
-        return false;
-      }
-    });
-  }
-
-  @Override
-  protected void onListItemClick(ListView l, View v, int position, long id) {
-    Log.d("THAD", "Clicked: " + entries.get(position).getRawText());
-    selectedItem = position;
-    openContextMenu(getListView());
-  }
-
-  void onSearchTextChange(final String searchText) {
-    Log.d("THAD", "onSearchTextChange: " + searchText);
-    synchronized (mutex) {
-      if (searchOperation != null) {
-        searchOperation.interrupted.set(true);
-      }
-      searchOperation = new SearchOperation(searchText);
-    }
-    searchExecutor.execute(searchOperation);
-  }
-
-  private final class SearchOperation implements Runnable {
-    final String searchText;
-    final int count = 100;
-    final AtomicBoolean interrupted = new AtomicBoolean(false);
-
-    public SearchOperation(final String searchText) {
-      this.searchText = searchText.toLowerCase(); // TODO: better
-    }
-
-    public void run() {
-      Log.d("THAD", "SearchOperation: " + searchText);
-      final List<Entry> newEntries = new ArrayList<Entry>(count);
-      try {
-        final Index.Node node = indexes[lang].lookup(searchText);
-        final Set<Integer> entryOffsets = new LinkedHashSet<Integer>(count);
-        node.getDescendantEntryOffsets(entryOffsets, count);
-        for (final int entryOffset : entryOffsets) {
-          if (interrupted.get()) {
-            Log.d("THAD", "Interrupted while parsing entries.");
-            return;
-          }
-          final String line = FileUtil.readLine(dictionaryRaf, entryOffset);
-          final Entry entry = new Entry(line);
-          newEntries.add(entry);
-        }
-      } catch (IOException e) {
-        Log.e("THAD", "Search failure.", e);
-      }
-
-      synchronized (mutex) {
-        if (interrupted.get()) {
-          return;
-        }
-        entries = newEntries;
-      }
-
-      uiHandler.post(new Runnable() {
-        public void run() {
-          synchronized (mutex) {
-            dictionaryListAdapter.notifyDataSetChanged();
-            if (entries.size() > 0) {
-              setSelection(0);
-            }
-          }
-        }
-      });
-    }
-  }
-
-  private class DictionaryListAdapter extends BaseAdapter {
-
-    public int getCount() {
-      synchronized (mutex) {
-        return entries.size();
-      }
-    }
-
-    public Object getItem(int position) {
-      synchronized (mutex) {
-        assert position < entries.size();
-        return entries.get(position).getFormattedEntry(lang);
-      }
-    }
-
-    public long getItemId(int position) {
-      return position;
-    }
-
-    public View getView(final int position, final View convertView,
-        final ViewGroup parent) {
-      TextView result = null;
-      if (convertView instanceof TextView) {
-        result = (TextView) convertView;
-      } else {
-        result = new TextView(parent.getContext());
-      }
-      result.setText((String) getItem(position));
-      return result;
-    }
-
-  }
-
-  private class DictionaryTextWatcher implements TextWatcher {
-    public void afterTextChanged(Editable searchText) {
-      onSearchTextChange(searchText.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
+package com.hughes.android.dictionary;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.io.RandomAccessFile;\r
+\r
+import com.hughes.util.FileUtil;\r
+import com.hughes.util.LRUCacheMap;\r
+\r
+public final class Dictionary {\r
+\r
+  public static final String INDEX_FORMAT = "%s_index_%d";\r
+\r
+  private final byte lang;\r
+  private final File dictionaryFile;\r
+  private final RandomAccessFile dictionaryRaf;\r
+  private final Index index;\r
+  \r
+  private final LRUCacheMap<Integer,Row> positionToRow = new LRUCacheMap<Integer, Row>(2000);\r
+\r
+  public Dictionary(final String dictionaryFileName, final byte lang)\r
+      throws IOException {\r
+    this.lang = lang;\r
+    this.dictionaryFile = new File(dictionaryFileName);\r
+\r
+    dictionaryRaf = new RandomAccessFile(dictionaryFile, "r");\r
+    index = new Index(String.format(INDEX_FORMAT, dictionaryFile\r
+        .getAbsolutePath(), lang));\r
+  }\r
+  \r
+  public int numRows() {\r
+    return index.root.getDescendantCount();\r
+  }\r
+  \r
+  public Row getRow(final int position) throws IOException {\r
+    Row row = positionToRow.get(position);\r
+    if (row == null) {\r
+      final Object o = index.root.getDescendant(position);\r
+      if (o instanceof Integer) {\r
+        final Entry entry = new Entry(FileUtil.readLine(dictionaryRaf, (Integer) o));\r
+        row = new Row(entry.getFormattedEntry(lang), false);\r
+      } else if (o instanceof String) {\r
+        row = new Row((String) o, true);\r
+      } else {\r
+        throw new RuntimeException(o.toString());\r
+      }\r
+      positionToRow.put(position, row);\r
+    }\r
+    return row;\r
+  }\r
+  \r
+  public static class Row {\r
+    final String text;\r
+    final boolean isWord;\r
+    public Row(final String text, final boolean isWord) {\r
+      this.text = text;\r
+      this.isWord = isWord;\r
+    }\r
+  }\r
+\r
+}\r
index d04722f273e4f1db3b15db5c9717fbea503b3e48..0c4cd60f7869c68b94814bb623084b1f42dccea4 100755 (executable)
@@ -45,7 +45,7 @@ public final class Entry {
     return text;\r
   }\r
 \r
-  public Object getFormattedEntry(final byte lang) {\r
+  public String getFormattedEntry(final byte lang) {\r
     return getAllText(lang) + "\n" + getAllText(OtherLang(lang));\r
   }\r
 \r
index 3970f2220fb473a00351cbb12353140fad508e8f..9981a9f52fe4085a73aefc0cf0201ac55912d239 100755 (executable)
@@ -110,26 +110,57 @@ public final class Index {
         tokenToOffsets.put(token, offsets);\r
       }\r
       \r
+      // TODO: move this up, and defer the loading of the other stuff until it's needed.\r
       descendantTokenCount = file.readInt();\r
       descendantEntryCount = file.readInt();\r
     }\r
     \r
+    @Override\r
+    public String toString() {\r
+      return String.format("%s(%d,%d)", nodeHandle.normalizedToken, getThisCount(), getDescendantCount());\r
+    }\r
+    \r
     public int getDescendantCount() {\r
       return descendantEntryCount + descendantTokenCount;\r
     }\r
+    \r
+    public int getThisCount() {\r
+      int count = tokenToOffsets.size();\r
+      for (final int[] offsets : tokenToOffsets.values()) {\r
+        count += offsets.length;\r
+      }\r
+      return count;\r
+    }\r
 \r
-    public Object getDescendant(final int position) throws IOException {\r
-      if (position < getDescendantCount()) {\r
-        return null;\r
+    public Object getDescendant(int position) throws IOException {\r
+      assert position < getDescendantCount(); \r
+\r
+//      System.out.println("getD: " + this + ", " + position);\r
+      if (position < getThisCount()) {\r
+        for (final Map.Entry<String, int[]> tokenEntry : tokenToOffsets.entrySet()) {\r
+          if (position == 0) {\r
+            return tokenEntry.getKey();\r
+          }\r
+          --position;\r
+          if (position < tokenEntry.getValue().length) {\r
+            return tokenEntry.getValue()[position];\r
+          }\r
+          position -= tokenEntry.getValue().length;\r
+        }\r
+        assert false;\r
       }\r
+      position -= getThisCount();\r
+      \r
+      \r
       for (final Map.Entry<String,NodeHandle> childEntry : children.entrySet()) {\r
         final Node child = childEntry.getValue().getNode();\r
         if (position < child.getDescendantCount()) {\r
-          \r
-        } else {\r
-          position -= child.getDescendantCount();\r
+          return child.getDescendant(position);\r
         }\r
+        position -= child.getDescendantCount();\r
       }\r
+      assert false;\r
+      return null;\r
     }\r
 \r
     public void getDescendantEntryOffsets(final Set<Integer> entryOffsets, int maxSize) throws IOException {\r