+ try {
+ if (dictRaf == null) {
+ dictFileTitleName = application.getDictionaryName(dictFile.getName());
+ dictRaf = new RandomAccessFile(dictFile, "r").getChannel();
+ }
+ this.setTitle("QuickDic: " + dictFileTitleName);
+ dictionary = new Dictionary(dictRaf);
+ } catch (Exception e) {
+ dictionaryOpenFail(e);
+ return;
+ }
+ String targetIndex = intent.getStringExtra(C.INDEX_SHORT_NAME);
+ if (savedInstanceState != null && savedInstanceState.getString(C.INDEX_SHORT_NAME) != null) {
+ targetIndex = savedInstanceState.getString(C.INDEX_SHORT_NAME);
+ }
+ indexIndex = 0;
+ for (int i = 0; i < dictionary.indices.size(); ++i) {
+ if (dictionary.indices.get(i).shortName.equals(targetIndex)) {
+ indexIndex = i;
+ break;
+ }
+ }
+ Log.d(LOG, "Loading index " + indexIndex);
+ index = dictionary.indices.get(indexIndex);
+ getListView().setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+ getListView().setEmptyView(findViewById(android.R.id.empty));
+ getListView().setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int row, long id) {
+ onListItemClick(getListView(), view, row, id);
+ }
+ });
+
+ setListAdapter(new IndexAdapter(index));
+
+ // Pre-load the Transliterator (will spawn its own thread)
+ TransliteratorManager.init(new TransliteratorManager.Callback() {
+ @Override
+ public void onTransliteratorReady() {
+ uiHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ onSearchTextChange(searchView.getQuery().toString());
+ }
+ });
+ }
+ }, DictionaryApplication.threadBackground);
+
+ // Pre-load the collators.
+ new Thread(new Runnable() {
+ public void run() {
+ android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
+ final long startMillis = System.currentTimeMillis();
+ try {
+ for (final Index index : dictionary.indices) {
+ final String searchToken = index.sortedIndexEntries.get(0).token;
+ final IndexEntry entry = index.findExact(searchToken);
+ if (entry == null || !searchToken.equals(entry.token)) {
+ Log.e(LOG, "Couldn't find token: " + searchToken + ", " + (entry == null ? "null" : entry.token));
+ }
+ }
+ indexPrepFinished = true;
+ } catch (Exception e) {
+ Log.w(LOG,
+ "Exception while prepping. This can happen if dictionary is closed while search is happening.");
+ }
+ Log.d(LOG, "Prepping indices took:" + (System.currentTimeMillis() - startMillis));
+ }
+ }).start();
+
+ String fontName = prefs.getString(getString(R.string.fontKey), "FreeSerif.otf.jpg");
+ switch (fontName) {
+ case "SYSTEM":
+ typeface = Typeface.DEFAULT;
+ break;
+ case "SERIF":
+ typeface = Typeface.SERIF;
+ break;
+ case "SANS_SERIF":
+ typeface = Typeface.SANS_SERIF;
+ break;
+ case "MONOSPACE":
+ typeface = Typeface.MONOSPACE;
+ break;
+ default:
+ if ("FreeSerif.ttf.jpg".equals(fontName)) {
+ fontName = "FreeSerif.otf.jpg";
+ }
+ try {
+ typeface = Typeface.createFromAsset(getAssets(), fontName);
+ } catch (Exception e) {
+ Log.w(LOG, "Exception trying to use typeface, using default.", e);
+ if (!isFinishing())
+ Toast.makeText(this, getString(R.string.fontFailure, e.getLocalizedMessage()),
+ Toast.LENGTH_LONG).show();
+ }
+ break;
+ }
+ if (typeface == null) {
+ Log.w(LOG, "Unable to create typeface, using default.");
+ typeface = Typeface.DEFAULT;
+ }
+ final String fontSize = prefs.getString(getString(R.string.fontSizeKey), "14");
+ try {
+ fontSizeSp = Integer.parseInt(fontSize.trim());
+ } catch (NumberFormatException e) {
+ fontSizeSp = 14;
+ }
+
+ // ContextMenu.
+ registerForContextMenu(getListView());
+
+ // Cache some prefs.
+ wordList = application.getWordListFile();
+ saveOnlyFirstSubentry = prefs.getBoolean(getString(R.string.saveOnlyFirstSubentryKey),
+ false);
+ clickOpensContextMenu = prefs.getBoolean(getString(R.string.clickOpensContextMenuKey),
+ !getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN));
+ Log.d(LOG, "wordList=" + wordList + ", saveOnlyFirstSubentry=" + saveOnlyFirstSubentry);
+
+ onCreateSetupActionBarAndSearchView();
+
+ View floatSwapButton = findViewById(R.id.floatSwapButton);
+ floatSwapButton.setOnLongClickListener(new OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ onLanguageButtonLongClick(v.getContext());
+ return true;
+ }
+ });
+
+ // Set the search text from the intent, then the saved state.
+ String text = getIntent().getStringExtra(C.SEARCH_TOKEN);
+ if (savedInstanceState != null) {
+ text = savedInstanceState.getString(C.SEARCH_TOKEN);
+ }
+ if (text == null) {
+ text = "";
+ }
+
+ searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
+ @Override
+ public boolean onSuggestionSelect(int position) {
+ return false;
+ }
+
+ @Override
+ public boolean onSuggestionClick(int position) {
+ setSearchText(searchHistory.get(position), true);
+ return true;
+ }
+ });
+ searchView.setSuggestionsAdapter(new CursorAdapter(this, text.isEmpty() ? searchHistoryCursor : null, 0) {
+ @Override
+ public View newView(Context context, Cursor c, ViewGroup p) {
+ TextView v = new TextView(context);
+ v.setTextColor(textColorFg);
+ v.setTypeface(typeface);
+ v.setTextSize(TypedValue.COMPLEX_UNIT_SP, 4 * fontSizeSp / 3);
+ return v;
+ }
+ @Override
+ public void bindView(View v, Context context, Cursor c) {
+ TextView t = (TextView)v;
+ t.setText(c.getString(1));
+ }
+ });
+ // Set up search history
+ addToSearchHistory(text);
+
+ setSearchText(text, true);
+ Log.d(LOG, "Trying to restore searchText=" + text);
+
+ setDictionaryPrefs(this, dictFile, index.shortName);
+
+ updateLangButton();
+ searchView.requestFocus();
+
+ // http://stackoverflow.com/questions/2833057/background-listview-becomes-black-when-scrolling
+// getListView().setCacheColorHint(0);
+ }
+
+ private void onCreateSetupActionBarAndSearchView() {
+ ActionBar actionBar = getSupportActionBar();
+ actionBar.setDisplayShowTitleEnabled(false);
+ actionBar.setDisplayShowHomeEnabled(false);
+ actionBar.setDisplayHomeAsUpEnabled(false);
+
+ final LinearLayout customSearchView = new LinearLayout(getSupportActionBar().getThemedContext());
+
+ final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ customSearchView.setLayoutParams(layoutParams);
+
+ languageButton = new ImageButton(customSearchView.getContext());
+ languageButton.setId(R.id.languageButton);
+ languageButton.setScaleType(ScaleType.FIT_CENTER);
+ languageButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onLanguageButtonLongClick(v.getContext());
+ }
+ });
+ languageButton.setAdjustViewBounds(true);
+ LinearLayout.LayoutParams lpb = new LinearLayout.LayoutParams(application.languageButtonPixels, LinearLayout.LayoutParams.MATCH_PARENT);
+ customSearchView.addView(languageButton, lpb);
+
+ searchView = new SearchView(getSupportActionBar().getThemedContext());
+ searchView.setId(R.id.searchView);
+
+ // Get rid of search icon, it takes up too much space.
+ // There is still text saying "search" in the search field.
+ searchView.setIconifiedByDefault(true);
+ searchView.setIconified(false);
+
+ searchView.setQueryHint(getString(R.string.searchText));
+ searchView.setSubmitButtonEnabled(false);
+ searchView.setInputType(InputType.TYPE_CLASS_TEXT);
+ searchView.setImeOptions(
+ EditorInfo.IME_ACTION_DONE |
+ EditorInfo.IME_FLAG_NO_EXTRACT_UI |
+ // EditorInfo.IME_FLAG_NO_FULLSCREEN | // Requires API
+ // 11
+ EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+ onQueryTextListener = new OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ Log.d(LOG, "OnQueryTextListener: onQueryTextSubmit: " + searchView.getQuery());
+ addToSearchHistory(searchView.getQuery().toString());
+ hideKeyboard();
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ Log.d(LOG, "OnQueryTextListener: onQueryTextChange: " + searchView.getQuery());
+ onSearchTextChange(searchView.getQuery().toString());
+ return true;
+ }
+ };
+ searchView.setOnQueryTextListener(onQueryTextListener);
+ searchView.setFocusable(true);
+ searchTextView = (AutoCompleteTextView)searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0,
+ FrameLayout.LayoutParams.WRAP_CONTENT, 1);
+ customSearchView.addView(searchView, lp);
+
+ actionBar.setCustomView(customSearchView);
+ actionBar.setDisplayShowCustomEnabled(true);
+
+ // Avoid wasting space on large left inset
+ Toolbar tb = (Toolbar)customSearchView.getParent();
+ tb.setContentInsetsRelative(0, 0);
+
+ getListView().setNextFocusLeftId(R.id.searchView);
+ findViewById(R.id.floatSwapButton).setNextFocusRightId(R.id.languageButton);
+ languageButton.setNextFocusLeftId(R.id.floatSwapButton);
+ }
+
+ @Override
+ protected void onResume() {
+ Log.d(LOG, "onResume");
+ super.onResume();
+ if (PreferenceActivity.prefsMightHaveChanged) {
+ PreferenceActivity.prefsMightHaveChanged = false;
+ finish();
+ startActivity(getIntent());
+ }
+ showKeyboard();
+ }
+
+ /**
+ * Invoked when MyWebView returns, since the user might have clicked some
+ * hypertext in the MyWebView.
+ */
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent result) {
+ super.onActivityResult(requestCode, resultCode, result);
+ if (result != null && result.hasExtra(C.SEARCH_TOKEN)) {
+ Log.d(LOG, "onActivityResult: " + result.getStringExtra(C.SEARCH_TOKEN));
+ jumpToTextFromHyperLink(result.getStringExtra(C.SEARCH_TOKEN), indexIndex);
+ }
+ }
+
+ private static void setDictionaryPrefs(final Context context, final File dictFile,
+ final String indexShortName) {
+ final SharedPreferences.Editor prefs = PreferenceManager.getDefaultSharedPreferences(
+ context).edit();
+ if (dictFile != null) {
+ prefs.putString(C.DICT_FILE, dictFile.getPath());
+ prefs.putString(C.INDEX_SHORT_NAME, indexShortName);
+ }
+ prefs.remove(C.SEARCH_TOKEN); // Don't need to save search token.
+ prefs.commit();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (dictRaf == null) {
+ return;
+ }
+
+ final SearchOperation searchOperation = currentSearchOperation;
+ currentSearchOperation = null;
+
+ // Before we close the RAF, we have to wind the current search down.
+ if (searchOperation != null) {
+ Log.d(LOG, "Interrupting search to shut down.");
+ currentSearchOperation = null;
+ searchOperation.interrupted.set(true);
+ }
+ searchExecutor.shutdownNow();
+ textToSpeech.shutdown();
+ textToSpeech = null;
+
+ indexAdapter = null;
+ setListAdapter(null);
+
+ try {
+ Log.d(LOG, "Closing RAF.");
+ dictRaf.close();
+ } catch (IOException e) {
+ Log.e(LOG, "Failed to close dictionary", e);
+ }
+ dictRaf = null;
+ }
+
+ // --------------------------------------------------------------------------
+ // Buttons
+ // --------------------------------------------------------------------------
+
+ private void showKeyboard() {
+ // For some reason, this doesn't always work the first time.
+ // One way to replicate the problem:
+ // Press the "task switch" button repeatedly to pause and resume
+ for (int delay = 1; delay <= 101; delay += 100) {
+ searchView.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ Log.d(LOG, "Trying to show soft keyboard.");
+ final boolean searchTextHadFocus = searchView.hasFocus();
+ searchView.requestFocusFromTouch();
+ searchTextView.requestFocus();
+ final InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ manager.showSoftInput(searchView, InputMethodManager.SHOW_IMPLICIT);
+ manager.showSoftInput(searchTextView, InputMethodManager.SHOW_IMPLICIT);
+ if (!searchTextHadFocus) {
+ defocusSearchText();
+ }
+ }
+ }, delay);
+ }
+ searchView.post(new Runnable() {
+ @Override
+ public void run() {
+ searchTextView.setThreshold(0);
+ searchTextView.showDropDown();
+ }
+ });
+ }
+
+ private void hideKeyboard() {
+ Log.d(LOG, "Hide soft keyboard.");
+ searchView.clearFocus();
+ InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ manager.hideSoftInputFromWindow(searchView.getWindowToken(), 0);
+ }