1 package com.hughes.android.dictionary;
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;
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;
39 import com.hughes.android.dictionary.Dictionary.IndexEntry;
40 import com.hughes.android.dictionary.Dictionary.LanguageData;
41 import com.hughes.android.dictionary.Dictionary.Row;
43 public class DictionaryActivity extends ListActivity {
45 private RandomAccessFile dictRaf = null;
46 private Dictionary dictionary = null;
47 private LanguageData activeLangaugeData = null;
49 private File wordList = new File("/sdcard/wordList.txt");
51 final Handler uiHandler = new Handler();
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;
60 /** Called when the activity is first created. */
62 public void onCreate(Bundle savedInstanceState) {
63 Log.d("THAD", "onCreate");
64 super.onCreate(savedInstanceState);
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);
74 setContentView(R.layout.main);
76 final EditText searchText = (EditText) findViewById(R.id.SearchText);
77 searchText.addTextChangedListener(new DictionaryTextWatcher());
79 setListAdapter(dictionaryListAdapter);
81 onSearchTextChange("");
84 final Button langButton = (Button) findViewById(R.id.LangButton);
85 langButton.setOnClickListener(new OnClickListener() {
86 public void onClick(View v) {
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;
101 destRowIndex = selectedTokenRowIndex;
103 jumpToRow(destRowIndex);
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;
115 destRowIndex = activeLangaugeData.rows.size() - 1;
117 jumpToRow(destRowIndex);
121 registerForContextMenu(getListView());
123 getListView().setOnItemSelectedListener(new OnItemSelectedListener() {
124 public void onItemSelected(AdapterView<?> arg0, View arg1, int rowIndex,
126 Log.d("THAD", "onItemSelected: " + rowIndex);
127 selectedRowIndex = rowIndex;
128 selectedTokenRowIndex = activeLangaugeData.getTokenRow(rowIndex);
132 public void onNothingSelected(AdapterView<?> arg0) {
136 getListView().setOnItemLongClickListener((new OnItemLongClickListener() {
137 public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int rowIndex,
139 selectedRowIndex = rowIndex;
145 public String getSelectedRowText() {
146 return activeLangaugeData.rowToString(activeLangaugeData.rows.get(selectedRowIndex));
149 private MenuItem switchLanguageMenuItem = null;
152 public boolean onCreateOptionsMenu(final Menu menu) {
153 switchLanguageMenuItem = menu.add("Switch to language.");
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);
164 public boolean onOptionsItemSelected(final MenuItem item) {
165 if (item == switchLanguageMenuItem) {
168 return super.onOptionsItemSelected(item);
172 public void onCreateContextMenu(ContextMenu menu, View v,
173 ContextMenuInfo menuInfo) {
174 if (selectedRowIndex == -1) {
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);
183 final OutputStream out = new FileOutputStream(wordList, true);
184 out.write((rawText + "\n").getBytes());
186 } catch (IOException e) {
187 throw new RuntimeException(e);
194 void switchLanguage() {
195 activeLangaugeData = dictionary.languageDatas[(activeLangaugeData == dictionary.languageDatas[0]) ? 1 : 0];
197 dictionaryListAdapter.notifyDataSetChanged();
198 final EditText searchText = (EditText) findViewById(R.id.SearchText);
199 onSearchTextChange(searchText.getText().toString());
202 void updateLangButton() {
203 final Button langButton = (Button) findViewById(R.id.LangButton);
204 langButton.setText(activeLangaugeData.language.symbol);
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();
218 return super.onKeyDown(keyCode, event);
222 protected void onListItemClick(ListView l, View v, int row, long id) {
223 selectedRowIndex = row;
224 Log.d("THAD", "Clicked: " + getSelectedRowText());
225 openContextMenu(getListView());
228 void onSearchTextChange(final String searchText) {
229 Log.d("THAD", "onSearchTextChange: " + searchText);
230 if (searchOperation != null) {
231 searchOperation.interrupted.set(true);
233 searchOperation = new SearchOperation(searchText);
234 searchExecutor.execute(searchOperation);
237 private void jumpToRow(final int rowIndex) {
238 selectedRowIndex = rowIndex;
239 selectedTokenRowIndex = activeLangaugeData.getTokenRow(rowIndex);
240 getListView().setSelection(rowIndex);
241 getListView().setSelected(true);
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)));
252 private final class SearchOperation implements Runnable {
253 final String searchText;
254 final AtomicBoolean interrupted = new AtomicBoolean(false);
256 public SearchOperation(final String searchText) {
257 this.searchText = searchText;
261 Log.d("THAD", "SearchOperation: " + searchText);
262 final int indexLocation = activeLangaugeData.lookup(searchText, interrupted);
263 if (interrupted.get()) {
266 final IndexEntry indexEntry = activeLangaugeData.sortedIndex
268 uiHandler.post(new Runnable() {
270 jumpToRow(indexEntry.startRow);
276 private class DictionaryListAdapter extends BaseAdapter {
278 public int getCount() {
279 return activeLangaugeData.rows.size();
282 public Dictionary.Row getItem(int rowIndex) {
283 assert rowIndex < activeLangaugeData.rows.size();
284 return activeLangaugeData.rows.get(rowIndex);
287 public long getItemId(int rowIndex) {
291 public View getView(final int rowIndex, final View convertView,
292 final ViewGroup parent) {
293 final Row row = getItem(rowIndex);
297 TextView result = null;
298 if (convertView instanceof TextView) {
299 result = (TextView) convertView;
301 result = new TextView(parent.getContext());
303 // result.setBackgroundColor(Color.WHITE);
304 result.setText(activeLangaugeData.rowToString(row));
305 result.setTextAppearance(parent.getContext(),
306 android.R.style.TextAppearance_Large);
311 final TableLayout result = new TableLayout(parent.getContext());
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());
318 // tableRow.setBackgroundColor(Color.DKGRAY);
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;
327 final TextView spacer = new TextView(tableRow.getContext());
328 spacer.setText(r == 0 ? "
\95 " : "
\95 ");
329 tableRow.addView(spacer);
331 tableRow.addView(column1, layoutParams);
333 final TextView spacer = new TextView(tableRow.getContext());
334 spacer.setText(r == 0 ? "
\95 " : "
\95 ");
335 tableRow.addView(spacer);
337 tableRow.addView(column2, layoutParams);
341 // column1.setTextAppearance(parent.getContext(), android.R.style.Text);
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]);
347 result.addView(tableRow);
352 } // DictionaryListAdapter
354 private class DictionaryTextWatcher implements TextWatcher {
355 public void afterTextChanged(Editable searchText) {
356 onSearchTextChange(searchText.toString());
359 public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
363 public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {