import java.io.PrintWriter;\r
import java.io.RandomAccessFile;\r
import java.text.SimpleDateFormat;\r
+import java.util.Arrays;\r
+import java.util.Collections;\r
import java.util.Date;\r
+import java.util.LinkedHashSet;\r
import java.util.List;\r
+import java.util.Set;\r
import java.util.concurrent.Executor;\r
import java.util.concurrent.Executors;\r
import java.util.concurrent.ThreadFactory;\r
import java.util.regex.Matcher;\r
import java.util.regex.Pattern;\r
\r
-import android.app.Activity;\r
import android.app.Dialog;\r
import android.app.ListActivity;\r
import android.content.Context;\r
import android.view.KeyEvent;\r
import android.view.Menu;\r
import android.view.MenuItem;\r
+import android.view.WindowManager;\r
import android.view.MenuItem.OnMenuItemClickListener;\r
import android.view.MotionEvent;\r
import android.view.View;\r
Dictionary dictionary = null;\r
int indexIndex = 0;\r
Index index = null;\r
+ List<RowBase> rowsToShow = null; // if not null, just show these rows.\r
\r
// package for test.\r
final Handler uiHandler = new Handler();\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
- Log.d(LOG, "onItemSelected: " + row.index());\r
- final TokenRow tokenRow = row.getTokenRow(true);\r
- searchText.setText(tokenRow.getToken());\r
+ if (!isFiltered()) {\r
+ final RowBase row = (RowBase) getListAdapter().getItem(position);\r
+ Log.d(LOG, "onItemSelected: " + row.index());\r
+ final TokenRow tokenRow = row.getTokenRow(true);\r
+ searchText.setText(tokenRow.getToken());\r
+ }\r
}\r
}\r
\r
searchText.requestFocus();\r
Log.d(LOG, "Trying to show soft keyboard.");\r
final InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);\r
- manager.showSoftInput(searchText, InputMethodManager.SHOW_FORCED);\r
+ manager.showSoftInput(searchText, InputMethodManager.SHOW_IMPLICIT);\r
}\r
\r
void updateLangButton() {\r
}\r
\r
void onUpDownButton(final boolean up) {\r
+ if (isFiltered()) {\r
+ return;\r
+ }\r
final int firstVisibleRow = getListView().getFirstVisiblePosition();\r
final RowBase row = index.rows.get(firstVisibleRow);\r
final TokenRow tokenRow = row.getTokenRow(true);\r
Log.d(LOG, "onUpDownButton, destIndexEntry=" + dest.token);\r
searchText.removeTextChangedListener(searchTextWatcher);\r
searchText.setText(dest.token);\r
+ Selection.moveToRightEdge(searchText.getText(), searchText.getLayout());\r
jumpToRow(index.sortedIndexEntries.get(destIndexEntry).startRow);\r
searchText.addTextChangedListener(searchTextWatcher);\r
}\r
});\r
}\r
\r
+ {\r
+ final MenuItem aboutDictionary = menu.add(getString(R.string.aboutDictionary));\r
+ aboutDictionary.setOnMenuItemClickListener(new OnMenuItemClickListener() {\r
+ public boolean onMenuItemClick(final MenuItem menuItem) {\r
+ final Context context = getListView().getContext();\r
+ final Dialog dialog = new Dialog(context);\r
+ dialog.setContentView(R.layout.about_dictionary_dialog);\r
+ final TextView textView = (TextView) dialog.findViewById(R.id.text);\r
+\r
+ final String name = application.getDictionaryName(dictFile.getName());\r
+ dialog.setTitle(name);\r
+ \r
+ final StringBuilder builder = new StringBuilder();\r
+ final DictionaryInfo dictionaryInfo = Dictionary.getDictionaryInfo(dictFile);\r
+ if (dictionaryInfo != null) {\r
+ builder.append(dictionaryInfo.dictInfo).append("\n\n");\r
+ builder.append(getString(R.string.dictionaryPath, dictFile.getPath())).append("\n");\r
+ builder.append(getString(R.string.dictionarySize, dictionaryInfo.uncompressedBytes)).append("\n");\r
+ builder.append(getString(R.string.dictionaryCreationTime, dictionaryInfo.creationMillis)).append("\n");\r
+ for (final IndexInfo indexInfo : dictionaryInfo.indexInfos) {\r
+ builder.append("\n");\r
+ builder.append(getString(R.string.indexName, indexInfo.shortName)).append("\n");\r
+ builder.append(getString(R.string.mainTokenCount, indexInfo.mainTokenCount)).append("\n");\r
+ }\r
+ } else {\r
+ builder.append(getString(R.string.invalidDictionary));\r
+ }\r
+ textView.setText(builder.toString());\r
+ \r
+ dialog.show();\r
+ final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();\r
+ layoutParams.width = WindowManager.LayoutParams.FILL_PARENT;\r
+ layoutParams.height = WindowManager.LayoutParams.FILL_PARENT;\r
+ dialog.getWindow().setAttributes(layoutParams);\r
+ return false;\r
+ }\r
+ });\r
+ }\r
+\r
return true;\r
}\r
\r
Log.d(LOG, "searchFinished: " + searchOperation + ", searchResult=" + searchResult);\r
\r
currentSearchOperation = null;\r
-\r
uiHandler.postDelayed(new Runnable() {\r
@Override\r
public void run() {\r
if (currentSearchOperation == null) {\r
- jumpToRow(searchResult.startRow);\r
+ if (searchResult != null) {\r
+ if (isFiltered()) {\r
+ clearFiltered();\r
+ }\r
+ jumpToRow(searchResult.startRow);\r
+ } else if (searchOperation.multiWordSearchResult != null) {\r
+ // Multi-row search....\r
+ setFiltered(searchOperation);\r
+ } else {\r
+ throw new IllegalStateException("This should never happen.");\r
+ }\r
} else {\r
Log.d(LOG, "More coming, waiting for currentSearchOperation.");\r
}\r
}\r
- }, 50);\r
- \r
-// if (!searchResult.success) {\r
-// if (vibrator != null) {\r
-// vibrator.vibrate(VIBRATE_MILLIS);\r
-// }\r
-// searchText.setText(searchResult.longestPrefixString);\r
-// searchText.setSelection(searchResult.longestPrefixString.length());\r
-// return;\r
-// }\r
+ }, 20);\r
\r
}\r
\r
getListView().setSelected(true);\r
}\r
\r
+ static final Pattern WHITESPACE = Pattern.compile("\\s+");\r
final class SearchOperation implements Runnable {\r
\r
final AtomicBoolean interrupted = new AtomicBoolean(false);\r
final String searchText;\r
+ List<String> searchTokens; // filled in for multiWord.\r
final Index index;\r
\r
long searchStartMillis;\r
\r
Index.IndexEntry searchResult;\r
+ List<RowBase> multiWordSearchResult;\r
\r
boolean done = false;\r
\r
public void run() {\r
try {\r
searchStartMillis = System.currentTimeMillis();\r
- searchResult = index.findInsertionPoint(searchText, interrupted);\r
+ final String[] searchTokenArray = WHITESPACE.split(searchText);\r
+ if (searchTokenArray.length == 1) {\r
+ searchResult = index.findInsertionPoint(searchText, interrupted);\r
+ } else {\r
+ searchTokens = Arrays.asList(searchTokenArray);\r
+ multiWordSearchResult = index.multiWordSearch(searchTokens, interrupted);\r
+ }\r
Log.d(LOG, "searchText=" + searchText + ", searchDuration="\r
+ (System.currentTimeMillis() - searchStartMillis) + ", interrupted="\r
+ interrupted.get());\r
final class IndexAdapter extends BaseAdapter {\r
\r
final Index index;\r
+ final List<RowBase> rows;\r
+ final Set<String> toHighlight;\r
\r
IndexAdapter(final Index index) {\r
this.index = index;\r
+ rows = index.rows;\r
+ this.toHighlight = null;\r
+ }\r
+\r
+ IndexAdapter(final Index index, final List<RowBase> rows, final List<String> toHighlight) {\r
+ this.index = index;\r
+ this.rows = rows;\r
+ this.toHighlight = new LinkedHashSet<String>(toHighlight);\r
}\r
\r
@Override\r
public int getCount() {\r
- return index.rows.size();\r
+ return rows.size();\r
}\r
\r
@Override\r
public RowBase getItem(int position) {\r
- return index.rows.get(position);\r
+ return rows.get(position);\r
}\r
\r
@Override\r
\r
@Override\r
public View getView(int position, final View convertView, ViewGroup parent) {\r
- final RowBase row = index.rows.get(position);\r
+ final RowBase row = getItem(position);\r
if (row instanceof PairEntry.Row) {\r
return getView(position, (PairEntry.Row) row, parent, convertView);\r
} else if (row instanceof TokenRow) {\r
col2.setText(col2Text, TextView.BufferType.SPANNABLE);\r
\r
// Bold the token instances in col1.\r
+ final Set<String> toBold = toHighlight != null ? this.toHighlight : Collections.singleton(row.getTokenRow(true).getToken());\r
final Spannable col1Spannable = (Spannable) col1.getText();\r
- int startPos = 0;\r
- final String token = row.getTokenRow(true).getToken();\r
- while ((startPos = col1Text.indexOf(token, startPos)) != -1) {\r
- col1Spannable.setSpan(new StyleSpan(Typeface.BOLD), startPos,\r
- startPos + token.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);\r
- startPos += token.length();\r
+ for (final String token : toBold) {\r
+ int startPos = 0;\r
+ while ((startPos = col1Text.indexOf(token, startPos)) != -1) {\r
+ col1Spannable.setSpan(new StyleSpan(Typeface.BOLD), startPos,\r
+ startPos + token.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);\r
+ startPos += token.length();\r
+ }\r
}\r
\r
createTokenLinkSpans(col1, col1Spannable, col1Text);\r
}\r
}\r
\r
+ // --------------------------------------------------------------------------\r
+ // Filtered results.\r
+ // --------------------------------------------------------------------------\r
+\r
+ boolean isFiltered() {\r
+ return rowsToShow != null;\r
+ }\r
+\r
+ void setFiltered(final SearchOperation searchOperation) {\r
+ ((Button) findViewById(R.id.UpButton)).setEnabled(false);\r
+ ((Button) findViewById(R.id.DownButton)).setEnabled(false);\r
+ rowsToShow = searchOperation.multiWordSearchResult;\r
+ setListAdapter(new IndexAdapter(index, rowsToShow, searchOperation.searchTokens));\r
+ }\r
+\r
+ void clearFiltered() {\r
+ ((Button) findViewById(R.id.UpButton)).setEnabled(true);\r
+ ((Button) findViewById(R.id.DownButton)).setEnabled(true);\r
+ setListAdapter(new IndexAdapter(index));\r
+ rowsToShow = null;\r
+ }\r
+\r
}\r