X-Git-Url: http://gitweb.fperrin.net/?a=blobdiff_plain;f=src%2Fcom%2Fhughes%2Fandroid%2Fdictionary%2FDictionaryActivity.java;h=8df2a2601ac2178b17503f1b96cf9076aff0dd7e;hb=5028fc2c15207ee98ff575ee257a5798e76d5b4f;hp=d2b4a923623fa4534151baca54ce25655b220604;hpb=e3a434becb9cc5e8bfa912a5241b66b6a24b65d1;p=Dictionary.git diff --git a/src/com/hughes/android/dictionary/DictionaryActivity.java b/src/com/hughes/android/dictionary/DictionaryActivity.java index d2b4a92..8df2a26 100644 --- a/src/com/hughes/android/dictionary/DictionaryActivity.java +++ b/src/com/hughes/android/dictionary/DictionaryActivity.java @@ -42,6 +42,7 @@ import android.text.Spannable; import android.text.method.LinkMovementMethod; import android.text.style.ClickableSpan; import android.text.style.StyleSpan; +import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.ContextMenu; @@ -98,6 +99,7 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collections; @@ -123,7 +125,8 @@ public class DictionaryActivity extends ActionBarActivity { DictionaryApplication application; File dictFile = null; - RandomAccessFile dictRaf = null; + FileChannel dictRaf = null; + String dictFileTitleName = null; Dictionary dictionary = null; @@ -223,12 +226,30 @@ public class DictionaryActivity extends ActionBarActivity { return search.length(); } + private void dictionaryOpenFail(Exception e) { + Log.e(LOG, "Unable to load dictionary.", e); + if (dictRaf != null) { + try { + dictRaf.close(); + } catch (IOException e1) { + Log.e(LOG, "Unable to close dictRaf.", e1); + } + dictRaf = null; + } + Toast.makeText(this, getString(R.string.invalidDictionary, "", e.getMessage()), + Toast.LENGTH_LONG).show(); + startActivity(DictionaryManagerActivity.getLaunchIntent(getApplicationContext())); + finish(); + } + @Override public void onCreate(Bundle savedInstanceState) { + DictionaryApplication.INSTANCE.init(getApplicationContext()); + application = DictionaryApplication.INSTANCE; // This needs to be before super.onCreate, otherwise ActionbarSherlock // doesn't makes the background of the actionbar white when you're // in the dark theme. - setTheme(((DictionaryApplication) getApplication()).getSelectedTheme().themeId); + setTheme(application.getSelectedTheme().themeId); Log.d(LOG, "onCreate:" + this); super.onCreate(savedInstanceState); @@ -240,10 +261,18 @@ public class DictionaryActivity extends ActionBarActivity { setContentView(R.layout.dictionary_activity); - application = (DictionaryApplication) getApplication(); theme = application.getSelectedTheme(); textColorFg = getResources().getColor(theme.tokenRowFgColor); + if (dictRaf != null) { + try { + dictRaf.close(); + } catch (IOException e) { + Log.e(LOG, "Failed to close dictionary", e); + } + dictRaf = null; + } + final Intent intent = getIntent(); String intentAction = intent.getAction(); /** @@ -320,6 +349,18 @@ public class DictionaryActivity extends ActionBarActivity { getIntent().putExtra(C.SEARCH_TOKEN, query); } } + // Support opening dictionary file directly + if (intentAction != null && intentAction.equals(Intent.ACTION_VIEW)) { + Uri uri = intent.getData(); + intent.putExtra(C.DICT_FILE, uri.toString()); + dictFileTitleName = uri.getLastPathSegment(); + try { + dictRaf = getContentResolver().openAssetFileDescriptor(uri, "r").createInputStream().getChannel(); + } catch (Exception e) { + dictionaryOpenFail(e); + return; + } + } /** * @author Dominik Köppl If no dictionary is chosen, use the default * dictionary specified in the preferences If this step does @@ -343,7 +384,7 @@ public class DictionaryActivity extends ActionBarActivity { try { Log.d(LOG, "Checking dictionary " + dics.get(i).uncompressedFilename); final File dictfile = application.getPath(dics.get(i).uncompressedFilename); - Dictionary dic = new Dictionary(new RandomAccessFile(dictfile, "r")); + Dictionary dic = new Dictionary(new RandomAccessFile(dictfile, "r").getChannel()); for (int j = 0; j < dic.indices.size(); ++j) { Index idx = dic.indices.get(j); Log.d(LOG, "Checking index " + idx.shortName); @@ -375,7 +416,7 @@ public class DictionaryActivity extends ActionBarActivity { finish(); return; } - if (dictFilename != null) + if (dictRaf == null && dictFilename != null) dictFile = new File(dictFilename); ttsReady = false; @@ -388,24 +429,14 @@ public class DictionaryActivity extends ActionBarActivity { }); try { - final String name = application.getDictionaryName(dictFile.getName()); - this.setTitle("QuickDic: " + name); - dictRaf = new RandomAccessFile(dictFile, "r"); + 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) { - Log.e(LOG, "Unable to load dictionary.", e); - if (dictRaf != null) { - try { - dictRaf.close(); - } catch (IOException e1) { - Log.e(LOG, "Unable to close dictRaf.", e1); - } - dictRaf = null; - } - Toast.makeText(this, getString(R.string.invalidDictionary, "", e.getMessage()), - Toast.LENGTH_LONG).show(); - startActivity(DictionaryManagerActivity.getLaunchIntent(getApplicationContext())); - finish(); + dictionaryOpenFail(e); return; } String targetIndex = intent.getStringExtra(C.INDEX_SHORT_NAME); @@ -421,27 +452,36 @@ public class DictionaryActivity extends ActionBarActivity { } 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_BACKGROUND); + android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE); final long startMillis = System.currentTimeMillis(); try { - TransliteratorManager.init(new TransliteratorManager.Callback() { - @Override - public void onTransliteratorReady() { - uiHandler.post(new Runnable() { - @Override - public void run() { - onSearchTextChange(searchView.getQuery().toString()); - } - }); - } - }); - for (final Index index : dictionary.indices) { final String searchToken = index.sortedIndexEntries.get(0).token; final IndexEntry entry = index.findExact(searchToken); @@ -523,7 +563,7 @@ public class DictionaryActivity extends ActionBarActivity { setSearchText(text, true); Log.d(LOG, "Trying to restore searchText=" + text); - setDictionaryPrefs(this, dictFile, index.shortName, searchView.getQuery().toString()); + setDictionaryPrefs(this, dictFile, index.shortName); updateLangButton(); searchView.requestFocus(); @@ -544,13 +584,6 @@ public class DictionaryActivity extends ActionBarActivity { ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); customSearchView.setLayoutParams(layoutParams); - listView.setOnItemClickListener(new OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int row, long id) { - onListItemClick(getListView(), view, row, id); - } - }); - languageButton = new ImageButton(customSearchView.getContext()); languageButton.setId(R.id.languageButton); languageButton.setScaleType(ScaleType.FIT_CENTER); @@ -645,12 +678,14 @@ public class DictionaryActivity extends ActionBarActivity { } private static void setDictionaryPrefs(final Context context, final File dictFile, - final String indexShortName, final String searchToken) { + final String indexShortName) { final SharedPreferences.Editor prefs = PreferenceManager.getDefaultSharedPreferences( context).edit(); - prefs.putString(C.DICT_FILE, dictFile.getPath()); - prefs.putString(C.INDEX_SHORT_NAME, indexShortName); - prefs.putString(C.SEARCH_TOKEN, ""); // Don't need to save search token. + 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(); } @@ -716,10 +751,9 @@ public class DictionaryActivity extends ActionBarActivity { } void updateLangButton() { - final LanguageResources languageResources = - DictionaryApplication.isoCodeToResources.get(index.shortName); - if (languageResources != null && languageResources.flagId != 0) { - languageButton.setImageResource(languageResources.flagId); + final int flagId = IsoUtils.INSTANCE.getFlagIdForIsoCode(index.shortName); + if (flagId != 0) { + languageButton.setImageResource(flagId); } else { if (indexIndex % 2 == 0) { languageButton.setImageResource(android.R.drawable.ic_media_next); @@ -802,10 +836,10 @@ public class DictionaryActivity extends ActionBarActivity { final LinearLayout result = new LinearLayout(parent.getContext()); - for (int i = 0; i < dictionaryInfo.indexInfos.size(); ++i) { + for (int i = 0; dictionaryInfo.indexInfos != null && i < dictionaryInfo.indexInfos.size(); ++i) { final IndexInfo indexInfo = dictionaryInfo.indexInfos.get(i); - final View button = application.createButton(parent.getContext(), - dictionaryInfo, indexInfo); + final View button = IsoUtils.INSTANCE.createButton(parent.getContext(), + dictionaryInfo, indexInfo, application.languageButtonPixels); final IntentLauncher intentLauncher = new IntentLauncher(parent.getContext(), getLaunchIntent(getApplicationContext(), application.getPath(dictionaryInfo.uncompressedFilename), @@ -958,16 +992,20 @@ public class DictionaryActivity extends ActionBarActivity { dialog.setContentView(R.layout.about_dictionary_dialog); final TextView textView = (TextView) dialog.findViewById(R.id.text); - final String name = application.getDictionaryName(dictFile.getName()); - dialog.setTitle(name); + dialog.setTitle(dictFileTitleName); final StringBuilder builder = new StringBuilder(); final DictionaryInfo dictionaryInfo = dictionary.getDictionaryInfo(); - dictionaryInfo.uncompressedBytes = dictFile.length(); if (dictionaryInfo != null) { + try { + dictionaryInfo.uncompressedBytes = dictRaf.size(); + } catch (IOException e) { + } builder.append(dictionaryInfo.dictInfo).append("\n\n"); - builder.append(getString(R.string.dictionaryPath, dictFile.getPath())) - .append("\n"); + if (dictFile != null) { + builder.append(getString(R.string.dictionaryPath, dictFile.getPath())) + .append("\n"); + } builder.append( getString(R.string.dictionarySize, dictionaryInfo.uncompressedBytes)) .append("\n"); @@ -1011,9 +1049,22 @@ public class DictionaryActivity extends ActionBarActivity { @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { - AdapterContextMenuInfo adapterContextMenuInfo = (AdapterContextMenuInfo) menuInfo; + final AdapterContextMenuInfo adapterContextMenuInfo = (AdapterContextMenuInfo) menuInfo; final RowBase row = (RowBase) getListAdapter().getItem(adapterContextMenuInfo.position); + if (clickOpensContextMenu && (row instanceof HtmlEntry.Row || + (row instanceof TokenRow && ((TokenRow)row).getIndexEntry().htmlEntries.size() > 0))) { + final List html = row instanceof TokenRow ? ((TokenRow)row).getIndexEntry().htmlEntries : Collections.singletonList(((HtmlEntry.Row)row).getEntry()); + final String highlight = row instanceof HtmlEntry.Row ? ((HtmlEntry.Row)row).getTokenRow(true).getToken() : null; + final MenuItem open = menu.add("Open"); + open.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + showHtml(html, highlight); + return false; + } + }); + } + final android.view.MenuItem addToWordlist = menu.add(getString(R.string.addToWordList, wordList.getName())); addToWordlist @@ -1075,6 +1126,37 @@ public class DictionaryActivity extends ActionBarActivity { } }); } + if (row instanceof PairEntry.Row && ttsReady) { + final List pairs = ((PairEntry.Row)row).getEntry().pairs; + final MenuItem speakLeft = menu.add(R.string.speak_left); + speakLeft.setOnMenuItemClickListener(new android.view.MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(android.view.MenuItem item) { + int idx = index.swapPairEntries ? 1 : 0; + updateTTSLanguage(idx); + String text = ""; + for (Pair p : pairs) text += p.get(idx); + text = text.replaceAll("\\{[^{}]*\\}", "").replace("{", "").replace("}", ""); + textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, + new HashMap()); + return false; + } + }); + final MenuItem speakRight = menu.add(R.string.speak_right); + speakRight.setOnMenuItemClickListener(new android.view.MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(android.view.MenuItem item) { + int idx = index.swapPairEntries ? 0 : 1; + updateTTSLanguage(idx); + String text = ""; + for (Pair p : pairs) text += p.get(idx); + text = text.replaceAll("\\{[^{}]*\\}", "").replace("{", "").replace("}", ""); + textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, + new HashMap()); + return false; + } + }); + } } private void jumpToTextFromHyperLink( @@ -1127,10 +1209,15 @@ public class DictionaryActivity extends ActionBarActivity { // searchView.selectAll(); } - protected void onListItemClick(ListView l, View v, int row, long id) { + protected void onListItemClick(ListView l, View v, int rowIdx, long id) { defocusSearchText(); if (clickOpensContextMenu && dictRaf != null) { openContextMenu(v); + } else { + final RowBase row = (RowBase)getListAdapter().getItem(rowIdx); + if (!(row instanceof PairEntry.Row)) { + v.performClick(); + } } } @@ -1211,7 +1298,7 @@ public class DictionaryActivity extends ActionBarActivity { indexAdapter = new IndexAdapter(index); setListAdapter(indexAdapter); Log.d(LOG, "changingIndex, newLang=" + index.longName); - setDictionaryPrefs(this, dictFile, index.shortName, searchView.getQuery().toString()); + setDictionaryPrefs(this, dictFile, index.shortName); updateLangButton(); } setSearchText(newSearchText, true, hideKeyboard); @@ -1374,6 +1461,16 @@ public class DictionaryActivity extends ActionBarActivity { // IndexAdapter // -------------------------------------------------------------------------- + private void showHtml(final List htmlEntries, final String htmlTextToHighlight) { + String html = HtmlEntry.htmlBody(htmlEntries, index.shortName); + // Log.d(LOG, "html=" + html); + startActivityForResult( + HtmlDisplayActivity.getHtmlIntent(getApplicationContext(), String.format( + "%s", html), + htmlTextToHighlight, false), + 0); + } + static ViewGroup.LayoutParams WEIGHT_1 = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT, 1.0f); @@ -1411,8 +1508,18 @@ public class DictionaryActivity extends ActionBarActivity { } private void getMetrics() { + float scale = 1; // Get the screen's density scale - final float scale = getResources().getDisplayMetrics().density; + // The previous method getResources().getDisplayMetrics() + // used to occasionally trigger a null pointer exception, + // so try this instead. + // As it still crashes, add a fallback + try { + DisplayMetrics dm = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(dm); + scale = dm.density; + } catch (NullPointerException e) + {} // Convert the dps to pixels, based on density scale mPaddingDefault = (int) (PADDING_DEFAULT_DP * scale + 0.5f); mPaddingLarge = (int) (PADDING_LARGE_DP * scale + 0.5f); @@ -1538,7 +1645,7 @@ public class DictionaryActivity extends ActionBarActivity { // http://groups.google.com/group/android-developers/browse_thread/thread/3d96af1530a7d62a?pli=1 result.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); result.setClickable(true); - result.setFocusable(true); + result.setFocusable(false); result.setLongClickable(true); // result.setBackgroundResource(android.R.drawable.menuitem_background); @@ -1605,16 +1712,17 @@ public class DictionaryActivity extends ActionBarActivity { textView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - String html = HtmlEntry.htmlBody(htmlEntries, index.shortName); - // Log.d(LOG, "html=" + html); - startActivityForResult( - HtmlDisplayActivity.getHtmlIntent(getApplicationContext(), String.format( - "%s", html), - htmlTextToHighlight, false), - 0); + showHtml(htmlEntries, htmlTextToHighlight); + } + }); + result.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + textView.performClick(); } }); } + result.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); return result; }