<string name="app_name">QuickDic</string>
- <!-- DictionaryListActivity -->
+ <!-- DictionaryManagerActivity -->
<string name="dictionaryManager">Dictionary manager</string>
<string name="selectADictionary"><![CDATA[Select a dictionary.
\nLong-press to edit the dictionary config. Press "menu" to add a new dictionary.]]></string>
<string name="dictionaryConfig">Dictionary config</string>
<string name="moveToTop">Move to top</string>
+ <string name="deleteDictionary">Delete dictionary</string>
<string name="notOnDevice">%s (not on device)</string>
<string name="thanksForUpdatingVersion">3.0.1h</string>
<item name="android:textColor">#FFFFFF</item>
</style>
- <color name="theme_default_token_row_fg">#FFFFFF</color>
<color name="theme_default_token_row_main_bg">#0000FF</color>
<color name="theme_default_token_row_other_bg">#888888</color>
<color name="theme_default_other_lang_bg">#222222</color>
package com.hughes.android.dictionary;
public class C {
-
+
static final String DICTIONARY_CONFIGS = "dictionaryConfigs";
static final String DICT_INDEX = "dictIndex";
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;
this.tokenRowOtherBg = tokenRowOtherBg;
this.otherLangBg = otherLangBg;
}
-
+
final int themeId;
final int tokenRowFg;
final int tokenRowMainBg;
final int otherLangBg;
}
-
}
import android.view.View.OnClickListener;\r
import android.view.ViewGroup;\r
import android.view.inputmethod.InputMethodManager;\r
+import android.webkit.WebView;\r
import android.widget.AdapterView;\r
import android.widget.AdapterView.AdapterContextMenuInfo;\r
import android.widget.BaseAdapter;\r
}\r
\r
{\r
- final MenuItem dictionaryList = menu.add(getString(R.string.dictionaryList));\r
+ final MenuItem dictionaryList = menu.add(getString(R.string.dictionaryManager));\r
dictionaryList.setOnMenuItemClickListener(new OnMenuItemClickListener() {\r
public boolean onMenuItemClick(final MenuItem menuItem) {\r
startActivity(DictionaryManagerActivity.getIntent(DictionaryActivity.this));\r
});\r
}\r
\r
- {\r
- final MenuItem dictionaryEdit = menu.add(getString(R.string.editDictionary));\r
- dictionaryEdit.setOnMenuItemClickListener(new OnMenuItemClickListener() {\r
- public boolean onMenuItemClick(final MenuItem menuItem) {\r
- final Intent intent = DictionaryEditActivity.getIntent(dictIndex);\r
- startActivity(intent);\r
- return false;\r
- }\r
- });\r
- }\r
-\r
{\r
final MenuItem about = menu.add(getString(R.string.about));\r
about.setOnMenuItemClickListener(new OnMenuItemClickListener() {\r
return true;\r
}\r
if (keyCode == KeyEvent.KEYCODE_BACK) {\r
+ Log.d(LOG, "Clearing dictionary prefs.");\r
+ DictionaryActivity.clearDictionaryPrefs(this);\r
}\r
if (keyCode == KeyEvent.KEYCODE_ENTER) {\r
Log.d(LOG, "Trying to hide soft keyboard.");\r
}\r
\r
private View getView(PairEntry.Row row, ViewGroup parent) {\r
- final TableLayout result = new TableLayout(parent.getContext());\r
+ final WebView result = new WebView(parent.getContext());\r
final PairEntry entry = row.getEntry();\r
final int rowCount = entry.pairs.size();\r
+ final StringBuilder html = new StringBuilder();\r
+ html.append("<html><table width=\"100%\">");\r
for (int r = 0; r < rowCount; ++r) {\r
- final TableRow tableRow = new TableRow(result.getContext());\r
+ html.append("<tr>");\r
\r
- final EditText column1 = new EditText(tableRow.getContext());\r
- final EditText column2 = new EditText(tableRow.getContext());\r
- final TableRow.LayoutParams layoutParams = new TableRow.LayoutParams();\r
- layoutParams.weight = 0.5f;\r
+ final Pair pair = entry.pairs.get(r);\r
+ // TODO: escape both the token and the text.\r
+ final String token = row.getTokenRow(true).getToken();\r
+ final String col1Text = index.swapPairEntries ? pair.lang2 : pair.lang1;\r
+ final String col2Text = index.swapPairEntries ? pair.lang1 : pair.lang2;\r
+ \r
+ col1Text.replaceAll(token, String.format("<b>%s</b", token));\r
\r
+ // Column1\r
+ html.append("<td width=\"50%\">");\r
if (r > 0) {\r
- final TextView spacer = new TextView(tableRow.getContext());\r
- spacer.setText(" • ");\r
- tableRow.addView(spacer);\r
+ html.append("<li>");\r
}\r
- tableRow.addView(column1, layoutParams);\r
- if (r > 0) {\r
- final TextView spacer = new TextView(tableRow.getContext());\r
- spacer.setText(" • ");\r
- tableRow.addView(spacer);\r
- }\r
- tableRow.addView(column2, layoutParams);\r
-\r
- column1.setWidth(1);\r
- column2.setWidth(1);\r
+ html.append(col1Text);\r
+ html.append("</td>");\r
\r
- // TODO: color words by gender\r
- final Pair pair = entry.pairs.get(r);\r
- final String col1Text = Language.fixBidiText(index.swapPairEntries ? pair.lang2 : pair.lang1);\r
- column1.setText(col1Text, TextView.BufferType.SPANNABLE);\r
- final Spannable col1Spannable = (Spannable) column1.getText();\r
- \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
+ // Column2\r
+ html.append("<td width=\"50%\">");\r
+ if (r > 0) {\r
+ html.append("<li>");\r
}\r
+ html.append(col2Text);\r
+ html.append("</td>");\r
\r
- String col2Text = index.swapPairEntries ? pair.lang1 : pair.lang2;\r
- col2Text = Language.fixBidiText(col2Text);\r
- column2.setText(col2Text, TextView.BufferType.NORMAL);\r
- \r
- column1.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp);\r
- column2.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp);\r
- column2.setBackgroundResource(theme.otherLangBg);\r
- \r
- column2.setOnLongClickListener(new EditText.OnLongClickListener() {\r
- @Override\r
- public boolean onLongClick(View v) {\r
- final int start = column2.getSelectionStart();\r
- final int end = column2.getSelectionStart();\r
- Log.i(LOG, "Long click on: " + column2.getText().toString().substring(start, end));\r
- return false;\r
- }\r
- });\r
+// column1.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp);\r
+// column2.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp);\r
\r
- result.addView(tableRow);\r
+ html.append("</tr>");\r
}\r
+ html.append("</html></table>");\r
+ \r
+ result.loadData(html.toString(), "text/html", null);\r
\r
return result;\r
}\r
}
});
- 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));
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() {
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];
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);
-
+
}
public final List<EntrySource> sources;
public final List<Index> indices;
+ /**
+ * dictFileVersion 1 adds:
+ * <li> counts of tokens in indices.
+ * <li> links to sources?
+ */
+
public Dictionary(final String dictInfo) {
- this.dictFileVersion = 0;
+ this.dictFileVersion = 1;
this.creationMillis = System.currentTimeMillis();
this.dictInfo = dictInfo;
pairEntries = new ArrayList<PairEntry>();
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<EntrySource> rafSources = RAFList.create(raf, EntrySource.SERIALIZER, raf.getFilePointer());
+ sources = new ArrayList<EntrySource>(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)) {
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);
}
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
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);
}
};
\r
package com.hughes.android.dictionary.engine;\r
\r
+import java.util.ArrayList;\r
import java.util.LinkedHashMap;\r
import java.util.Locale;\r
import java.util.Map;\r
isoCodeToResourceId.put("CI", R.string.CI);\r
isoCodeToResourceId.put("YI", R.string.YI);\r
isoCodeToResourceId.put("ZU", R.string.ZU);\r
+ \r
+ // Hack to allow lower-case ISO codes to work:\r
+ for (final String isoCode : new ArrayList<String>(isoCodeToResourceId.keySet())) {\r
+ isoCodeToResourceId.put(isoCode.toLowerCase(), isoCodeToResourceId.get(isoCode));\r
+ }\r
}\r
\r
\r
*/\r
private static final String rtlChars =\r
"\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC";\r
- private static final Pattern RTL_TOKEN = Pattern.compile("[" + rtlChars + "]+");\r
+ private static final Pattern RTL_TOKEN = Pattern.compile("[" + rtlChars + "]");\r
\r
public static String fixBidiText(final String text) {\r
- return RTL_TOKEN.matcher(text).replaceAll("\u200e $0 \u200e");\r
+ // TODO: fix me!, use me!\r
+ return text;\r
}\r
\r
// ----------------------------------------------------------------\r
public final List<Pair> pairs;
- public PairEntry() {
- pairs = new ArrayList<Pair>(1);
+ public PairEntry(final EntrySource entrySource) {
+ super(entrySource);
+ pairs = new ArrayList<Pair>(1);
}
- public PairEntry(final String lang1, final String lang2) {
- pairs = new ArrayList<Pair>(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<PairEntry.Pair>(size);
for (int i = 0; i < size; ++i) {
}
@Override
public void write(RandomAccessFile raf) throws IOException {
+ super.write(raf);
// TODO: this could be a short.
raf.writeInt(pairs.size());
for (int i = 0; i < pairs.size(); ++i) {
+ assert pairs.get(i).lang1.length() > 0;
raf.writeUTF(pairs.get(i).lang1);
raf.writeUTF(pairs.get(i).lang2);
}
}
- static final RAFSerializer<PairEntry> SERIALIZER = new RAFSerializer<PairEntry>() {
+ static final class Serializer implements RAFSerializer<PairEntry> {
+
+ 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
final String text;
- public TextEntry(final RandomAccessFile raf) throws IOException {
+ public TextEntry(final Dictionary dictionary, final RandomAccessFile raf) throws IOException {
+ super(dictionary, raf);
text = raf.readUTF();
}
@Override
public void write(RandomAccessFile raf) throws IOException {
+ super.write(raf);
raf.writeUTF(text);
}
- static final RAFSerializer<TextEntry> SERIALIZER = new RAFSerializer<TextEntry>() {
+ static final class Serializer implements RAFSerializer<TextEntry> {
+
+ 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
t.write(raf);
}
};
+
@Override
public int addToDictionary(final Dictionary dictionary) {