android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:background="@drawable/icon"></ImageView>
- <TextView android:text=" Dictionary 1.0" android:id="@+id/title"
+ <TextView android:id="@+id/title"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="wrap_content" android:layout_height="wrap_content"
- android:layout_gravity="center_vertical|fill_vertical"></TextView>
+ android:layout_gravity="center_vertical|fill_vertical" android:text="QuickDic 1.0"></TextView>
</LinearLayout>
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"></TextView>
- <TextView android:text="thughes@cs.stanford.edu" android:id="@+id/email"
+ <TextView android:text=" " android:id="@+id/space3"
android:layout_width="wrap_content" android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal" android:autoLink="email"
- android:clickable="true"></TextView>
+ android:layout_gravity="center_horizontal"></TextView>
+
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content" android:id="@+id/emailMe"
+ android:text="If you're using QuickDic, I'd love to hear from you. Please send comments, suggestions, bug reports, or just a quick hello to:"></TextView>
+
+ <TextView android:id="@+id/email" android:layout_width="wrap_content"
+ android:layout_height="wrap_content" android:autoLink="email" android:clickable="true"
+ android:text="thad.hughes+quickdic@gmail.com" android:layout_gravity="left"></TextView>
<TextView android:text=" " android:id="@+id/space2"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"></TextView>
- <TextView android:text="Current dictionary info" android:id="@+id/currentDictInfoTitle"
+ <TextView android:id="@+id/currentDictInfoTitle"
android:textAppearance="?android:attr/textAppearanceLarge"
- android:layout_width="fill_parent" android:layout_height="wrap_content"></TextView>
+ android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Current dictionary info:"></TextView>
<TextView android:text="No dictionary loaded." android:id="@+id/currentDictInfo"
android:layout_width="fill_parent" android:layout_height="wrap_content"></TextView>
+
</LinearLayout>
<ProgressBar android:id="@+id/downloadProgressBar"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:indeterminate="false"></ProgressBar>
- <TextView android:id="@+id/downloadComplete" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:text="Download complete." android:visibility="invisible"></TextView>
+ <TextView android:id="@+id/downloadStatus" android:layout_width="wrap_content"
+ android:layout_height="wrap_content" android:visibility="visible" android:text="Download status."></TextView>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="app_name">Dictionary</string>
-<string name="about_text">Dictionary\nby Thad Hughes</string>
+ <string name="app_name">QuickDic</string>
+<string name="about_text">QuickDic\nby Thad Hughes</string>
<string name="wordListFile">wordListFile</string>
<string name="dictFile">dictFile</string>
static final RAFSerializer<IndexEntry> INDEX_ENTRY_SERIALIZER = new RAFSerializableSerializer<IndexEntry>(\r
IndexEntry.RAF_FACTORY);\r
\r
+ final String dictionaryInfo;\r
final List<Entry> entries;\r
final LanguageData[] languageDatas = new LanguageData[2];\r
\r
- public Dictionary(final Language language0, final Language language1) {\r
+ public Dictionary(final String dictionaryInfo, final Language language0, final Language language1) {\r
+ this.dictionaryInfo = dictionaryInfo;\r
languageDatas[0] = new LanguageData(this, language0, Entry.LANG1);\r
languageDatas[1] = new LanguageData(this, language1, Entry.LANG2);\r
entries = new ArrayList<Entry>();\r
}\r
\r
public Dictionary(final RandomAccessFile raf) throws IOException {\r
+ dictionaryInfo = raf.readUTF();\r
entries = CachingList.create(FileList.create(raf, ENTRY_SERIALIZER, raf\r
.getFilePointer()), 10000);\r
languageDatas[0] = new LanguageData(this, raf, Entry.LANG1);\r
}\r
\r
public void write(RandomAccessFile raf) throws IOException {\r
+ raf.writeUTF(dictionaryInfo);\r
FileList.write(raf, entries, ENTRY_SERIALIZER);\r
languageDatas[0].write(raf);\r
languageDatas[1].write(raf);\r
DICT_FETCH_URL = getResources().getString(R.string.dictFetchUrl);
Log.d("THAD", "onCreate");
-
-
}
@Override
dictionaryListAdapter.notifyDataSetChanged();
Log.d("THAD", "Unable to read dictionary file.");
final AlertDialog alert = new AlertDialog.Builder(DictionaryActivity.this).create();
- alert.setMessage("Unable to read dictionary file: " + wordList.getAbsolutePath());
- alert.setButton("Download dictionary from Internet", new DialogInterface.OnClickListener() {
+ alert.setMessage("Unable to read dictionary file: " + dictFile.getAbsolutePath());
+ alert.setButton("Download dictionary", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
startDownloadDictActivity();
}});
final Button upButton = (Button) findViewById(R.id.UpButton);
upButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
+ if (dictionary == null) {
+ return;
+ }
final int destRowIndex;
final Row tokenRow = activeLangaugeData.rows.get(selectedTokenRowIndex);
assert tokenRow.isToken();
final Button downButton = (Button) findViewById(R.id.DownButton);
downButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
+ if (dictionary == null) {
+ return;
+ }
final Row tokenRow = activeLangaugeData.rows.get(selectedTokenRowIndex);
assert tokenRow.isToken();
final int nextTokenIndex = tokenRow.getIndex() + 1;
if (dictionary == null) {
currentDictInfo.append("No dictionary loaded.");
} else {
+ currentDictInfo.append(dictionary.dictionaryInfo).append("\n\n");
currentDictInfo.append("Entry count: " + dictionary.entries.size()).append("\n");
for (int i = 0; i < 2; ++i) {
final LanguageData languageData = dictionary.languageDatas[i];
}
void switchLanguage() {
+ if (dictionary == null) {
+ return;
+ }
activeLangaugeData = dictionary.languageDatas[(activeLangaugeData == dictionary.languageDatas[0]) ? 1 : 0];
selectedRowIndex = 0;
selectedTokenRowIndex = 0;
void onSearchTextChange(final String searchText) {
Log.d("THAD", "onSearchTextChange: " + searchText);
+ if (dictionary == null) {
+ return;
+ }
if (searchOperation != null) {
searchOperation.interrupted.set(true);
}
tableRow.addView(spacer);
}
tableRow.addView(column1, layoutParams);
- if (r>0){
+ if (r > 0) {
final TextView spacer = new TextView(tableRow.getContext());
spacer.setText(r == 0 ? "\95 " : " \95 ");
tableRow.addView(spacer);
package com.hughes.android.dictionary;\r
\r
+import java.io.File;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.net.URL;\r
import java.util.concurrent.Executor;\r
import java.util.concurrent.Executors;\r
\r
import android.os.Bundle;\r
import android.os.Handler;\r
import android.util.Log;\r
-import android.view.View;\r
import android.widget.ProgressBar;\r
import android.widget.TextView;\r
\r
\r
String source;\r
String dest;\r
- \r
+\r
private final Executor downloadExecutor = Executors.newSingleThreadExecutor();\r
private final Handler uiHandler = new Handler();\r
\r
throw new RuntimeException("null source or dest.");\r
}\r
setContentView(R.layout.download);\r
- \r
+\r
final TextView sourceTextView = (TextView) findViewById(R.id.source);\r
sourceTextView.setText(source);\r
- \r
+\r
final TextView destTextView = (TextView) findViewById(R.id.dest);\r
destTextView.setText(dest);\r
\r
progressBar.setIndeterminate(false);\r
progressBar.setMax(100);\r
\r
+ final InputStream in;\r
+ final FileOutputStream out;\r
+ \r
+ final File destFile = new File(dest);\r
+ final File destTmpFile;\r
+ try {\r
+ destTmpFile = File.createTempFile("dictionaryDownload", "tmp", destFile.getParentFile());\r
+ final URL uri = new URL(source);\r
+ in = uri.openStream();\r
+ out = new FileOutputStream(destTmpFile);\r
+ } catch (Exception e) {\r
+ Log.e("THAD", "Error downloading file", e);\r
+ setDownloadStatus("Error downloading file: \n" + e.getLocalizedMessage());\r
+ return;\r
+ }\r
+\r
final Runnable runnable = new Runnable() {\r
public void run() {\r
- \r
- for (int i = 0; i < 100; ++i) {\r
- \r
- final int progress = i;\r
- uiHandler.post(new Runnable() {\r
- public void run() {\r
- Log.d("THAD", "Setting progress: " + progress);\r
- progressBar.setProgress(progress);\r
- }\r
- });\r
- \r
- try {\r
- Thread.sleep(100);\r
- } catch (InterruptedException e) {\r
- e.printStackTrace();\r
+ try {\r
+ long byteCount = 0;\r
+ int bytesRead;\r
+ final byte[] bytes = new byte[4096];\r
+ while ((bytesRead = in.read(bytes)) != -1) {\r
+ out.write(bytes, 0, bytesRead);\r
+ byteCount += bytesRead;\r
+ setDownloadStatus(String.format("Downloading: %d bytes so far", byteCount));\r
}\r
+ in.close();\r
+ out.close();\r
+ destFile.delete();\r
+ destTmpFile.renameTo(destFile);\r
+ setDownloadStatus(String.format("Downloaded finished: %d bytes", byteCount));\r
+ } catch (IOException e) {\r
+ Log.e("THAD", "Error downloading file", e);\r
+ setDownloadStatus("Error downloading file: \n" + e.getLocalizedMessage());\r
}\r
- \r
- final TextView downloadComplete = (TextView) findViewById(R.id.downloadComplete);\r
- uiHandler.post(new Runnable() {\r
- public void run() {\r
- progressBar.setProgress(100);\r
- downloadComplete.setVisibility(View.VISIBLE);\r
- }\r
- });\r
- \r
- }};\r
+ }\r
+ };\r
+\r
downloadExecutor.execute(runnable);\r
- \r
}\r
- \r
+\r
+ private void setDownloadStatus(final String status) {\r
+ final TextView downloadStatus = (TextView) findViewById(R.id.downloadStatus);\r
+ uiHandler.post(new Runnable() {\r
+ public void run() {\r
+ downloadStatus.setText(status);\r
+ }\r
+ });\r
+ }\r
+\r
}\r
\r
public Set<String> getIndexableTokens(final byte lang) {\r
final Set<String> result = new LinkedHashSet<String>();\r
- String text = Arrays.asList(getAllText(lang)).toString();\r
+ String text = " ";\r
+ for (final String subentry : getAllText(lang)) {\r
+ text += subentry + " ";\r
+ }\r
\r
text = text.replaceAll("fig\\.", " ");\r
text = text.replaceAll("\\{[^\\}]+}", " ");\r
text = text.replaceAll("\"-", "-");\r
text = text.replaceAll("-\"", "-");\r
- text = text.replaceAll("[\":/\\()<>\\[\\],;?!.]", " ");\r
+ text = text.replaceAll("[\"/\\()<>\\[\\],;?!.]", " ");\r
+ text = text.replaceAll("[:] ", " ");\r
+ text = text.replaceAll(" [:]", " ");\r
result.addAll(Arrays.asList(WHITESPACE.split(text)));\r
\r
text = text.replaceAll("[-]", " ");\r
if (c != 0) {\r
return c;\r
}\r
- return StringUtil.reverse(s1).compareTo(StringUtil.reverse(s2));\r
+ return StringUtil.flipCase(StringUtil.reverse(s1)).compareTo(StringUtil.flipCase(StringUtil.reverse(s2)));\r
}};\r
}\r
\r
\r
\r
// ----------------------------------------------------------------\r
+ \r
+ static final String normalizeTokenForSort(final String token, final boolean vowelETranslation) {\r
+ final StringBuilder result = new StringBuilder();\r
+ for (int i = 0; i < token.length(); ++i) {\r
+ Character c = token.charAt(i);\r
+ c = Character.toLowerCase(c);\r
+ // only check for lowercase 'e' in subsequent position means don't treat acronyms as umlauted: SAE.\r
+ if (vowelETranslation && (c == 'a' || c == 'o' || c == 'u') && i + 1 < token.length() && token.charAt(i + 1) == 'e') {\r
+ if (c == 'a') {\r
+ result.append('ä');\r
+ } else if (c == 'o') {\r
+ result.append('ö');\r
+ } else if (c == 'u') {\r
+ result.append('ü');\r
+ }\r
+ ++i;\r
+ } else if (c >= 'a' && c <= 'z' || c >= '0' && c <= '9') {\r
+ result.append(c);\r
+ } else if (c == 'ß') {\r
+ result.append("ss");\r
+ } else if (c == 'ä') {\r
+ result.append(c);\r
+ } else if (c == 'ö') {\r
+ result.append(c);\r
+ } else if (c == 'ü') {\r
+ result.append(c);\r
+ }\r
+ }\r
+ return result.toString();\r
+ }\r
\r
public static final Language EN = new Language("EN") {\r
@Override\r
public String normalizeTokenForSort(final String token) {\r
- return token.toLowerCase().replaceAll("ß", "ss").replaceAll("ä", "a")\r
- .replaceAll("ö", "o").replaceAll("ü", "u").replaceAll("[^A-Za-z0-9]",\r
- "");\r
+ return Language.normalizeTokenForSort(token, false);\r
}\r
};\r
-\r
+ \r
public static final Language DE = new Language("DE") {\r
@Override\r
String normalizeTokenForSort(final String token) {\r
- return token.toLowerCase().replaceAll("ß", "ss").replaceAll("ä", "a")\r
- .replaceAll("ae", "a").replaceAll("ö", "o").replaceAll("oe", "o")\r
- .replaceAll("ü", "u").replaceAll("ue", "u").replaceAll(\r
- "[^A-Za-z0-9]", "");\r
+ return Language.normalizeTokenForSort(token, true);\r
}\r
};\r
\r
public static final int icon=0x7f020000;\r
}\r
public static final class id {\r
- public static final int DownButton=0x7f060019;\r
+ public static final int DownButton=0x7f06001b;\r
public static final int ImageView01=0x7f060002;\r
- public static final int LangButton=0x7f060018;\r
+ public static final int LangButton=0x7f06001a;\r
public static final int LinearLayout01=0x7f060000;\r
public static final int LinearLayout02=0x7f060001;\r
- public static final int SearchBarLinearLayout=0x7f060014;\r
- public static final int SearchBarTableLayout=0x7f060015;\r
- public static final int SearchBarTableRow=0x7f060016;\r
- public static final int SearchText=0x7f060017;\r
- public static final int TextView01=0x7f06000b;\r
- public static final int UpButton=0x7f06001a;\r
+ public static final int SearchBarLinearLayout=0x7f060016;\r
+ public static final int SearchBarTableLayout=0x7f060017;\r
+ public static final int SearchBarTableRow=0x7f060018;\r
+ public static final int SearchText=0x7f060019;\r
+ public static final int TextView01=0x7f06000d;\r
+ public static final int UpButton=0x7f06001c;\r
public static final int author=0x7f060006;\r
public static final int copyright=0x7f060005;\r
- public static final int currentDictInfo=0x7f06000a;\r
- public static final int currentDictInfoTitle=0x7f060009;\r
- public static final int dest=0x7f060011;\r
- public static final int destLayout=0x7f06000f;\r
- public static final int destTitle=0x7f060010;\r
- public static final int downloadComplete=0x7f060013;\r
- public static final int downloadProgressBar=0x7f060012;\r
- public static final int email=0x7f060007;\r
- public static final int source=0x7f06000e;\r
- public static final int sourceLayout=0x7f06000c;\r
- public static final int sourceTitle=0x7f06000d;\r
+ public static final int currentDictInfo=0x7f06000c;\r
+ public static final int currentDictInfoTitle=0x7f06000b;\r
+ public static final int dest=0x7f060013;\r
+ public static final int destLayout=0x7f060011;\r
+ public static final int destTitle=0x7f060012;\r
+ public static final int downloadProgressBar=0x7f060014;\r
+ public static final int downloadStatus=0x7f060015;\r
+ public static final int email=0x7f060009;\r
+ public static final int emailMe=0x7f060008;\r
+ public static final int source=0x7f060010;\r
+ public static final int sourceLayout=0x7f06000e;\r
+ public static final int sourceTitle=0x7f06000f;\r
public static final int space1=0x7f060004;\r
- public static final int space2=0x7f060008;\r
+ public static final int space2=0x7f06000a;\r
+ public static final int space3=0x7f060007;\r
public static final int title=0x7f060003;\r
}\r
public static final class layout {\r