]> gitweb.fperrin.net Git - Dictionary.git/blob - src/com/hughes/android/dictionary/Dictionary.java
go
[Dictionary.git] / src / com / hughes / android / dictionary / Dictionary.java
1 package com.hughes.android.dictionary;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.RandomAccessFile;
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.LinkedHashSet;
9 import java.util.List;
10 import java.util.Set;
11 import java.util.concurrent.Executor;
12 import java.util.concurrent.Executors;
13 import java.util.concurrent.atomic.AtomicBoolean;
14
15 import android.app.Activity;
16 import android.os.Bundle;
17 import android.os.Handler;
18 import android.text.Editable;
19 import android.text.TextWatcher;
20 import android.util.Log;
21 import android.view.View;
22 import android.view.ViewGroup;
23 import android.widget.BaseAdapter;
24 import android.widget.EditText;
25 import android.widget.ListView;
26 import android.widget.TextView;
27
28 import com.hughes.util.FileUtil;
29
30 public class Dictionary extends Activity {
31
32   public static final String INDEX_FORMAT = "%s_index_%d";
33   private File dictionaryFile = new File("/sdcard/dict-de-en.txt");
34
35   private RandomAccessFile dictionaryRaf;
36   private final Index[] indexes = new Index[2];
37   private final byte lang = Entry.LANG1;
38   
39   final Handler uiHandler = new Handler();
40
41   private final Object mutex = new Object();
42   private Executor searchExecutor = Executors.newSingleThreadExecutor();
43   private SearchOperation searchOperation = null;
44   private List<Entry> entries = Collections.emptyList();
45   private DictionaryListAdapter dictionaryListAdapter = new DictionaryListAdapter();
46
47   /** Called when the activity is first created. */
48   @Override
49   public void onCreate(Bundle savedInstanceState) {
50     Log.d("THAD", "onCreate");
51     super.onCreate(savedInstanceState);
52     setContentView(R.layout.main);
53
54     EditText searchText = (EditText) findViewById(R.id.SearchText);
55     searchText.addTextChangedListener(new DictionaryTextWatcher());
56
57     ListView searchResults = (ListView) findViewById(R.id.SearchResults);
58     searchResults.setAdapter(dictionaryListAdapter);
59     try {
60       loadIndex();
61     } catch (Exception e) {
62       throw new RuntimeException(e);
63     }
64     onSearchTextChange("");
65   }
66
67   private void loadIndex() throws IOException, ClassNotFoundException {
68     Log.d("THAD", "enter loadIndex");
69     indexes[0] = new Index(String.format(INDEX_FORMAT, dictionaryFile
70         .getAbsolutePath(), Entry.LANG1));
71     dictionaryRaf = new RandomAccessFile(dictionaryFile, "r");
72     Log.d("THAD", "exit loadIndex");
73   }
74
75   void onSearchTextChange(final String searchText) {
76     Log.d("THAD", "onSearchTextChange: " + searchText);
77     synchronized (mutex) {
78       if (searchOperation != null) {
79         searchOperation.interrupted.set(true);
80       }
81       searchOperation = new SearchOperation(searchText);
82     }
83     searchExecutor.execute(searchOperation);
84   }
85
86   private final class SearchOperation implements Runnable {
87     final String searchText;
88     final int count = 100;
89     final AtomicBoolean interrupted = new AtomicBoolean(false);
90     
91     public SearchOperation(final String searchText) {
92       this.searchText = searchText;
93     }
94     
95     public void run() {
96       Log.d("THAD", "SearchOperation: " + searchText);
97       final List<Entry> newEntries = new ArrayList<Entry>(count);
98       try {
99         final Index.Node node = indexes[lang].lookup(searchText);
100         final Set<Integer> entryOffsets = new LinkedHashSet<Integer>(count);
101         node.getDescendantEntryOffsets(entryOffsets, count);
102         for (final int entryOffset : entryOffsets) {
103           if (interrupted.get()) {
104             Log.d("THAD", "Interrupted while parsing entries.");
105             return;
106           }
107           final String line = FileUtil.readLine(dictionaryRaf, entryOffset);
108           final Entry entry = new Entry(line);
109           newEntries.add(entry);
110         }
111       } catch (IOException e) {
112         Log.e("THAD", "Search failure.", e);
113       }
114
115       synchronized (mutex) {
116         if (interrupted.get()) {
117           return;
118         }
119         entries = newEntries;
120       }
121       
122       uiHandler.post(new Runnable() {
123         public void run() {
124           synchronized (mutex) {
125             dictionaryListAdapter.notifyDataSetChanged();
126           }
127         }});
128     }
129   }
130
131   private class DictionaryListAdapter extends BaseAdapter {
132
133     public int getCount() {
134       synchronized (mutex) {
135         return entries.size();
136       }
137     }
138
139     public Object getItem(int position) {
140       synchronized (mutex) {
141         assert position < entries.size();
142         return entries.get(position).getFormattedEntry(lang);
143       }
144     }
145
146     public long getItemId(int position) {
147       return position;
148     }
149
150     public View getView(int position, View convertView, ViewGroup parent) {
151       TextView result = null;
152       if (convertView instanceof TextView) {
153         result = (TextView) convertView;
154       } else {
155         result = new TextView(parent.getContext());
156       }
157       result.setText((String) getItem(position));
158       return result;
159     }
160
161   }
162
163   private class DictionaryTextWatcher implements TextWatcher {
164     public void afterTextChanged(Editable searchText) {
165       onSearchTextChange(searchText.toString());
166     }
167
168     public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
169         int arg3) {
170     }
171
172     public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
173     }
174   }
175
176   public void run() {
177     // TODO Auto-generated method stub
178
179   }
180
181 }