X-Git-Url: http://gitweb.fperrin.net/?a=blobdiff_plain;f=src%2Fcom%2Fhughes%2Fandroid%2Fdictionary%2FDictionaryActivity.java;h=863e20b81bffcaaefa20935baef6ac467af99715;hb=7db6eafc81c441ce7b1dc2f8afd9e1706cc4fb66;hp=c4d2ddae81a926ede0ede7237abe1c3a953823e1;hpb=2c7ba9fe59ab6f5da92af5ddb4e3be0b90ea393c;p=Dictionary.git diff --git a/src/com/hughes/android/dictionary/DictionaryActivity.java b/src/com/hughes/android/dictionary/DictionaryActivity.java index c4d2dda..863e20b 100644 --- a/src/com/hughes/android/dictionary/DictionaryActivity.java +++ b/src/com/hughes/android/dictionary/DictionaryActivity.java @@ -39,6 +39,7 @@ import android.support.v7.widget.Toolbar; import android.text.ClipboardManager; import android.text.InputType; import android.text.Spannable; +import android.text.SpannableString; import android.text.method.LinkMovementMethod; import android.text.style.ClickableSpan; import android.text.style.StyleSpan; @@ -99,6 +100,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; @@ -124,7 +126,8 @@ public class DictionaryActivity extends ActionBarActivity { DictionaryApplication application; File dictFile = null; - RandomAccessFile dictRaf = null; + FileChannel dictRaf = null; + String dictFileTitleName = null; Dictionary dictionary = null; @@ -224,6 +227,24 @@ public class DictionaryActivity extends ActionBarActivity { return search.length(); } + private void dictionaryOpenFail(Exception e) { + Log.e(LOG, "Unable to load dictionary.", e); + if (dictRaf != null) { + indexAdapter = null; + setListAdapter(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()); @@ -239,13 +260,22 @@ public class DictionaryActivity extends ActionBarActivity { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); // Don't auto-launch if this fails. - prefs.edit().remove(C.DICT_FILE).commit(); + prefs.edit().remove(C.DICT_FILE).remove(C.INDEX_SHORT_NAME).commit(); setContentView(R.layout.dictionary_activity); 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(); /** @@ -322,6 +352,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 @@ -345,7 +387,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); @@ -377,7 +419,7 @@ public class DictionaryActivity extends ActionBarActivity { finish(); return; } - if (dictFilename != null) + if (dictRaf == null && dictFilename != null) dictFile = new File(dictFilename); ttsReady = false; @@ -390,24 +432,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); @@ -534,7 +566,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(); @@ -649,12 +681,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(); } @@ -678,6 +712,9 @@ public class DictionaryActivity extends ActionBarActivity { textToSpeech.shutdown(); textToSpeech = null; + indexAdapter = null; + setListAdapter(null); + try { Log.d(LOG, "Closing RAF."); dictRaf.close(); @@ -805,7 +842,7 @@ 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 = IsoUtils.INSTANCE.createButton(parent.getContext(), dictionaryInfo, indexInfo, application.languageButtonPixels); @@ -961,16 +998,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"); @@ -1263,7 +1304,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); @@ -1506,36 +1547,66 @@ public class DictionaryActivity extends ActionBarActivity { } @Override - public TableLayout getView(int position, View convertView, ViewGroup parent) { - final TableLayout result; - if (convertView instanceof TableLayout) { - result = (TableLayout) convertView; - result.removeAllViews(); + public int getViewTypeCount() { + return 5; + } + + @Override + public int getItemViewType(int position) { + final RowBase row = getItem(position); + if (row instanceof PairEntry.Row) { + final PairEntry entry = ((PairEntry.Row)row).getEntry(); + final int rowCount = entry.pairs.size(); + return rowCount > 1 ? 1 : 0; + } else if (row instanceof TokenRow) { + final IndexEntry indexEntry = ((TokenRow)row).getIndexEntry(); + return indexEntry.htmlEntries.isEmpty() ? 2 : 3; + } else if (row instanceof HtmlEntry.Row) { + return 4; } else { - result = new TableLayout(parent.getContext()); + throw new IllegalArgumentException("Unsupported Row type: " + row.getClass()); } + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { final RowBase row = getItem(position); if (row instanceof PairEntry.Row) { - return getView(position, (PairEntry.Row) row, parent, result); + return getView(position, (PairEntry.Row) row, parent, (TableLayout)convertView); } else if (row instanceof TokenRow) { - return getView((TokenRow) row, parent, result); + return getView((TokenRow) row, parent, (TextView)convertView); } else if (row instanceof HtmlEntry.Row) { - return getView((HtmlEntry.Row) row, parent, result); + return getView((HtmlEntry.Row) row, parent, (TextView)convertView); } else { throw new IllegalArgumentException("Unsupported Row type: " + row.getClass()); } } private TableLayout getView(final int position, PairEntry.Row row, ViewGroup parent, - final TableLayout result) { + TableLayout result) { + final Context context = parent.getContext(); final PairEntry entry = row.getEntry(); final int rowCount = entry.pairs.size(); + if (result == null) { + result = new TableLayout(context); + // Because we have a Button inside a ListView row: + // http://groups.google.com/group/android-developers/browse_thread/thread/3d96af1530a7d62a?pli=1 + result.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); + result.setClickable(true); + result.setFocusable(false); + result.setLongClickable(true); +// result.setBackgroundResource(android.R.drawable.menuitem_background); + + result.setBackgroundResource(theme.normalRowBg); + } else if (result.getChildCount() > rowCount) { + result.removeViews(rowCount, result.getChildCount() - rowCount); + } final TableRow.LayoutParams layoutParams = new TableRow.LayoutParams(); layoutParams.weight = 0.5f; layoutParams.leftMargin = mPaddingLarge; - for (int r = 0; r < rowCount; ++r) { + for (int r = result.getChildCount(); r < rowCount; ++r) { final TableRow tableRow = new TableRow(result.getContext()); final TextView col1 = new TextView(tableRow.getContext()); @@ -1548,35 +1619,51 @@ public class DictionaryActivity extends ActionBarActivity { // Set the columns in the table. if (r > 0) { final TextView bullet = new TextView(tableRow.getContext()); - bullet.setText(" • "); + bullet.setText(" •"); tableRow.addView(bullet); } tableRow.addView(col1, layoutParams); - final TextView margin = new TextView(tableRow.getContext()); - margin.setText(" "); - tableRow.addView(margin); if (r > 0) { final TextView bullet = new TextView(tableRow.getContext()); - bullet.setText(" • "); + bullet.setText(" •"); tableRow.addView(bullet); } tableRow.addView(col2, layoutParams); col1.setWidth(1); col2.setWidth(1); - // Set what's in the columns. + col1.setTypeface(typeface); + col2.setTypeface(typeface); + col1.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp); + col2.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp); + // col2.setBackgroundResource(theme.otherLangBg); + if (index.swapPairEntries) { + col2.setOnLongClickListener(textViewLongClickListenerIndex0); + col1.setOnLongClickListener(textViewLongClickListenerIndex1); + } else { + col1.setOnLongClickListener(textViewLongClickListenerIndex0); + col2.setOnLongClickListener(textViewLongClickListenerIndex1); + } + + result.addView(tableRow); + } + + for (int r = 0; r < rowCount; ++r) { + final TableRow tableRow = (TableRow)result.getChildAt(r); + final TextView col1 = (TextView)tableRow.getChildAt(r == 0 ? 0 : 1); + final TextView col2 = (TextView)tableRow.getChildAt(r == 0 ? 1 : 3); + + // Set what's in the columns. final Pair pair = entry.pairs.get(r); final String col1Text = index.swapPairEntries ? pair.lang2 : pair.lang1; final String col2Text = index.swapPairEntries ? pair.lang1 : pair.lang2; - - col1.setText(col1Text, TextView.BufferType.SPANNABLE); - col2.setText(col2Text, TextView.BufferType.SPANNABLE); + final Spannable col1Spannable = new SpannableString(col1Text); + final Spannable col2Spannable = new SpannableString(col2Text); // Bold the token instances in col1. final Set toBold = toHighlight != null ? this.toHighlight : Collections .singleton(row.getTokenRow(true).getToken()); - final Spannable col1Spannable = (Spannable) col1.getText(); for (final String token : toBold) { int startPos = 0; while ((startPos = col1Text.indexOf(token, startPos)) != -1) { @@ -1587,35 +1674,12 @@ public class DictionaryActivity extends ActionBarActivity { } createTokenLinkSpans(col1, col1Spannable, col1Text); - createTokenLinkSpans(col2, (Spannable) col2.getText(), col2Text); - - col1.setTypeface(typeface); - col2.setTypeface(typeface); - col1.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp); - col2.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp); - // col2.setBackgroundResource(theme.otherLangBg); + createTokenLinkSpans(col2, col2Spannable, col2Text); - if (index.swapPairEntries) { - col2.setOnLongClickListener(textViewLongClickListenerIndex0); - col1.setOnLongClickListener(textViewLongClickListenerIndex1); - } else { - col1.setOnLongClickListener(textViewLongClickListenerIndex0); - col2.setOnLongClickListener(textViewLongClickListenerIndex1); - } - - result.addView(tableRow); + col1.setText(col1Spannable); + col2.setText(col2Spannable); } - // Because we have a Button inside a ListView row: - // http://groups.google.com/group/android-developers/browse_thread/thread/3d96af1530a7d62a?pli=1 - result.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); - result.setClickable(true); - result.setFocusable(false); - result.setLongClickable(true); -// result.setBackgroundResource(android.R.drawable.menuitem_background); - - result.setBackgroundResource(theme.normalRowBg); - result.setOnClickListener(new TextView.OnClickListener() { @Override public void onClick(View v) { @@ -1626,42 +1690,43 @@ public class DictionaryActivity extends ActionBarActivity { return result; } - private TableLayout getPossibleLinkToHtmlEntryView(final boolean isTokenRow, + private TextView getPossibleLinkToHtmlEntryView(final boolean isTokenRow, final String text, final boolean hasMainEntry, final List htmlEntries, - final String htmlTextToHighlight, ViewGroup parent, final TableLayout result) { + final String htmlTextToHighlight, ViewGroup parent, TextView textView) { final Context context = parent.getContext(); + if (textView == null) { + textView = new TextView(context); + // set up things invariant across one ItemViewType + // ItemViewTypes handled here are: + // 2: isTokenRow == true, htmlEntries.isEmpty() == true + // 3: isTokenRow == true, htmlEntries.isEmpty() == false + // 4: isTokenRow == false, htmlEntries.isEmpty() == false + textView.setPadding(isTokenRow ? mPaddingDefault : mPaddingLarge, mPaddingDefault, mPaddingDefault, 0); + textView.setOnLongClickListener(indexIndex > 0 ? textViewLongClickListenerIndex1 : textViewLongClickListenerIndex0); + textView.setLongClickable(true); + + // Doesn't work: + // textView.setTextColor(android.R.color.secondary_text_light); + textView.setTypeface(typeface); + if (isTokenRow) { + textView.setTextAppearance(context, theme.tokenRowFg); + textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 4 * fontSizeSp / 3); + } else { + textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp); + } + if (!htmlEntries.isEmpty()) { + textView.setClickable(true); + textView.setMovementMethod(LinkMovementMethod.getInstance()); + } + } - final TableRow tableRow = new TableRow(result.getContext()); - tableRow.setBackgroundResource(hasMainEntry ? theme.tokenRowMainBg + textView.setBackgroundResource(hasMainEntry ? theme.tokenRowMainBg : theme.tokenRowOtherBg); - if (isTokenRow) { - tableRow.setPadding(mPaddingDefault, mPaddingDefault, mPaddingDefault, 0); - } else { - tableRow.setPadding(mPaddingLarge, mPaddingDefault, mPaddingDefault, 0); - } - result.addView(tableRow); // Make it so we can long-click on these token rows, too: - final TextView textView = new TextView(context); - textView.setText(text, BufferType.SPANNABLE); - createTokenLinkSpans(textView, (Spannable) textView.getText(), text); - textView.setOnLongClickListener(indexIndex > 0 ? textViewLongClickListenerIndex1 : textViewLongClickListenerIndex0); - result.setLongClickable(true); - - // Doesn't work: - // textView.setTextColor(android.R.color.secondary_text_light); - textView.setTypeface(typeface); - TableRow.LayoutParams lp = new TableRow.LayoutParams(0); - if (isTokenRow) { - textView.setTextAppearance(context, theme.tokenRowFg); - textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 4 * fontSizeSp / 3); - } else { - textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp); - } - lp.weight = 1.0f; - - textView.setLayoutParams(lp); - tableRow.addView(textView); + final Spannable textSpannable = new SpannableString(text); + createTokenLinkSpans(textView, textSpannable, text); + textView.setText(textSpannable); if (!htmlEntries.isEmpty()) { final ClickableSpan clickableSpan = new ClickableSpan() { @@ -1671,33 +1736,23 @@ public class DictionaryActivity extends ActionBarActivity { }; ((Spannable) textView.getText()).setSpan(clickableSpan, 0, text.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); - result.setClickable(true); - textView.setClickable(true); - textView.setMovementMethod(LinkMovementMethod.getInstance()); textView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showHtml(htmlEntries, htmlTextToHighlight); } }); - result.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - textView.performClick(); - } - }); } - result.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); - return result; + return textView; } - private TableLayout getView(TokenRow row, ViewGroup parent, final TableLayout result) { + private TextView getView(TokenRow row, ViewGroup parent, final TextView result) { final IndexEntry indexEntry = row.getIndexEntry(); return getPossibleLinkToHtmlEntryView(true, indexEntry.token, row.hasMainEntry, indexEntry.htmlEntries, null, parent, result); } - private TableLayout getView(HtmlEntry.Row row, ViewGroup parent, final TableLayout result) { + private TextView getView(HtmlEntry.Row row, ViewGroup parent, final TextView result) { final HtmlEntry htmlEntry = row.getEntry(); final TokenRow tokenRow = row.getTokenRow(true); return getPossibleLinkToHtmlEntryView(false,