-import com.ibm.icu.text.Collator;
-
-public class DictionaryApplication extends Application {
-
- static final String LOG = "QuickDicApp";
-
- private static final File DICT_DIR = new File(Environment.getExternalStorageDirectory().getName(), "quickdic");
-
- // Static, determined by resources (and locale).
- // Unordered.
- static Map<String,DictionaryInfo> DOWNLOADABLE_NAME_TO_INFO = null;
-
- static final class DictionaryConfig implements Serializable {
- private static final long serialVersionUID = -1444177164708201262L;
- // User-ordered list, persisted, just the ones that are/have been present.
- final List<DictionaryInfo> dictionaryFilesOrdered = new ArrayList<DictionaryInfo>();
- final Set<String> invalidatedFilenames = new LinkedHashSet<String>();
- }
- DictionaryConfig dictionaryConfig = null;
-
- static final class DictionaryHistory implements Serializable {
- private static final long serialVersionUID = -4842995032541390284L;
- // User-ordered list, persisted, just the ones that are/have been present.
- final List<DictionaryLink> dictionaryLinks = new ArrayList<DictionaryLink>();
- }
- DictionaryHistory dictionaryHistory = null;
-
-
- @Override
- public void onCreate() {
- super.onCreate();
- Log.d("QuickDic", "Application: onCreate");
- TransliteratorManager.init(null);
- staticInit(getApplicationContext());
-
- // Load the dictionaries we know about.
- dictionaryConfig = PersistentObjectCache.init(getApplicationContext()).read(C.DICTIONARY_CONFIGS, DictionaryConfig.class);
- if (dictionaryConfig == null) {
- dictionaryConfig = new DictionaryConfig();
+import com.hughes.util.ListUtil;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+public enum DictionaryApplication {
+ INSTANCE;
+
+ private Context appContext;
+
+ static final String LOG = "QuickDicApp";
+
+ // If set to false, avoid use of ICU collator
+ // Works well enough for most european languages,
+ // gives faster startup and avoids crashes on some
+ // devices due to Dalvik bugs (e.g. ARMv6, S5570i, CM11)
+ // when using ICU4J.
+ // Leave it enabled by default for correctness except
+ // for my known broken development/performance test device config.
+ //static public final boolean USE_COLLATOR = !android.os.Build.FINGERPRINT.equals("Samsung/cm_tassve/tassve:4.4.4/KTU84Q/20150211:userdebug/release-keys");
+ public static final boolean USE_COLLATOR = true;
+
+ public static final TransliteratorManager.ThreadSetup threadBackground = new TransliteratorManager.ThreadSetup() {
+ @Override
+ public void onThreadStart() {
+ // THREAD_PRIORITY_BACKGROUND seemed like a good idea, but it
+ // can make Transliterator go from 20 seconds to 3 minutes (!)
+ android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
+ }
+ };
+
+ // Static, determined by resources (and locale).
+ // Unordered.
+ static Map<String, DictionaryInfo> DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO = null;
+
+ enum Theme {
+ DEFAULT(R.style.Theme_Default,
+ R.style.Theme_Default_TokenRow_Fg,
+ R.color.theme_default_token_row_fg,
+ R.drawable.theme_default_token_row_main_bg,
+ R.drawable.theme_default_token_row_other_bg,
+ R.drawable.theme_default_normal_row_bg),
+
+ LIGHT(R.style.Theme_Light,
+ R.style.Theme_Light_TokenRow_Fg,
+ R.color.theme_light_token_row_fg,
+ R.drawable.theme_light_token_row_main_bg,
+ R.drawable.theme_light_token_row_other_bg,
+ R.drawable.theme_light_normal_row_bg);
+
+ Theme(final int themeId, final int tokenRowFg,
+ final int tokenRowFgColor,
+ final int tokenRowMainBg, final int tokenRowOtherBg,
+ final int normalRowBg) {
+ this.themeId = themeId;
+ this.tokenRowFg = tokenRowFg;
+ this.tokenRowFgColor = tokenRowFgColor;
+ this.tokenRowMainBg = tokenRowMainBg;
+ this.tokenRowOtherBg = tokenRowOtherBg;
+ this.normalRowBg = normalRowBg;
+ }
+
+ final int themeId;
+ final int tokenRowFg;
+ final int tokenRowFgColor;
+ final int tokenRowMainBg;
+ final int tokenRowOtherBg;
+ final int normalRowBg;
+ }
+
+ public static final class DictionaryConfig implements Serializable {
+ private static final long serialVersionUID = -1444177164708201263L;
+ // User-ordered list, persisted, just the ones that are/have been
+ // present.
+ final List<String> dictionaryFilesOrdered = new ArrayList<>();
+
+ final Map<String, DictionaryInfo> uncompressedFilenameToDictionaryInfo = new HashMap<>();
+
+ /**
+ * Sometimes a deserialized version of this data structure isn't valid.
+ */
+ @SuppressWarnings("ConstantConditions")
+ boolean isValid() {
+ return uncompressedFilenameToDictionaryInfo != null && dictionaryFilesOrdered != null;
+ }
+ }
+
+ DictionaryConfig dictionaryConfig = null;
+
+ public int languageButtonPixels = -1;
+
+ static synchronized void staticInit(final Context context) {
+ if (DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO != null) {
+ return;
+ }
+ DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO = new HashMap<>();
+ final BufferedReader reader = new BufferedReader(
+ new InputStreamReader(context.getResources().openRawResource(R.raw.dictionary_info)));
+ try {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ if (line.length() == 0 || line.charAt(0) == '#') {
+ continue;
+ }
+ final DictionaryInfo dictionaryInfo = new DictionaryInfo(line);
+ DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.put(
+ dictionaryInfo.uncompressedFilename, dictionaryInfo);
+ }
+ } catch (IOException e) {
+ Log.e(LOG, "Failed to load downloadable dictionary lists.", e);
+ }
+ try {
+ reader.close();
+ } catch (IOException ignored) {}
+ }
+
+ public synchronized void init(Context c) {
+ if (appContext != null) {
+ assert c == appContext;
+ return;
+ }
+ appContext = c;
+ Log.d("QuickDic", "Application: onCreate");
+ TransliteratorManager.init(null, threadBackground);
+ staticInit(appContext);
+
+ languageButtonPixels = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP, 60, appContext.getResources().getDisplayMetrics());
+
+ // Load the dictionaries we know about.
+ dictionaryConfig = PersistentObjectCache.init(appContext).read(
+ C.DICTIONARY_CONFIGS, DictionaryConfig.class);
+ if (dictionaryConfig == null) {
+ dictionaryConfig = new DictionaryConfig();
+ }
+ if (!dictionaryConfig.isValid()) {
+ dictionaryConfig = new DictionaryConfig();
+ }
+
+ // Theme stuff.
+ appContext.setTheme(getSelectedTheme().themeId);
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext);
+ prefs.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+ String key) {
+ Log.d("QuickDic", "prefs changed: " + key);
+ if (key.equals(appContext.getString(R.string.themeKey))) {
+ appContext.setTheme(getSelectedTheme().themeId);
+ }
+ }
+ });