]> gitweb.fperrin.net Git - Dictionary.git/blob - src/com/hughes/android/dictionary/DictionaryActivity.java
go
[Dictionary.git] / src / com / hughes / android / dictionary / DictionaryActivity.java
1 package com.hughes.android.dictionary;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6 import java.io.OutputStream;
7 import java.io.RandomAccessFile;
8 import java.util.concurrent.Executor;
9 import java.util.concurrent.Executors;
10 import java.util.concurrent.atomic.AtomicBoolean;
11
12 import android.app.ListActivity;
13 import android.graphics.Color;
14 import android.os.Bundle;
15 import android.os.Handler;
16 import android.text.Editable;
17 import android.text.TextWatcher;
18 import android.util.Log;
19 import android.view.ContextMenu;
20 import android.view.KeyEvent;
21 import android.view.Menu;
22 import android.view.MenuItem;
23 import android.view.View;
24 import android.view.ViewGroup;
25 import android.view.ContextMenu.ContextMenuInfo;
26 import android.view.MenuItem.OnMenuItemClickListener;
27 import android.view.View.OnClickListener;
28 import android.widget.AdapterView;
29 import android.widget.BaseAdapter;
30 import android.widget.Button;
31 import android.widget.EditText;
32 import android.widget.ListView;
33 import android.widget.TableLayout;
34 import android.widget.TableRow;
35 import android.widget.TextView;
36 import android.widget.AdapterView.OnItemLongClickListener;
37 import android.widget.AdapterView.OnItemSelectedListener;
38
39 import com.hughes.android.dictionary.Dictionary.IndexEntry;
40 import com.hughes.android.dictionary.Dictionary.LanguageData;
41 import com.hughes.android.dictionary.Dictionary.Row;
42
43 public class DictionaryActivity extends ListActivity {
44
45   private RandomAccessFile dictRaf = null;
46   private Dictionary dictionary = null;
47   private LanguageData activeLangaugeData = null;
48
49   private File wordList = new File("/sdcard/wordList.txt");
50
51   final Handler uiHandler = new Handler();
52
53   private Executor searchExecutor = Executors.newSingleThreadExecutor();
54   private SearchOperation searchOperation = null;
55   // private List<Entry> entries = Collections.emptyList();
56   private DictionaryListAdapter dictionaryListAdapter = new DictionaryListAdapter();
57   private int selectedRowIndex = -1;
58   private int selectedTokenRowIndex = -1;
59
60   /** Called when the activity is first created. */
61   @Override
62   public void onCreate(Bundle savedInstanceState) {
63     Log.d("THAD", "onCreate");
64     super.onCreate(savedInstanceState);
65
66     try {
67       dictRaf = new RandomAccessFile("/sdcard/de-en.dict", "r");
68       dictionary = new Dictionary(dictRaf);
69       activeLangaugeData = dictionary.languageDatas[Entry.LANG1];
70     } catch (Exception e) {
71       throw new RuntimeException(e);
72     }
73
74     setContentView(R.layout.main);
75
76     final EditText searchText = (EditText) findViewById(R.id.SearchText);
77     searchText.addTextChangedListener(new DictionaryTextWatcher());
78
79     setListAdapter(dictionaryListAdapter);
80
81     onSearchTextChange("");
82     
83     // Language button.
84     final Button langButton = (Button) findViewById(R.id.LangButton);
85     langButton.setOnClickListener(new OnClickListener() {
86       public void onClick(View v) {
87         switchLanguage();
88       }});
89     updateLangButton();
90
91     final Button upButton = (Button) findViewById(R.id.UpButton);
92     upButton.setOnClickListener(new OnClickListener() {
93       public void onClick(View v) {
94         final int destRowIndex;
95         final Row tokenRow = activeLangaugeData.rows.get(selectedTokenRowIndex);
96         assert tokenRow.isToken();
97         final int prevTokenIndex = tokenRow.getIndex() - 1;
98         if (selectedRowIndex == selectedTokenRowIndex && selectedRowIndex > 0) {
99           destRowIndex = activeLangaugeData.sortedIndex.get(prevTokenIndex).startRow;
100         } else {
101           destRowIndex = selectedTokenRowIndex;
102         }
103         jumpToRow(destRowIndex);
104       }});
105     final Button downButton = (Button) findViewById(R.id.DownButton);
106     downButton.setOnClickListener(new OnClickListener() {
107       public void onClick(View v) {
108         final Row tokenRow = activeLangaugeData.rows.get(selectedTokenRowIndex);
109         assert tokenRow.isToken();
110         final int nextTokenIndex = tokenRow.getIndex() + 1;
111         final int destRowIndex;
112         if (nextTokenIndex < activeLangaugeData.sortedIndex.size()) {
113           destRowIndex = activeLangaugeData.sortedIndex.get(nextTokenIndex).startRow;
114         } else {
115           destRowIndex = activeLangaugeData.rows.size() - 1;
116         }
117         jumpToRow(destRowIndex);
118       }});
119
120     // Context menu.
121     registerForContextMenu(getListView());
122     
123     getListView().setOnItemSelectedListener(new OnItemSelectedListener() {
124       public void onItemSelected(AdapterView<?> arg0, View arg1, int rowIndex,
125           long arg3) {
126         Log.d("THAD", "onItemSelected: " + rowIndex);
127         selectedRowIndex = rowIndex;
128         selectedTokenRowIndex = activeLangaugeData.getTokenRow(rowIndex);
129         updateSearchText();
130       }
131
132       public void onNothingSelected(AdapterView<?> arg0) {
133       }});
134     
135     
136     getListView().setOnItemLongClickListener((new OnItemLongClickListener() {
137       public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int rowIndex,
138           long arg3) {
139         selectedRowIndex = rowIndex;
140         return false;
141       }
142     }));
143   }
144   
145   public String getSelectedRowText() {
146     return activeLangaugeData.rowToString(activeLangaugeData.rows.get(selectedRowIndex));
147   }
148
149   private MenuItem switchLanguageMenuItem = null;
150   
151   @Override
152   public boolean onCreateOptionsMenu(final Menu menu) {
153     switchLanguageMenuItem = menu.add("Switch to language.");
154     return true;
155   }
156   
157   @Override
158   public boolean onPrepareOptionsMenu(final Menu menu) {
159     switchLanguageMenuItem.setTitle(String.format("Switch to %s", dictionary.languageDatas[Entry.otherLang(activeLangaugeData.lang)].language.symbol));
160     return super.onPrepareOptionsMenu(menu);
161   }
162   
163   @Override
164   public boolean onOptionsItemSelected(final MenuItem item) {
165     if (item == switchLanguageMenuItem) {
166       switchLanguage();
167     }
168     return super.onOptionsItemSelected(item);
169   }
170
171   @Override
172   public void onCreateContextMenu(ContextMenu menu, View v,
173       ContextMenuInfo menuInfo) {
174     if (selectedRowIndex == -1) {
175       return;
176     }
177     final MenuItem addToWordlist = menu.add("Add to wordlist.");
178     addToWordlist.setOnMenuItemClickListener(new OnMenuItemClickListener() {
179       public boolean onMenuItemClick(MenuItem item) {
180         final String rawText = getSelectedRowText();
181         Log.d("THAD", "Writing : " + rawText);
182         try {
183           final OutputStream out = new FileOutputStream(wordList, true);
184           out.write((rawText + "\n").getBytes());
185           out.close();
186         } catch (IOException e) {
187           throw new RuntimeException(e);
188         }
189         return false;
190       }
191     });
192   }
193   
194   void switchLanguage() {
195     activeLangaugeData = dictionary.languageDatas[(activeLangaugeData == dictionary.languageDatas[0]) ? 1 : 0];
196     updateLangButton();
197     dictionaryListAdapter.notifyDataSetChanged();
198     final EditText searchText = (EditText) findViewById(R.id.SearchText);
199     onSearchTextChange(searchText.getText().toString());
200   }
201   
202   void updateLangButton() {
203     final Button langButton = (Button) findViewById(R.id.LangButton);
204     langButton.setText(activeLangaugeData.language.symbol);
205   }
206   
207   @Override
208   public boolean onKeyDown(int keyCode, KeyEvent event) {
209     if (event.getUnicodeChar() != 0) {
210       final EditText searchText = (EditText) findViewById(R.id.SearchText);
211       if (!searchText.hasFocus()) {
212         searchText.setText("" + (char)event.getUnicodeChar());
213         onSearchTextChange(searchText.getText().toString());
214         searchText.requestFocus();
215       }
216       return true;
217     }
218     return super.onKeyDown(keyCode, event);
219   }
220
221   @Override
222   protected void onListItemClick(ListView l, View v, int row, long id) {
223     selectedRowIndex = row;
224     Log.d("THAD", "Clicked: " + getSelectedRowText());
225     openContextMenu(getListView());
226   }
227
228   void onSearchTextChange(final String searchText) {
229     Log.d("THAD", "onSearchTextChange: " + searchText);
230     if (searchOperation != null) {
231       searchOperation.interrupted.set(true);
232     }
233     searchOperation = new SearchOperation(searchText);
234     searchExecutor.execute(searchOperation);
235   }
236   
237   private void jumpToRow(final int rowIndex) {
238     selectedRowIndex = rowIndex;
239     selectedTokenRowIndex = activeLangaugeData.getTokenRow(rowIndex);
240     getListView().setSelection(rowIndex);
241     getListView().setSelected(true);
242     updateSearchText();
243   }
244
245   private void updateSearchText() {
246     final EditText searchText = (EditText) findViewById(R.id.SearchText);
247     if (!searchText.hasFocus()) {
248       searchText.setText(activeLangaugeData.rowToString(activeLangaugeData.rows.get(selectedTokenRowIndex)));
249     }
250   }
251
252   private final class SearchOperation implements Runnable {
253     final String searchText;
254     final AtomicBoolean interrupted = new AtomicBoolean(false);
255
256     public SearchOperation(final String searchText) {
257       this.searchText = searchText;
258     }
259
260     public void run() {
261       Log.d("THAD", "SearchOperation: " + searchText);
262       final int indexLocation = activeLangaugeData.lookup(searchText, interrupted);
263       if (interrupted.get()) {
264         return;
265       }
266       final IndexEntry indexEntry = activeLangaugeData.sortedIndex
267           .get(indexLocation);
268       uiHandler.post(new Runnable() {
269         public void run() {
270           jumpToRow(indexEntry.startRow);
271         }
272       });
273     }
274   }
275
276   private class DictionaryListAdapter extends BaseAdapter {
277
278     public int getCount() {
279       return activeLangaugeData.rows.size();
280     }
281
282     public Dictionary.Row getItem(int rowIndex) {
283       assert rowIndex < activeLangaugeData.rows.size();
284       return activeLangaugeData.rows.get(rowIndex);
285     }
286
287     public long getItemId(int rowIndex) {
288       return rowIndex;
289     }
290
291     public View getView(final int rowIndex, final View convertView,
292         final ViewGroup parent) {
293       final Row row = getItem(rowIndex);
294       
295       // Token row.
296       if (row.isToken()) {
297         TextView result = null;
298         if (convertView instanceof TextView) {
299           result = (TextView) convertView;
300         } else {
301           result = new TextView(parent.getContext());
302         }
303 //        result.setBackgroundColor(Color.WHITE);
304         result.setText(activeLangaugeData.rowToString(row));
305         result.setTextAppearance(parent.getContext(),
306             android.R.style.TextAppearance_Large);
307         return result;
308       }
309
310       // Entry row(s).
311       final TableLayout result = new TableLayout(parent.getContext());
312
313       final Entry entry = dictionary.entries.get(row.getIndex());
314       final int rowCount = entry.getRowCount();
315       for (int r = 0; r < rowCount; ++r) {
316         final TableRow tableRow = new TableRow(result.getContext());
317 //        if (r > 0) {
318 //          tableRow.setBackgroundColor(Color.DKGRAY);  
319 //        }
320         
321         TextView column1 = new TextView(tableRow.getContext());
322         TextView column2 = new TextView(tableRow.getContext());
323         final TableRow.LayoutParams layoutParams = new TableRow.LayoutParams();
324         layoutParams.weight = 0.5f;
325         
326         if (r>0){
327           final TextView spacer = new TextView(tableRow.getContext());
328           spacer.setText(r == 0 ? "\95 " : " \95 ");
329           tableRow.addView(spacer);
330         }
331         tableRow.addView(column1, layoutParams);
332         if (r>0){
333           final TextView spacer = new TextView(tableRow.getContext());
334           spacer.setText(r == 0 ? "\95 " : " \95 ");
335           tableRow.addView(spacer);
336         }
337         tableRow.addView(column2, layoutParams);
338         
339         column1.setWidth(1);
340         column2.setWidth(1);
341         // column1.setTextAppearance(parent.getContext(), android.R.style.Text);
342         
343         // TODO: highlight query word in entries.
344         column1.setText(entry.getAllText(activeLangaugeData.lang)[r]);
345         column2.setText(entry.getAllText(Entry.otherLang(activeLangaugeData.lang))[r]);
346         
347         result.addView(tableRow);
348       }
349       
350       return result;
351     }
352   }  // DictionaryListAdapter
353
354   private class DictionaryTextWatcher implements TextWatcher {
355     public void afterTextChanged(Editable searchText) {
356       onSearchTextChange(searchText.toString());
357     }
358
359     public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
360         int arg3) {
361     }
362
363     public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
364     }
365   }
366
367 }