From f16d8ed40c49c70cf6c4e80e0392f9c01793cd25 Mon Sep 17 00:00:00 2001 From: Thad Hughes Date: Mon, 16 Jan 2012 11:43:16 -0800 Subject: [PATCH] Switching to WebView! --- res/values/strings.xml | 3 +- res/values/themes.xml | 1 - src/com/hughes/android/dictionary/C.java | 27 +++--- .../dictionary/DictionaryActivity.java | 93 +++++++------------ .../dictionary/DictionaryEditActivity.java | 2 +- .../dictionary/DictionaryManagerActivity.java | 9 -- .../android/dictionary/QuickDicConfig.java | 2 +- .../dictionary/engine/AbstractEntry.java | 24 ++++- .../android/dictionary/engine/Dictionary.java | 25 +++-- .../dictionary/engine/EntrySource.java | 8 +- .../android/dictionary/engine/Language.java | 11 ++- .../android/dictionary/engine/PairEntry.java | 25 +++-- .../android/dictionary/engine/TextEntry.java | 16 +++- 13 files changed, 135 insertions(+), 111 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 3a90f6b..4688787 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3,12 +3,13 @@ QuickDic - + Dictionary manager Dictionary config Move to top + Delete dictionary %s (not on device) 3.0.1h diff --git a/res/values/themes.xml b/res/values/themes.xml index 7403f79..d070800 100644 --- a/res/values/themes.xml +++ b/res/values/themes.xml @@ -9,7 +9,6 @@ #FFFFFF - #FFFFFF #0000FF #888888 #222222 diff --git a/src/com/hughes/android/dictionary/C.java b/src/com/hughes/android/dictionary/C.java index 4c6fff4..acb10ee 100644 --- a/src/com/hughes/android/dictionary/C.java +++ b/src/com/hughes/android/dictionary/C.java @@ -15,7 +15,7 @@ package com.hughes.android.dictionary; public class C { - + static final String DICTIONARY_CONFIGS = "dictionaryConfigs"; static final String DICT_INDEX = "dictIndex"; @@ -23,15 +23,21 @@ public class C { static final String SEARCH_TOKEN = "searchToken"; public static final String THANKS_FOR_UPDATING_VERSION = "thanksForUpdatingVersion"; - + enum Theme { - DEFAULT(R.style.Theme_Default, R.style.Theme_Light_TokenRow_Fg, R.drawable.theme_default_token_row_main_bg, R.drawable.theme_default_token_row_other_bg, R.drawable.theme_default_other_lang_bg), - LIGHT(R.style.Theme_Light, R.style.Theme_Default_TokenRow_Fg, R.drawable.theme_light_token_row_main_bg, R.drawable.theme_light_token_row_other_bg, R.drawable.theme_light_other_lang_bg); - - private Theme(final int themeId, - final int tokenRowFg, - final int tokenRowMainBg, - final int tokenRowOtherBg, + DEFAULT(R.style.Theme_Default, R.style.Theme_Light_TokenRow_Fg, + R.drawable.theme_default_token_row_main_bg, + R.drawable.theme_default_token_row_other_bg, + R.drawable.theme_default_other_lang_bg), + + LIGHT(R.style.Theme_Light, + R.style.Theme_Light_TokenRow_Fg, + R.drawable.theme_light_token_row_main_bg, + R.drawable.theme_light_token_row_other_bg, + R.drawable.theme_light_other_lang_bg); + + private Theme(final int themeId, final int tokenRowFg, + final int tokenRowMainBg, final int tokenRowOtherBg, final int otherLangBg) { this.themeId = themeId; this.tokenRowFg = tokenRowFg; @@ -39,7 +45,7 @@ public class C { this.tokenRowOtherBg = tokenRowOtherBg; this.otherLangBg = otherLangBg; } - + final int themeId; final int tokenRowFg; final int tokenRowMainBg; @@ -47,5 +53,4 @@ public class C { final int otherLangBg; } - } diff --git a/src/com/hughes/android/dictionary/DictionaryActivity.java b/src/com/hughes/android/dictionary/DictionaryActivity.java index 0a846e6..ac9fd9b 100644 --- a/src/com/hughes/android/dictionary/DictionaryActivity.java +++ b/src/com/hughes/android/dictionary/DictionaryActivity.java @@ -52,6 +52,7 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; +import android.webkit.WebView; import android.widget.AdapterView; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.BaseAdapter; @@ -425,7 +426,7 @@ public class DictionaryActivity extends ListActivity { } { - final MenuItem dictionaryList = menu.add(getString(R.string.dictionaryList)); + final MenuItem dictionaryList = menu.add(getString(R.string.dictionaryManager)); dictionaryList.setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(final MenuItem menuItem) { startActivity(DictionaryManagerActivity.getIntent(DictionaryActivity.this)); @@ -435,17 +436,6 @@ public class DictionaryActivity extends ListActivity { }); } - { - final MenuItem dictionaryEdit = menu.add(getString(R.string.editDictionary)); - dictionaryEdit.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(final MenuItem menuItem) { - final Intent intent = DictionaryEditActivity.getIntent(dictIndex); - startActivity(intent); - return false; - } - }); - } - { final MenuItem about = menu.add(getString(R.string.about)); about.setOnMenuItemClickListener(new OnMenuItemClickListener() { @@ -560,6 +550,8 @@ public class DictionaryActivity extends ListActivity { return true; } if (keyCode == KeyEvent.KEYCODE_BACK) { + Log.d(LOG, "Clearing dictionary prefs."); + DictionaryActivity.clearDictionaryPrefs(this); } if (keyCode == KeyEvent.KEYCODE_ENTER) { Log.d(LOG, "Trying to hide soft keyboard."); @@ -704,67 +696,46 @@ public class DictionaryActivity extends ListActivity { } private View getView(PairEntry.Row row, ViewGroup parent) { - final TableLayout result = new TableLayout(parent.getContext()); + final WebView result = new WebView(parent.getContext()); final PairEntry entry = row.getEntry(); final int rowCount = entry.pairs.size(); + final StringBuilder html = new StringBuilder(); + html.append(""); for (int r = 0; r < rowCount; ++r) { - final TableRow tableRow = new TableRow(result.getContext()); + html.append(""); - final EditText column1 = new EditText(tableRow.getContext()); - final EditText column2 = new EditText(tableRow.getContext()); - final TableRow.LayoutParams layoutParams = new TableRow.LayoutParams(); - layoutParams.weight = 0.5f; + final Pair pair = entry.pairs.get(r); + // TODO: escape both the token and the text. + final String token = row.getTokenRow(true).getToken(); + final String col1Text = index.swapPairEntries ? pair.lang2 : pair.lang1; + final String col2Text = index.swapPairEntries ? pair.lang1 : pair.lang2; + + col1Text.replaceAll(token, String.format("%s"); if (r > 0) { - final TextView spacer = new TextView(tableRow.getContext()); - spacer.setText(" • "); - tableRow.addView(spacer); + html.append("
  • "); } - tableRow.addView(column1, layoutParams); - if (r > 0) { - final TextView spacer = new TextView(tableRow.getContext()); - spacer.setText(" • "); - tableRow.addView(spacer); - } - tableRow.addView(column2, layoutParams); - - column1.setWidth(1); - column2.setWidth(1); + html.append(col1Text); + html.append(""); - // TODO: color words by gender - final Pair pair = entry.pairs.get(r); - final String col1Text = Language.fixBidiText(index.swapPairEntries ? pair.lang2 : pair.lang1); - column1.setText(col1Text, TextView.BufferType.SPANNABLE); - final Spannable col1Spannable = (Spannable) column1.getText(); - - int startPos = 0; - final String token = row.getTokenRow(true).getToken(); - while ((startPos = col1Text.indexOf(token, startPos)) != -1) { - col1Spannable.setSpan(new StyleSpan(Typeface.BOLD), startPos, - startPos + token.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); - startPos += token.length(); + // Column2 + html.append("
  • "); - String col2Text = index.swapPairEntries ? pair.lang1 : pair.lang2; - col2Text = Language.fixBidiText(col2Text); - column2.setText(col2Text, TextView.BufferType.NORMAL); - - column1.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp); - column2.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp); - column2.setBackgroundResource(theme.otherLangBg); - - column2.setOnLongClickListener(new EditText.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - final int start = column2.getSelectionStart(); - final int end = column2.getSelectionStart(); - Log.i(LOG, "Long click on: " + column2.getText().toString().substring(start, end)); - return false; - } - }); +// column1.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp); +// column2.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp); - result.addView(tableRow); + html.append(""); } + html.append("
    "); + if (r > 0) { + html.append("
  • "); } + html.append(col2Text); + html.append("
  • "); + + result.loadData(html.toString(), "text/html", null); return result; } diff --git a/src/com/hughes/android/dictionary/DictionaryEditActivity.java b/src/com/hughes/android/dictionary/DictionaryEditActivity.java index 909db75..8ad0e25 100644 --- a/src/com/hughes/android/dictionary/DictionaryEditActivity.java +++ b/src/com/hughes/android/dictionary/DictionaryEditActivity.java @@ -170,7 +170,7 @@ public class DictionaryEditActivity extends Activity { } }); - final MenuItem dictionaryList = menu.add(getString(R.string.dictionaryList)); + final MenuItem dictionaryList = menu.add(getString(R.string.dictionaryManager)); dictionaryList.setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(final MenuItem menuItem) { startActivity(DictionaryManagerActivity.getIntent(DictionaryEditActivity.this)); diff --git a/src/com/hughes/android/dictionary/DictionaryManagerActivity.java b/src/com/hughes/android/dictionary/DictionaryManagerActivity.java index ac1d97b..9057803 100644 --- a/src/com/hughes/android/dictionary/DictionaryManagerActivity.java +++ b/src/com/hughes/android/dictionary/DictionaryManagerActivity.java @@ -162,15 +162,6 @@ public class DictionaryManagerActivity extends ListActivity { final AdapterContextMenuInfo adapterContextMenuInfo = (AdapterContextMenuInfo) menuInfo; - final MenuItem editMenuItem = menu.add(R.string.editDictionary); - editMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - startActivity(DictionaryEditActivity.getIntent(adapterContextMenuInfo.position)); - return true; - } - }); - if (adapterContextMenuInfo.position > 0) { final MenuItem moveToTopMenuItem = menu.add(R.string.moveToTop); moveToTopMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { diff --git a/src/com/hughes/android/dictionary/QuickDicConfig.java b/src/com/hughes/android/dictionary/QuickDicConfig.java index 0ad8b38..ac32748 100644 --- a/src/com/hughes/android/dictionary/QuickDicConfig.java +++ b/src/com/hughes/android/dictionary/QuickDicConfig.java @@ -54,13 +54,13 @@ public final class QuickDicConfig implements Serializable { final BufferedReader reader = new BufferedReader(new InputStreamReader(context.getResources().openRawResource(R.raw.dictionary_info))); String line; - String name = ""; try { while ((line = reader.readLine()) != null) { if (line.startsWith("#") || line.length() == 0) { continue; } final DictionaryInfo dictionaryInfo = new DictionaryInfo(line); + String name = ""; for (int i = 0; i < dictionaryInfo.langIsos.length; ++i) { final Integer langCode = Language.isoCodeToResourceId.get(dictionaryInfo.langIsos[i]); final String lang = langCode != null ? context.getString(langCode) : dictionaryInfo.langIsos[i]; diff --git a/src/com/hughes/android/dictionary/engine/AbstractEntry.java b/src/com/hughes/android/dictionary/engine/AbstractEntry.java index 7fc5012..24a1d82 100644 --- a/src/com/hughes/android/dictionary/engine/AbstractEntry.java +++ b/src/com/hughes/android/dictionary/engine/AbstractEntry.java @@ -14,9 +14,31 @@ package com.hughes.android.dictionary.engine; +import java.io.IOException; +import java.io.RandomAccessFile; + public abstract class AbstractEntry { + + final EntrySource entrySource; + + protected AbstractEntry(EntrySource entrySource) { + this.entrySource = entrySource; + } + + public AbstractEntry(Dictionary dictionary, RandomAccessFile raf) throws IOException { + if (dictionary.dictFileVersion >= 1) { + final int entrySouceIdx = raf.readShort(); + this.entrySource = dictionary.sources.get(entrySouceIdx); + } else { + this.entrySource = null; + } + } + + public void write(RandomAccessFile raf) throws IOException { + raf.writeShort(entrySource.index()); + } public abstract int addToDictionary(final Dictionary dictionary); - + } diff --git a/src/com/hughes/android/dictionary/engine/Dictionary.java b/src/com/hughes/android/dictionary/engine/Dictionary.java index a6e217d..c662998 100644 --- a/src/com/hughes/android/dictionary/engine/Dictionary.java +++ b/src/com/hughes/android/dictionary/engine/Dictionary.java @@ -41,8 +41,14 @@ public class Dictionary implements RAFSerializable { public final List sources; public final List indices; + /** + * dictFileVersion 1 adds: + *
  • counts of tokens in indices. + *
  • links to sources? + */ + public Dictionary(final String dictInfo) { - this.dictFileVersion = 0; + this.dictFileVersion = 1; this.creationMillis = System.currentTimeMillis(); this.dictInfo = dictInfo; pairEntries = new ArrayList(); @@ -53,14 +59,19 @@ public class Dictionary implements RAFSerializable { public Dictionary(final RandomAccessFile raf) throws IOException { dictFileVersion = raf.readInt(); - if (dictFileVersion != 0) { + if (dictFileVersion < 0 || dictFileVersion > 1) { throw new IOException("Invalid dictionary version: " + dictFileVersion); } creationMillis = raf.readLong(); dictInfo = raf.readUTF(); - sources = CachingList.createFullyCached(RAFList.create(raf, EntrySource.SERIALIZER, raf.getFilePointer())); - pairEntries = CachingList.create(RAFList.create(raf, PairEntry.SERIALIZER, raf.getFilePointer()), CACHE_SIZE); - textEntries = CachingList.create(RAFList.create(raf, TextEntry.SERIALIZER, raf.getFilePointer()), CACHE_SIZE); + + // Load the sources, then seek past them, because reading them later disrupts the offset. + final RAFList rafSources = RAFList.create(raf, EntrySource.SERIALIZER, raf.getFilePointer()); + sources = new ArrayList(rafSources); + raf.seek(rafSources.getEndOffset()); + + pairEntries = CachingList.create(RAFList.create(raf, new PairEntry.Serializer(this), raf.getFilePointer()), CACHE_SIZE); + textEntries = CachingList.create(RAFList.create(raf, new TextEntry.Serializer(this), raf.getFilePointer()), CACHE_SIZE); indices = CachingList.createFullyCached(RAFList.create(raf, indexSerializer, raf.getFilePointer())); final String end = raf.readUTF(); if (!end.equals(END_OF_DICTIONARY)) { @@ -74,8 +85,8 @@ public class Dictionary implements RAFSerializable { raf.writeLong(creationMillis); raf.writeUTF(dictInfo); RAFList.write(raf, sources, EntrySource.SERIALIZER); - RAFList.write(raf, pairEntries, PairEntry.SERIALIZER); - RAFList.write(raf, textEntries, TextEntry.SERIALIZER); + RAFList.write(raf, pairEntries, new PairEntry.Serializer(this)); + RAFList.write(raf, textEntries, new TextEntry.Serializer(this)); RAFList.write(raf, indices, indexSerializer); raf.writeUTF(END_OF_DICTIONARY); } diff --git a/src/com/hughes/android/dictionary/engine/EntrySource.java b/src/com/hughes/android/dictionary/engine/EntrySource.java index f624817..80c4ebf 100644 --- a/src/com/hughes/android/dictionary/engine/EntrySource.java +++ b/src/com/hughes/android/dictionary/engine/EntrySource.java @@ -26,12 +26,10 @@ public class EntrySource extends IndexedObject implements Serializable { private static final long serialVersionUID = -1323165134846120269L; final String name; - final int pairEntryStart; - public EntrySource(final int index, final String name, final int pairEntryStart) { + public EntrySource(final int index, final String name) { super(index); this.name = name; - this.pairEntryStart = pairEntryStart; } @Override @@ -46,14 +44,12 @@ public class EntrySource extends IndexedObject implements Serializable { public EntrySource read(RandomAccessFile raf, int readIndex) throws IOException { final String name = raf.readUTF(); - final int pairEntryStart = raf.readInt(); - return new EntrySource(readIndex, name, pairEntryStart); + return new EntrySource(readIndex, name); } @Override public void write(RandomAccessFile raf, EntrySource t) throws IOException { raf.writeUTF(t.name); - raf.writeInt(t.pairEntryStart); } }; diff --git a/src/com/hughes/android/dictionary/engine/Language.java b/src/com/hughes/android/dictionary/engine/Language.java index fcf74f1..fe24d1f 100644 --- a/src/com/hughes/android/dictionary/engine/Language.java +++ b/src/com/hughes/android/dictionary/engine/Language.java @@ -14,6 +14,7 @@ package com.hughes.android.dictionary.engine; +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; @@ -88,6 +89,11 @@ public class Language { isoCodeToResourceId.put("CI", R.string.CI); isoCodeToResourceId.put("YI", R.string.YI); isoCodeToResourceId.put("ZU", R.string.ZU); + + // Hack to allow lower-case ISO codes to work: + for (final String isoCode : new ArrayList(isoCodeToResourceId.keySet())) { + isoCodeToResourceId.put(isoCode.toLowerCase(), isoCodeToResourceId.get(isoCode)); + } } @@ -133,10 +139,11 @@ public class Language { */ private static final String rtlChars = "\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC"; - private static final Pattern RTL_TOKEN = Pattern.compile("[" + rtlChars + "]+"); + private static final Pattern RTL_TOKEN = Pattern.compile("[" + rtlChars + "]"); public static String fixBidiText(final String text) { - return RTL_TOKEN.matcher(text).replaceAll("\u200e $0 \u200e"); + // TODO: fix me!, use me! + return text; } // ---------------------------------------------------------------- diff --git a/src/com/hughes/android/dictionary/engine/PairEntry.java b/src/com/hughes/android/dictionary/engine/PairEntry.java index d42dd68..ebfd84a 100644 --- a/src/com/hughes/android/dictionary/engine/PairEntry.java +++ b/src/com/hughes/android/dictionary/engine/PairEntry.java @@ -27,16 +27,18 @@ public class PairEntry extends AbstractEntry implements RAFSerializable pairs; - public PairEntry() { - pairs = new ArrayList(1); + public PairEntry(final EntrySource entrySource) { + super(entrySource); + pairs = new ArrayList(1); } - public PairEntry(final String lang1, final String lang2) { - pairs = new ArrayList(1); + public PairEntry(final EntrySource entrySource, final String lang1, final String lang2) { + this(entrySource); this.pairs.add(new Pair(lang1, lang2)); } - public PairEntry(final RandomAccessFile raf) throws IOException { + public PairEntry(final Dictionary dictionary, final RandomAccessFile raf) throws IOException { + super(dictionary, raf); final int size = raf.readInt(); pairs = new ArrayList(size); for (int i = 0; i < size; ++i) { @@ -45,18 +47,27 @@ public class PairEntry extends AbstractEntry implements RAFSerializable 0; raf.writeUTF(pairs.get(i).lang1); raf.writeUTF(pairs.get(i).lang2); } } - static final RAFSerializer SERIALIZER = new RAFSerializer() { + static final class Serializer implements RAFSerializer { + + final Dictionary dictionary; + + Serializer(Dictionary dictionary) { + this.dictionary = dictionary; + } + @Override public PairEntry read(RandomAccessFile raf) throws IOException { - return new PairEntry(raf); + return new PairEntry(dictionary, raf); } @Override diff --git a/src/com/hughes/android/dictionary/engine/TextEntry.java b/src/com/hughes/android/dictionary/engine/TextEntry.java index fa3dc53..8bef294 100644 --- a/src/com/hughes/android/dictionary/engine/TextEntry.java +++ b/src/com/hughes/android/dictionary/engine/TextEntry.java @@ -25,18 +25,27 @@ public class TextEntry extends AbstractEntry implements RAFSerializable SERIALIZER = new RAFSerializer() { + static final class Serializer implements RAFSerializer { + + final Dictionary dictionary; + + Serializer(Dictionary dictionary) { + this.dictionary = dictionary; + } + @Override public TextEntry read(RandomAccessFile raf) throws IOException { - return new TextEntry(raf); + return new TextEntry(dictionary, raf); } @Override @@ -44,6 +53,7 @@ public class TextEntry extends AbstractEntry implements RAFSerializable