diff --git a/.classpath b/.classpath
index 609aa00..7bc01d9 100644
--- a/.classpath
+++ b/.classpath
@@ -3,5 +3,7 @@
-
+
+
+
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ca5f575..4ac8205 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -6,35 +6,30 @@
+ android:targetSdkVersion="18" />
-
-
-
+
diff --git a/README.txt b/README.txt
index 5a91d73..465fa9b 100644
--- a/README.txt
+++ b/README.txt
@@ -1,7 +1,7 @@
README
=======
-Copyright (C) 2011-2012 Takahiro Yoshimura
+Copyright (C) 2011-2013 Takahiro Yoshimura
This is a simple text-like file viewer application for the Android
platform. It is also my learning project.
@@ -34,10 +34,11 @@ It is available at: https://gist.github.com/1223663 .
Thanks to the jchardet project (http://jchardet.sourceforge.net/).
- * 2 color themes
+ * 4 color themes
White-on-black (energy saving on OLED display, and eye saver under
dark conditions) and black-on-white are supported.
+ Update: Solarized Color theme (dark & light)
* Configurable font size
@@ -46,6 +47,10 @@ It is available at: https://gist.github.com/1223663 .
* Words-searching/finding
* Selectable/copyable text (only in Honeycomb or above)
+
+ * Now, it can choose text file from installed file manager
+
+ * Recent files
2. BUGS
@@ -64,3 +69,8 @@ Character set detection is done with the jchardet project
Word searching, text selection/copy feature is kindly contributed by
Renjaya Raga Zenta .
+
+Solarized Color: Precision colors for machines and people
+(http://ethanschoonover.com/solarized)
+
+Saving recent files use ObjectSerializer (https://github.com/apache/pig)
diff --git a/project.properties b/project.properties
index 5b44c8c..f5544e2 100644
--- a/project.properties
+++ b/project.properties
@@ -11,4 +11,5 @@
proguard.config=etc/proguard/android.txt:etc/proguard/project.txt
# Project target.
-target=android-17
+target=android-18
+android.library.reference.1=../../android-sdk-linux/extras/android/support/v7/appcompat
diff --git a/res/drawable-hdpi-v11/cancel.png b/res/drawable-hdpi-v11/cancel.png
deleted file mode 100644
index 094eea5..0000000
Binary files a/res/drawable-hdpi-v11/cancel.png and /dev/null differ
diff --git a/res/drawable-hdpi-v11/next.png b/res/drawable-hdpi-v11/next.png
deleted file mode 100644
index 50b1587..0000000
Binary files a/res/drawable-hdpi-v11/next.png and /dev/null differ
diff --git a/res/drawable-hdpi-v11/previous.png b/res/drawable-hdpi-v11/previous.png
deleted file mode 100644
index 64538ce..0000000
Binary files a/res/drawable-hdpi-v11/previous.png and /dev/null differ
diff --git a/res/drawable-hdpi-v11/action_search.png b/res/drawable-hdpi/action_search.png
similarity index 100%
rename from res/drawable-hdpi-v11/action_search.png
rename to res/drawable-hdpi/action_search.png
diff --git a/res/drawable-hdpi/cancel.png b/res/drawable-hdpi/cancel.png
index cde36e1..094eea5 100644
Binary files a/res/drawable-hdpi/cancel.png and b/res/drawable-hdpi/cancel.png differ
diff --git a/res/drawable-hdpi/drawer_shadow.9.png b/res/drawable-hdpi/drawer_shadow.9.png
new file mode 100644
index 0000000..224cc4f
Binary files /dev/null and b/res/drawable-hdpi/drawer_shadow.9.png differ
diff --git a/res/drawable-hdpi/ic_drawer.png b/res/drawable-hdpi/ic_drawer.png
new file mode 100644
index 0000000..ff7b1de
Binary files /dev/null and b/res/drawable-hdpi/ic_drawer.png differ
diff --git a/res/drawable-hdpi/next.png b/res/drawable-hdpi/next.png
index e6495b2..50b1587 100644
Binary files a/res/drawable-hdpi/next.png and b/res/drawable-hdpi/next.png differ
diff --git a/res/drawable-hdpi/previous.png b/res/drawable-hdpi/previous.png
index 23778ae..64538ce 100644
Binary files a/res/drawable-hdpi/previous.png and b/res/drawable-hdpi/previous.png differ
diff --git a/res/drawable-mdpi-v11/cancel.png b/res/drawable-mdpi-v11/cancel.png
deleted file mode 100644
index 3336760..0000000
Binary files a/res/drawable-mdpi-v11/cancel.png and /dev/null differ
diff --git a/res/drawable-mdpi-v11/next.png b/res/drawable-mdpi-v11/next.png
deleted file mode 100644
index 3fa4887..0000000
Binary files a/res/drawable-mdpi-v11/next.png and /dev/null differ
diff --git a/res/drawable-mdpi-v11/previous.png b/res/drawable-mdpi-v11/previous.png
deleted file mode 100644
index b8b3e1a..0000000
Binary files a/res/drawable-mdpi-v11/previous.png and /dev/null differ
diff --git a/res/drawable-mdpi-v11/action_search.png b/res/drawable-mdpi/action_search.png
similarity index 100%
rename from res/drawable-mdpi-v11/action_search.png
rename to res/drawable-mdpi/action_search.png
diff --git a/res/drawable-mdpi/cancel.png b/res/drawable-mdpi/cancel.png
index 9f4c3d6..3336760 100644
Binary files a/res/drawable-mdpi/cancel.png and b/res/drawable-mdpi/cancel.png differ
diff --git a/res/drawable-mdpi/drawer_shadow.9.png b/res/drawable-mdpi/drawer_shadow.9.png
new file mode 100644
index 0000000..3797f99
Binary files /dev/null and b/res/drawable-mdpi/drawer_shadow.9.png differ
diff --git a/res/drawable-mdpi/ic_drawer.png b/res/drawable-mdpi/ic_drawer.png
new file mode 100644
index 0000000..fb681ba
Binary files /dev/null and b/res/drawable-mdpi/ic_drawer.png differ
diff --git a/res/drawable-mdpi/next.png b/res/drawable-mdpi/next.png
index 88029a8..3fa4887 100644
Binary files a/res/drawable-mdpi/next.png and b/res/drawable-mdpi/next.png differ
diff --git a/res/drawable-mdpi/previous.png b/res/drawable-mdpi/previous.png
index 8d19e39..b8b3e1a 100644
Binary files a/res/drawable-mdpi/previous.png and b/res/drawable-mdpi/previous.png differ
diff --git a/res/layout-v11/main.xml b/res/layout-v11/viewer.xml
similarity index 74%
rename from res/layout-v11/main.xml
rename to res/layout-v11/viewer.xml
index c435ea7..e359b67 100644
--- a/res/layout-v11/main.xml
+++ b/res/layout-v11/viewer.xml
@@ -1,20 +1,39 @@
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+
+
+
+
+ android:background="?attr/dividerHorizontal" />
+ android:background="?attr/dividerHorizontal" />
-
-
-
-
-
\ No newline at end of file
diff --git a/res/layout/drawer_list_item.xml b/res/layout/drawer_list_item.xml
new file mode 100644
index 0000000..86f6ca7
--- /dev/null
+++ b/res/layout/drawer_list_item.xml
@@ -0,0 +1,14 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/main.xml b/res/layout/main.xml
index f4714aa..d4911d4 100644
--- a/res/layout/main.xml
+++ b/res/layout/main.xml
@@ -1,66 +1,30 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+ android:layout_gravity="center"
+ android:text="@string/browse_file" >
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/viewer.xml b/res/layout/viewer.xml
new file mode 100644
index 0000000..3554bb2
--- /dev/null
+++ b/res/layout/viewer.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/menu-v11/main.xml b/res/menu-v11/main.xml
deleted file mode 100644
index f85b485..0000000
--- a/res/menu-v11/main.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
\ No newline at end of file
diff --git a/res/menu/main.xml b/res/menu/main.xml
index 7881488..67956a1 100644
--- a/res/menu/main.xml
+++ b/res/menu/main.xml
@@ -2,12 +2,13 @@
\ No newline at end of file
diff --git a/res/menu/viewer.xml b/res/menu/viewer.xml
new file mode 100644
index 0000000..4468da5
--- /dev/null
+++ b/res/menu/viewer.xml
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/res/values-ja/arrays.xml b/res/values-ja/arrays.xml
index 1aef267..dca4e91 100644
--- a/res/values-ja/arrays.xml
+++ b/res/values-ja/arrays.xml
@@ -3,6 +3,8 @@
- 黒地に白
- 白地に黒
+ - Solarizedさ暗い
+ - Solarizedさ光
- 1画面
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 189fbe4..14d1a73 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -1,12 +1,15 @@
テキスト見本です。\nファイルマネージャなどのアプリを使用して、表示したいファイルを読み込んで下さい。
+ テキストファイルをブラウズ
+ 最近使ったファイル
設定
- 探す
+ オープンファイル
+ 明確な最近のファイル
+ 探す
文字の配色
文字のサイズ
等幅フォントを使用する
- タイトルバーを表示する
音量キーでスクロール
スクロール幅
主な言語
diff --git a/res/values-v11/styles.xml b/res/values-v11/styles.xml
deleted file mode 100644
index 7234bfc..0000000
--- a/res/values-v11/styles.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/values-v14/styles.xml b/res/values-v14/styles.xml
deleted file mode 100644
index 7234bfc..0000000
--- a/res/values-v14/styles.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 466c05c..d821dba 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -3,10 +3,14 @@
- White on black
- Black on white
+ - Solarized Dark
+ - Solarized Light
- black
- white
+ - solarized_dark
+ - solarized_light
- 8
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8209322..3898d5f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1,14 +1,19 @@
Text Viewer
- 0.1.8
+ 0.2.0
This is an example text.\nPlease use something like file-manager to open a text-like file.
- Preferences
- Search
+ Browse text files
+ Recent files
+ Settings
+ Open File
+ Clear Recent Files
+ Search
+ Open navigation drawer
+ Close navigation drawer
Color theme
Font size
Use monospace fonts
- Show title bar
Scroll by volume keys
Scroll height
Preferred Lang.
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 66e522e..ed1a705 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -1,6 +1,32 @@
-
+
-
+
+
+
+
+
+
+
+
+ #333333
+ #99000000
\ No newline at end of file
diff --git a/res/xml/config.xml b/res/xml/config.xml
index 3820874..5d9d891 100644
--- a/res/xml/config.xml
+++ b/res/xml/config.xml
@@ -11,16 +11,12 @@
-
= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ getActionBar().setHomeButtonEnabled(true);
+ }
this.colortheme = (ListPreference) getPreferenceScreen()
.findPreference(ConfigKey.COLORTHEME);
@@ -44,6 +54,7 @@ protected void onCreate(Bundle savedInstanceState) {
.findPreference(ConfigKey.CHARSET_PREFERENCE);
}
+ @SuppressWarnings("deprecation")
@Override
protected void onResume() {
super.onResume();
@@ -58,6 +69,7 @@ protected void onResume() {
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
+ @SuppressWarnings("deprecation")
@Override
protected void onPause() {
super.onPause();
@@ -85,4 +97,14 @@ private void updateSummary(SharedPreferences sharedPreferences, String key) {
this.charsetpreference
.setSummary(this.charsetpreference.getEntry());
}
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
}
diff --git a/src/com/gmail/altakey/dawne/NewMainActivity.java b/src/com/gmail/altakey/dawne/NewMainActivity.java
new file mode 100644
index 0000000..ad421e0
--- /dev/null
+++ b/src/com/gmail/altakey/dawne/NewMainActivity.java
@@ -0,0 +1,340 @@
+/**
+ * Copyright (C) 2011-2013 Takahiro Yoshimura, Renjaya Raga Zenta
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.gmail.altakey.dawne;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.preference.PreferenceManager;
+import android.support.v4.app.ActionBarDrawerToggle;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.ActionBarActivity;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.webkit.MimeTypeMap;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.ListView;
+import android.widget.Toast;
+
+import com.gmail.altakey.dawne.ViewerFragment.OnContentTapListener;
+import com.gmail.altakey.dawne.util.ConfigKey;
+import com.gmail.altakey.dawne.util.ObjectSerializer;
+import com.gmail.altakey.dawne.util.RecentFile;
+import com.gmail.altakey.dawne.util.StackRecentFiles;
+
+import java.io.IOException;
+
+public class NewMainActivity extends ActionBarActivity implements OnContentTapListener {
+
+ private static final int BROWSE_FILE_REQUEST_CODE = 4869;
+ private static final String TAG = "dawne";
+
+ private ActionBar mActionBar;
+ private DrawerLayout mDrawerLayout;
+ private ListView mDrawerList;
+ private ActionBarDrawerToggle mDrawerToggle;
+ private StackRecentFiles mStackRecentFiles;
+ private RecentFilesAdapter mDrawerAdapter;
+
+ private Handler mHandler;
+ private final Runnable mHideActionBarDelayed = new Runnable() {
+ @Override
+ public void run() {
+ mActionBar.hide();
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ mHandler = new Handler();
+
+ SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
+ String recentFiles = pref.getString(ConfigKey.RECENT_FILES, null);
+ if (recentFiles == null || recentFiles.equals("")) {
+ mStackRecentFiles = new StackRecentFiles();
+ } else {
+ try {
+ mStackRecentFiles = (StackRecentFiles) ObjectSerializer.deserialize(recentFiles);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ mActionBar = getSupportActionBar();
+ mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE
+ | ActionBar.DISPLAY_HOME_AS_UP);
+
+ mDrawerAdapter = new RecentFilesAdapter(this, mStackRecentFiles);
+ mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
+ mDrawerList = (ListView) findViewById(R.id.left_drawer);
+ mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
+ mDrawerList.setAdapter(mDrawerAdapter);
+ mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
+ mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer,
+ R.string.drawer_open, R.string.drawer_close) {
+
+ @Override
+ public void onDrawerClosed(View drawerView) {
+ final ViewerFragment f = (ViewerFragment) getSupportFragmentManager()
+ .findFragmentById(R.id.content_frame);
+ if (f != null) {
+ if (f.isSearching()) {
+ mActionBar.hide();
+ } else {
+ hideActionBarDelayed();
+ }
+ mActionBar.setTitle("");
+ } else {
+ mActionBar.setTitle(getTitle());
+ }
+ supportInvalidateOptionsMenu();
+
+ }
+
+ @Override
+ public void onDrawerOpened(View drawerView) {
+ stopHideActionBarDelayed();
+ if (!mActionBar.isShowing()) {
+ mActionBar.show();
+ }
+ mActionBar.setTitle(R.string.recent_file);
+ supportInvalidateOptionsMenu();
+ }
+
+ };
+ mDrawerLayout.setDrawerListener(mDrawerToggle);
+
+ final Intent intent = getIntent();
+ final String action = intent.getAction();
+ final String type = intent.getType();
+ if (Intent.ACTION_VIEW.equals(action) && type != null) {
+ if (type.startsWith("text/")) {
+ handleTextFile(intent.getData());
+ }
+ }
+
+ final Button buttonBrowse = (Button) findViewById(R.id.buttonBrowse);
+ buttonBrowse.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ browseFile();
+ }
+ });
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ menu.findItem(R.id.menu_main_clear_recent).setEnabled(!mDrawerAdapter.isEmpty());
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (mDrawerToggle.onOptionsItemSelected(item)) {
+ return true;
+ }
+ switch (item.getItemId()) {
+ case R.id.menu_main_open:
+ browseFile();
+ return true;
+ case R.id.menu_main_clear_recent:
+ clearRecentFiles();
+ return true;
+ case R.id.menu_main_config:
+ startActivity(new Intent(this, ConfigActivity.class));
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ mDrawerToggle.onConfigurationChanged(newConfig);
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ mDrawerToggle.syncState();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == BROWSE_FILE_REQUEST_CODE) {
+ if (resultCode == Activity.RESULT_OK) {
+ final Uri uri = data.getData();
+ final String intentType = data.getType();
+ final String mimeType = getContentResolver().getType(uri);
+ final String extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString());
+ Log.d(TAG, "File type: " + intentType + "::" + extension + "::" + mimeType);
+ if ((intentType != null && intentType.startsWith("text/")) ||
+ (mimeType != null && mimeType.startsWith("text/")) ||
+ (extension != null && extension.equals("txt"))) {
+ final ViewerFragment f = ViewerFragment.newInstance(uri.toString());
+ getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, f)
+ .commit();
+ // Save recent file
+ saveRecentFiles(uri);
+ hideActionBarDelayed();
+ Log.d(TAG, "Opening file: " + uri.toString());
+ } else {
+ Toast.makeText(this, "Unsupported file type", Toast.LENGTH_LONG).show();
+ }
+
+ }
+ }
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean scrollerEnabled = pref.getBoolean(ConfigKey.SCROLL_BY_VOLUME_KEYS, false);
+
+ if (scrollerEnabled) {
+ int divisor = Integer.parseInt(pref.getString(ConfigKey.SCROLL_LINES, "2"));
+
+ int action = event.getAction();
+ int keyCode = event.getKeyCode();
+ final FragmentManager fm = getSupportFragmentManager();
+ final ViewerFragment f = (ViewerFragment) fm.findFragmentById(R.id.content_frame);
+ if (f != null) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ if (action == KeyEvent.ACTION_DOWN) {
+ f.onVolumeKeyUp(divisor);
+ }
+ return true;
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ if (action == KeyEvent.ACTION_DOWN) {
+ f.onVolumeKeyDown(divisor);
+ }
+ return true;
+ }
+ }
+ }
+ return super.dispatchKeyEvent(event);
+ }
+
+ void browseFile() {
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("text/*");
+ if (intent.resolveActivity(getPackageManager()) != null) {
+ startActivityForResult(intent, BROWSE_FILE_REQUEST_CODE);
+ } else {
+ Toast.makeText(this, "Sorry, there's no file browser available", Toast.LENGTH_LONG)
+ .show();
+ }
+ }
+
+ void handleTextFile(Uri uri) {
+ final ViewerFragment f = ViewerFragment.newInstance(uri.toString());
+ getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, f).commit();
+ // Save recent file
+ saveRecentFiles(uri);
+ Log.d(TAG, "Viewing file: " + uri.getLastPathSegment());
+ hideActionBarDelayed();
+ }
+
+ void saveRecentFiles(Uri uri) {
+ mStackRecentFiles.pushRecentFile(new RecentFile(uri.getLastPathSegment(), uri.toString()));
+ mDrawerAdapter.notifyDataSetChanged();
+ SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
+ Editor editor = pref.edit();
+ try {
+ editor.putString(ConfigKey.RECENT_FILES, ObjectSerializer.serialize(mStackRecentFiles));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ editor.commit();
+ }
+
+ void clearRecentFiles() {
+ mStackRecentFiles.clear();
+ mDrawerAdapter.notifyDataSetChanged();
+ SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
+ pref.edit().putString(ConfigKey.RECENT_FILES, "").commit();
+ supportInvalidateOptionsMenu();
+ }
+
+ void hideActionBarDelayed() {
+ mHandler.postDelayed(mHideActionBarDelayed, 5000);
+ }
+
+ void stopHideActionBarDelayed() {
+ mHandler.removeCallbacks(mHideActionBarDelayed);
+ }
+
+ boolean isDrawerOpen() {
+ return mDrawerLayout.isDrawerOpen(mDrawerList);
+ }
+
+ private class DrawerItemClickListener implements ListView.OnItemClickListener {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ final String uriString = ((RecentFile) mDrawerAdapter.getItem(position)).getUri();
+ Log.d(TAG, "Re-opening file: " + uriString);
+ final ViewerFragment f = ViewerFragment.newInstance(uriString);
+ getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, f)
+ .commit();
+ mDrawerLayout.closeDrawer(mDrawerList);
+ // Save recent file
+ saveRecentFiles(Uri.parse(uriString));
+ }
+ }
+
+ @Override
+ public void onContentTap() {
+ if (!mActionBar.isShowing()) {
+ mActionBar.show();
+ hideActionBarDelayed();
+ }
+ }
+}
diff --git a/src/com/gmail/altakey/dawne/RecentFilesAdapter.java b/src/com/gmail/altakey/dawne/RecentFilesAdapter.java
new file mode 100644
index 0000000..bacb56b
--- /dev/null
+++ b/src/com/gmail/altakey/dawne/RecentFilesAdapter.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright (C) 2013 Takahiro Yoshimura, Renjaya Raga Zenta
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.gmail.altakey.dawne;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import com.gmail.altakey.dawne.util.StackRecentFiles;
+
+public class RecentFilesAdapter extends BaseAdapter {
+
+ private StackRecentFiles mStack;
+ private LayoutInflater mInflater;
+
+ public RecentFilesAdapter(Context context, StackRecentFiles stack) {
+ mStack = stack;
+ mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ @Override
+ public int getCount() {
+ return mStack.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mStack.getRecentFileAt(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View view = convertView;
+ ViewHolder holder;
+ if (view == null) {
+ view = mInflater.inflate(R.layout.drawer_list_item, parent, false);
+ holder = new ViewHolder();
+ holder.text = (TextView) view.findViewById(android.R.id.text1);
+ view.setTag(holder);
+ } else {
+ holder = (ViewHolder) view.getTag();
+ }
+ holder.text.setText(mStack.getRecentFileAt(position).getFileName());
+ return view;
+ }
+
+ static class ViewHolder {
+ TextView text;
+ }
+
+}
diff --git a/src/com/gmail/altakey/dawne/ViewActivity.java b/src/com/gmail/altakey/dawne/ViewActivity.java
deleted file mode 100644
index a609ec0..0000000
--- a/src/com/gmail/altakey/dawne/ViewActivity.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * Copyright (C) 2011-2012 Takahiro Yoshimura
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package com.gmail.altakey.dawne;
-
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Bundle;
-import android.preference.PreferenceManager;
-import android.text.Selection;
-import android.text.Spannable;
-import android.view.KeyEvent;
-import android.widget.EditText;
-import android.widget.ScrollView;
-
-public class ViewActivity extends MainActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- SharedPreferences pref = PreferenceManager
- .getDefaultSharedPreferences(this);
-
- final TextLoaderParam param = new TextLoaderParam();
- param.context = getApplicationContext();
- param.uri = getIntent().getData();
- param.charset = pref
- .getString(ConfigKey.CHARSET_PREFERENCE, "japanese");
- new LoadTextTask().execute(param);
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- SharedPreferences pref = PreferenceManager
- .getDefaultSharedPreferences(this);
- boolean scrollerEnabled = pref.getBoolean(
- ConfigKey.SCROLL_BY_VOLUME_KEYS, false);
-
- if (scrollerEnabled) {
- int divisor = Integer.parseInt(pref.getString(
- ConfigKey.SCROLL_LINES, "2"));
-
- int action = event.getAction();
- int keyCode = event.getKeyCode();
-
- final TextPager textPager = TextPager.create(this.textView,
- (ScrollView) this.rootView, divisor);
- switch (keyCode) {
- case KeyEvent.KEYCODE_VOLUME_UP:
- if (action == KeyEvent.ACTION_DOWN)
- textPager.up();
- return true;
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- if (action == KeyEvent.ACTION_DOWN)
- textPager.down();
- return true;
- }
- }
-
- return super.dispatchKeyEvent(event);
- }
-
- private class LoadTextTask extends AsyncTask {
-
- ProgressDialog progressDialog;
-
- @Override
- protected void onPreExecute() {
- ViewActivity.this.textView.setText("");
- progressDialog = ProgressDialog.show(ViewActivity.this, "",
- "Loading ...", true);
- }
-
- @Override
- protected String doInBackground(TextLoaderParam... params) {
- final TextLoaderParam param = params[0];
- return TextLoader.create(param.context, param.uri, param.charset)
- .read();
- }
-
- @Override
- protected void onPostExecute(String result) {
- ViewActivity.this.textView.setText(result);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- Selection.setSelection(
- (Spannable) ViewActivity.this.textView.getText(),
- selectionStart, selectionEnd);
- } else {
- ((EditText) ViewActivity.this.textView).setSelection(
- ViewActivity.this.selectionStart,
- ViewActivity.this.selectionEnd);
- }
- progressDialog.dismiss();
- }
-
- }
-
- static class TextLoaderParam {
- Context context;
- Uri uri;
- String charset;
- }
-}
diff --git a/src/com/gmail/altakey/dawne/MainActivity.java b/src/com/gmail/altakey/dawne/ViewerFragment.java
similarity index 58%
rename from src/com/gmail/altakey/dawne/MainActivity.java
rename to src/com/gmail/altakey/dawne/ViewerFragment.java
index d2d8949..55ac6e9 100644
--- a/src/com/gmail/altakey/dawne/MainActivity.java
+++ b/src/com/gmail/altakey/dawne/ViewerFragment.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2011-2012 Takahiro Yoshimura
+ * Copyright (C) 2011-2013 Takahiro Yoshimura, Renjaya Raga Zenta
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,38 +18,51 @@
package com.gmail.altakey.dawne;
import android.annotation.SuppressLint;
-import android.app.ActionBar;
import android.app.Activity;
+import android.app.ProgressDialog;
import android.content.Context;
-import android.content.Intent;
import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
+import android.support.v4.app.Fragment;
+import android.support.v7.app.ActionBarActivity;
import android.text.Selection;
import android.text.Spannable;
+import android.util.Log;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
-import android.view.Window;
+import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageButton;
+import android.widget.ScrollView;
import android.widget.TextView;
-public class MainActivity extends Activity {
- protected View rootView;
- protected TextView textView;
- protected View searchBar;
- protected EditText searchField;
- protected int selectionStart;
- protected int selectionEnd;
- private boolean titleHidden;
+import com.gmail.altakey.dawne.util.ConfigKey;
+import com.gmail.altakey.dawne.util.TextLoader;
+import com.gmail.altakey.dawne.util.TextPager;
+import com.gmail.altakey.dawne.util.TextStyler;
- private String currentCharsetpreference;
+public class ViewerFragment extends Fragment {
+
+ private View scrollView;
+ private TextView textView;
+ private View searchBar;
+ private EditText searchField;
+ private int selectionStart;
+ private int selectionEnd;
+ private Uri mUri;
+ private OnContentTapListener mCallback;
+ private boolean isSearching = false;
+ private String currentCharsetPreference;
private final View.OnClickListener cancelButtonListener = new View.OnClickListener() {
@@ -72,11 +85,25 @@ public void onClick(View v) {
searchNext();
}
};
+ private final View.OnTouchListener contentTouchListener = new View.OnTouchListener() {
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (!isSearching) {
+ mCallback.onContentTap();
+ }
+ // call super listener (for selecting text)
+ return false;
+ }
+ };
private final View.OnTouchListener dummyTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
- // do nothing
+ if (!isSearching) {
+ mCallback.onContentTap();
+ }
+ // ignore super listener
return true;
}
};
@@ -113,166 +140,179 @@ public boolean onKey(View v, int keyCode, KeyEvent event) {
}
};
- /** Called when the activity is first created. */
- @SuppressLint("NewApi")
+ public ViewerFragment() {
+ }
+
+ public static ViewerFragment newInstance(String uriString) {
+ final ViewerFragment f = new ViewerFragment();
+ final Bundle args = new Bundle(1);
+ args.putString("uri", uriString);
+ f.setArguments(args);
+ return f;
+ }
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- this.setupWindow();
+ mUri = getArguments() != null ? Uri.parse(getArguments().getString("uri")) : null;
+ setHasOptionsMenu(true);
+ }
- setContentView(R.layout.main);
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ mCallback = (OnContentTapListener) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString()
+ + " must implement OnContentClickListener");
+ }
+ }
- this.rootView = findViewById(R.id.view);
+ @SuppressLint("NewApi")
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ final View rootView = inflater.inflate(R.layout.viewer, container, false);
+ scrollView = rootView.findViewById(R.id.view);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// In Honeycomb or above, we can set TextView to be selectable
- this.textView = (TextView) findViewById(R.id.textview);
- this.textView.setTextIsSelectable(true);
+ textView = (TextView) rootView.findViewById(R.id.textview);
+ textView.setTextIsSelectable(true);
+ textView.setOnTouchListener(contentTouchListener);
} else {
// Below Honeycomb we need EditText class
- this.textView = (EditText) findViewById(R.id.textview);
+ textView = (EditText) rootView.findViewById(R.id.textview);
// this is needed to make EditText behaves like simple TextView
// so the soft keyboard won't appear if user touches the text
- this.textView.setOnTouchListener(dummyTouchListener);
+ textView.setOnTouchListener(dummyTouchListener);
// this is needed to make EditText won't be changed if user tries
// to edit the text with physical keyboard
- this.textView.setOnKeyListener(dummyKeyListener);
+ textView.setOnKeyListener(dummyKeyListener);
}
- this.textView.setSaveEnabled(false);
+ textView.setSaveEnabled(false);
+ searchBar = rootView.findViewById(R.id.search);
+ searchField = (EditText) rootView.findViewById(R.id.edittext);
+ searchField.setOnKeyListener(searchKeyListener);
- this.searchBar = findViewById(R.id.search);
- this.searchField = (EditText) findViewById(R.id.edittext);
- this.searchField.setOnKeyListener(searchKeyListener);
-
- ImageButton cancelButton = (ImageButton) findViewById(R.id.cancel);
+ ImageButton cancelButton = (ImageButton) rootView.findViewById(R.id.cancel);
cancelButton.setOnClickListener(cancelButtonListener);
- ImageButton prevButton = (ImageButton) findViewById(R.id.previous);
+ ImageButton prevButton = (ImageButton) rootView.findViewById(R.id.previous);
prevButton.setOnClickListener(prevButtonListener);
- ImageButton nextButton = (ImageButton) findViewById(R.id.next);
+ ImageButton nextButton = (ImageButton) rootView.findViewById(R.id.next);
nextButton.setOnClickListener(nextButtonListener);
- this.restyle();
+ return rootView;
}
- @SuppressLint("InlinedApi")
- protected void setupWindow() {
- SharedPreferences pref = PreferenceManager
- .getDefaultSharedPreferences(this);
- boolean hideTitle = !pref.getBoolean(ConfigKey.SHOW_TITLE, true);
- String charsetpreference = pref.getString(ConfigKey.CHARSET_PREFERENCE,
- "all");
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- this.requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
- }
- if (hideTitle) {
- this.requestWindowFeature(Window.FEATURE_NO_TITLE);
- }
-
- this.titleHidden = hideTitle;
- this.currentCharsetpreference = charsetpreference;
- }
-
- private void restyle() {
- SharedPreferences pref = PreferenceManager
- .getDefaultSharedPreferences(this);
-
- String colortheme = pref.getString(ConfigKey.COLORTHEME, "black");
- int foreground = 0xffffffff;
- int background = 0xff000000;
-
- float fontsize = Float.parseFloat(pref.getString(ConfigKey.FONTSIZE,
- "14"));
- boolean useMonospaceFonts = pref.getBoolean(
- ConfigKey.USE_MONOSPACE_FONTS, false);
-
- if (colortheme.equals("white")) {
- foreground = 0xff000000;
- background = 0xffffffff;
- }
-
- TextStyler.create(this.rootView, this.textView, background, foreground,
- fontsize, useMonospaceFonts ? "monospace" : "default").style();
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- if (titleHidden) {
- rootView.setPadding(0, 0, 0, 0);
- }
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ String charsetPreference = pref.getString(ConfigKey.CHARSET_PREFERENCE, "all");
+ currentCharsetPreference = charsetPreference;
+ if (savedInstanceState != null) {
+ selectionStart = savedInstanceState.getInt("selectionStart", 0);
+ selectionEnd = savedInstanceState.getInt("selectionEnd", 0);
}
+ ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle("");
+ loadText(charsetPreference);
}
@Override
public void onResume() {
super.onResume();
-
- SharedPreferences pref = PreferenceManager
- .getDefaultSharedPreferences(this);
- boolean hideTitle = !pref.getBoolean(ConfigKey.SHOW_TITLE, true);
- String charsetpreference = pref.getString(ConfigKey.CHARSET_PREFERENCE,
- "all");
-
- if (this.titleHidden != hideTitle
- || this.currentCharsetpreference != charsetpreference) {
- this.restart();
- return;
+ SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ String charsetPreference = pref.getString(ConfigKey.CHARSET_PREFERENCE, "all");
+ if (!currentCharsetPreference.equals(charsetPreference)) {
+ loadText(charsetPreference);
+ currentCharsetPreference = charsetPreference;
}
-
- this.restyle();
+ ((NewMainActivity) getActivity()).hideActionBarDelayed();
+ restyle();
}
@Override
- protected void onSaveInstanceState(Bundle outState) {
+ public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("selectionStart", selectionStart);
outState.putInt("selectionEnd", selectionEnd);
}
@Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- if (savedInstanceState != null) {
- selectionStart = savedInstanceState.getInt("selectionStart", 0);
- selectionEnd = savedInstanceState.getInt("selectionEnd", 0);
- }
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.viewer, menu);
+ super.onCreateOptionsMenu(menu, inflater);
}
- private void restart() {
- Intent intent = getIntent();
- finish();
- startActivity(intent);
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_viewer_search:
+ showSearchBar(true);
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.main, menu);
- return true;
+ public void onPrepareOptionsMenu(Menu menu) {
+ menu.findItem(R.id.menu_viewer_search).setVisible(
+ !((NewMainActivity) getActivity()).isDrawerOpen());
+ super.onPrepareOptionsMenu(menu);
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_main_search:
- showSearchBar(true);
- break;
- case R.id.menu_main_config:
- startActivity(new Intent(this, ConfigActivity.class));
- break;
+ private void loadText(String charsetPreference) {
+ final TextLoaderParam param = new TextLoaderParam();
+ param.context = getActivity().getApplicationContext();
+ param.uri = mUri;
+ param.charset = charsetPreference;
+ new LoadTextTask().execute(param);
+ }
+
+ private void restyle() {
+ if (getActivity() == null) {
+ Log.d("dawne.Viewer", "Activity null :(");
+ return;
}
- return true;
+ SharedPreferences pref = PreferenceManager
+ .getDefaultSharedPreferences(getActivity());
+
+ String colortheme = pref.getString(ConfigKey.COLORTHEME, "black");
+ int foreground = 0xffffffff;
+ int background = 0xff000000;
+
+ float fontsize = Float.parseFloat(pref.getString(ConfigKey.FONTSIZE,
+ "14"));
+ boolean useMonospaceFonts = pref.getBoolean(
+ ConfigKey.USE_MONOSPACE_FONTS, false);
+
+ if (colortheme.equals("white")) {
+ foreground = 0xff000000;
+ background = 0xffffffff;
+ } else if (colortheme.equals("solarized_dark")) {
+ foreground = 0xff839496;
+ background = 0xff002b36;
+ } else if (colortheme.equals("solarized_light")) {
+ foreground = 0xff657b83;
+ background = 0xfffdf6e3;
+ }
+
+ TextStyler.create(scrollView, textView, background, foreground,
+ fontsize, useMonospaceFonts ? "monospace" : "default").style();
}
void hideSoftKeyboard() {
- ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
+ ((InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(searchField.getWindowToken(), 0);
}
void showSoftKeyBoard() {
- ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
+ ((InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE))
.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
- @SuppressLint("NewApi")
void showSearchBar(boolean shown) {
+ isSearching = shown;
if (searchBar == null) {
throw new IllegalStateException();
}
@@ -280,26 +320,20 @@ void showSearchBar(boolean shown) {
searchBar.setVisibility(View.VISIBLE);
searchBar.requestFocus();
showSoftKeyBoard();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- if (!titleHidden) {
- final ActionBar actionBar = getActionBar();
- rootView.setPadding(0, 0, 0, 0);
- actionBar.hide();
- }
- }
+ ((ActionBarActivity) getActivity()).getSupportActionBar().hide();
} else {
hideSoftKeyboard();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- if (!titleHidden) {
- final ActionBar actionBar = getActionBar();
- rootView.setPadding(0, actionBar.getHeight(), 0, 0);
- actionBar.show();
- }
- }
+ ((ActionBarActivity) getActivity()).getSupportActionBar().show();
+ ((NewMainActivity) getActivity()).hideActionBarDelayed();
searchBar.setVisibility(View.GONE);
}
}
+ boolean isSearching() {
+ return isSearching;
+ }
+
+ @SuppressLint("DefaultLocale")
void searchNext() {
final String text = textView.getText().toString().toLowerCase();
final String search = searchField.getText().toString().toLowerCase();
@@ -353,6 +387,7 @@ void searchNext() {
}
+ @SuppressLint("DefaultLocale")
void searchPrevious() {
final String text = textView.getText().toString().toLowerCase();
final String search = searchField.getText().toString().toLowerCase();
@@ -402,4 +437,55 @@ void searchPrevious() {
hideSoftKeyboard();
}
}
+
+ private class LoadTextTask extends AsyncTask {
+
+ ProgressDialog progressDialog;
+
+ @Override
+ protected void onPreExecute() {
+ textView.setText("");
+ progressDialog = ProgressDialog.show(getActivity(), "",
+ "Loading ...", true);
+ }
+
+ @Override
+ protected String doInBackground(TextLoaderParam... params) {
+ final TextLoaderParam param = params[0];
+ return TextLoader.create(param.context, param.uri, param.charset)
+ .read();
+ }
+
+ @Override
+ protected void onPostExecute(String result) {
+ restyle();
+ textView.setText(result);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ Selection.setSelection(
+ (Spannable) textView.getText(), selectionStart, selectionEnd);
+ } else {
+ ((EditText) textView).setSelection(selectionStart, selectionEnd);
+ }
+ progressDialog.dismiss();
+ }
+
+ }
+
+ static class TextLoaderParam {
+ Context context;
+ Uri uri;
+ String charset;
+ }
+
+ public void onVolumeKeyUp(int divisor) {
+ (TextPager.create(textView, (ScrollView) scrollView, divisor)).up();
+ }
+
+ public void onVolumeKeyDown(int divisor) {
+ (TextPager.create(textView, (ScrollView) scrollView, divisor)).down();
+ }
+
+ public interface OnContentTapListener {
+ public void onContentTap();
+ }
}
diff --git a/src/com/gmail/altakey/dawne/CharsetDetector.java b/src/com/gmail/altakey/dawne/util/CharsetDetector.java
similarity index 98%
rename from src/com/gmail/altakey/dawne/CharsetDetector.java
rename to src/com/gmail/altakey/dawne/util/CharsetDetector.java
index f072c44..15ca58b 100644
--- a/src/com/gmail/altakey/dawne/CharsetDetector.java
+++ b/src/com/gmail/altakey/dawne/util/CharsetDetector.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2011-2012 Takahiro Yoshimura
+ * Copyright (C) 2011-2013 Takahiro Yoshimura
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.gmail.altakey.dawne;
+package com.gmail.altakey.dawne.util;
import java.util.Arrays;
import java.util.List;
diff --git a/src/com/gmail/altakey/dawne/ConfigKey.java b/src/com/gmail/altakey/dawne/util/ConfigKey.java
similarity index 88%
rename from src/com/gmail/altakey/dawne/ConfigKey.java
rename to src/com/gmail/altakey/dawne/util/ConfigKey.java
index fdcc2e3..33a9f27 100644
--- a/src/com/gmail/altakey/dawne/ConfigKey.java
+++ b/src/com/gmail/altakey/dawne/util/ConfigKey.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2011-2012 Takahiro Yoshimura
+ * Copyright (C) 2011-2013 Takahiro Yoshimura
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.gmail.altakey.dawne;
+package com.gmail.altakey.dawne.util;
public class ConfigKey {
public static final String COLORTHEME = "colortheme";
@@ -23,6 +23,6 @@ public class ConfigKey {
public static final String USE_MONOSPACE_FONTS = "usemonospacefonts";
public static final String SCROLL_BY_VOLUME_KEYS = "scrollbyvolumekeys";
public static final String SCROLL_LINES = "scrolllines";
- public static final String SHOW_TITLE = "showtitle";
public static final String CHARSET_PREFERENCE = "charsetpreference";
+ public static final String RECENT_FILES = "recentfiles";
}
diff --git a/src/com/gmail/altakey/dawne/util/ObjectSerializer.java b/src/com/gmail/altakey/dawne/util/ObjectSerializer.java
new file mode 100644
index 0000000..e19ab81
--- /dev/null
+++ b/src/com/gmail/altakey/dawne/util/ObjectSerializer.java
@@ -0,0 +1,83 @@
+/**
+ * Copyright (C) 2013 Takahiro Yoshimura, Renjaya Raga Zenta
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.gmail.altakey.dawne.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+public class ObjectSerializer {
+ public static String serialize(Serializable obj) throws IOException {
+ if (obj == null) {
+ return "";
+ }
+ try {
+ ByteArrayOutputStream serialObj = new ByteArrayOutputStream();
+ ObjectOutputStream objStream = new ObjectOutputStream(serialObj);
+ objStream.writeObject(obj);
+ objStream.close();
+ return encodeBytes(serialObj.toByteArray());
+ } catch (Exception e) {
+ throw new IOException("Serialization error: " + e.getMessage());
+ }
+
+ }
+
+ public static Object deserialize(String str) throws IOException {
+ if (str == null || str.length() == 0) {
+ return null;
+ }
+ try {
+ ByteArrayInputStream serialObj = new ByteArrayInputStream(decodeBytes(str));
+ ObjectInputStream objStream = new ObjectInputStream(serialObj);
+ return objStream.readObject();
+ } catch (Exception e) {
+ throw new IOException("Deserialization error: " + e.getMessage());
+ }
+
+ }
+
+ public static String encodeBytes(byte[] bytes) {
+ final StringBuffer strBuf = new StringBuffer();
+
+ final int length = bytes.length;
+ for (int i = 0; i < length; i++) {
+ strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ((int) 'a')));
+ strBuf.append((char) (((bytes[i]) & 0xF) + ((int) 'a')));
+ }
+
+ return strBuf.toString();
+ }
+
+ public static byte[] decodeBytes(String str) {
+ final byte[] bytes = new byte[str.length() / 2];
+ final int length = str.length();
+ for (int i = 0; i < length; i += 2) {
+ char c = str.charAt(i);
+ bytes[i / 2] = (byte) ((c - 'a') << 4);
+ c = str.charAt(i + 1);
+ bytes[i / 2] += (c - 'a');
+ }
+ return bytes;
+
+ }
+
+}
diff --git a/src/com/gmail/altakey/dawne/util/RecentFile.java b/src/com/gmail/altakey/dawne/util/RecentFile.java
new file mode 100644
index 0000000..74f25ea
--- /dev/null
+++ b/src/com/gmail/altakey/dawne/util/RecentFile.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 2013 Takahiro Yoshimura, Renjaya Raga Zenta
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.gmail.altakey.dawne.util;
+
+import java.io.Serializable;
+
+public class RecentFile implements Serializable {
+
+ private String fileName;
+ private String uri;
+ private static final long serialVersionUID = 7359036288102114071L;
+
+ public RecentFile(String fileName, String uri) {
+ this.setFileName(fileName);
+ this.setUri(uri);
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+}
diff --git a/src/com/gmail/altakey/dawne/util/StackRecentFiles.java b/src/com/gmail/altakey/dawne/util/StackRecentFiles.java
new file mode 100644
index 0000000..df3c150
--- /dev/null
+++ b/src/com/gmail/altakey/dawne/util/StackRecentFiles.java
@@ -0,0 +1,99 @@
+/**
+ * Copyright (C) 2013 Takahiro Yoshimura, Renjaya Raga Zenta
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.gmail.altakey.dawne.util;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+public class StackRecentFiles implements Serializable {
+
+ public static final int MAX_CAPACITY = 10;
+ private ArrayList stack;
+ private int top;
+ private static final long serialVersionUID = 7977738208421002767L;
+
+ public StackRecentFiles() {
+ this.stack = new ArrayList(MAX_CAPACITY);
+ this.top = -1;
+ }
+
+ public void pushRecentFile(RecentFile recentFile) {
+ final int index = indexOf(recentFile);
+ if (index == -1) {
+ if (top >= MAX_CAPACITY - 1) {
+ shiftElementToBottom();
+ stack.set(top, recentFile);
+ } else {
+ stack.add(++top, recentFile);
+ }
+ } else {
+ shiftElementToBottom(index);
+ }
+ }
+
+ public RecentFile getRecentFile() {
+ if (top < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ return stack.get(top);
+ }
+
+ public RecentFile getRecentFileAt(int position) {
+ final int size = stack.size();
+ if (position < 0 || position >= size) {
+ throw new IndexOutOfBoundsException();
+ }
+ return stack.get(size - position - 1);
+ }
+
+ public int size() {
+ return stack.size();
+ }
+
+ public void clear() {
+ stack.clear();
+ top = -1;
+ }
+
+ private int indexOf(RecentFile recentFile) {
+ final int size = stack.size();
+ for (int i = 0; i < size; i++) {
+ final RecentFile rf = stack.get(i);
+ if (recentFile.getFileName().equals(rf.getFileName())) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ // Only called if stack is full!
+ private void shiftElementToBottom() {
+ for (int i = 0; i < top; i++) {
+ stack.set(i, stack.get(i + 1));
+ }
+ stack.set(top, null);
+ }
+
+ private void shiftElementToBottom(int index) {
+ final RecentFile rotated = stack.get(index);
+ for (int i = index; i < top; i++) {
+ stack.set(i, stack.get(i + 1));
+ }
+ stack.set(top, rotated);
+ }
+}
diff --git a/src/com/gmail/altakey/dawne/TextLoader.java b/src/com/gmail/altakey/dawne/util/TextLoader.java
similarity index 95%
rename from src/com/gmail/altakey/dawne/TextLoader.java
rename to src/com/gmail/altakey/dawne/util/TextLoader.java
index 9727fa4..f04455b 100644
--- a/src/com/gmail/altakey/dawne/TextLoader.java
+++ b/src/com/gmail/altakey/dawne/util/TextLoader.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2011-2012 Takahiro Yoshimura
+ * Copyright (C) 2011-2013 Takahiro Yoshimura
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.gmail.altakey.dawne;
+package com.gmail.altakey.dawne.util;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
diff --git a/src/com/gmail/altakey/dawne/TextPager.java b/src/com/gmail/altakey/dawne/util/TextPager.java
similarity index 94%
rename from src/com/gmail/altakey/dawne/TextPager.java
rename to src/com/gmail/altakey/dawne/util/TextPager.java
index 1fdaee4..9faacdd 100644
--- a/src/com/gmail/altakey/dawne/TextPager.java
+++ b/src/com/gmail/altakey/dawne/util/TextPager.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2011-2012 Takahiro Yoshimura
+ * Copyright (C) 2011-2013 Takahiro Yoshimura
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.gmail.altakey.dawne;
+package com.gmail.altakey.dawne.util;
import android.widget.ScrollView;
import android.widget.TextView;
diff --git a/src/com/gmail/altakey/dawne/TextStyler.java b/src/com/gmail/altakey/dawne/util/TextStyler.java
similarity index 96%
rename from src/com/gmail/altakey/dawne/TextStyler.java
rename to src/com/gmail/altakey/dawne/util/TextStyler.java
index be0691f..dc07b62 100644
--- a/src/com/gmail/altakey/dawne/TextStyler.java
+++ b/src/com/gmail/altakey/dawne/util/TextStyler.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2011-2012 Takahiro Yoshimura
+ * Copyright (C) 2011-2013 Takahiro Yoshimura
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package com.gmail.altakey.dawne;
+package com.gmail.altakey.dawne.util;
import android.graphics.Typeface;
import android.util.TypedValue;